/**
 * This file contains enhanced and type-narrowed versions of the types generated by the RTKQ codegen package.
 */
import { type MergeDeep, type MergeExclusive, type OverrideProperties } from 'type-fest';

import type {
  ListReceiverApiResponse,
  Receiver,
  ReceiverIntegration,
} from '@grafana/api-clients/rtkq/notifications.alerting/v1beta1';

type GenericIntegration = OverrideProperties<
  ReceiverIntegration,
  {
    settings: Record<string, unknown>;
  }
>;

// Based on https://github.com/grafana/alerting/blob/main/receivers/email/config.go#L20-L25
type EmailIntegration = OverrideProperties<
  GenericIntegration,
  {
    type: 'email';
    version: 'v1';
    settings: {
      singleEmail?: boolean;
      addresses: string;
      message?: string;
      subject?: string;
    };
    secureFields: never; // email doesn't have any secure fields
  }
>;

// Based on https://github.com/grafana/alerting/blob/main/receivers/slack/config.go
type SlackIntegration = OverrideProperties<
  GenericIntegration,
  {
    type: 'slack';
    version: 'v1';
    settings: {
      endpointUrl?: string;
      url?: string;
      recipient?: string;
      text?: string;
      title?: string;
      username?: string;
      icon_emoji?: string;
      icon_url?: string;
      mentionChannel?: string;
      mentionUsers?: string; // comma separated string
      mentionGroups?: string; // comma separated string
      color?: string;
    };
    // secureFields is a union type that can be either a token or a URL but you can't have both
    secureFields: MergeExclusive<{ token: string }, { url: string }>;
  }
>;

// Based on https://github.com/grafana/alerting/blob/main/receivers/oncall/config.go#L14-L27
type OnCallIntegration = OverrideProperties<
  GenericIntegration,
  {
    type: 'OnCall';
    version: 'v1';
    settings: {
      url: string;
      httpMethod?: 'POST' | 'PUT';
      maxAlerts?: number;
      authorization_scheme?: string;
      authorization_credentials?: string;
      username?: string;
      password?: string;
      title?: string;
      message?: string;
    };
  }
>;

export type Integration = EmailIntegration | SlackIntegration | OnCallIntegration | GenericIntegration;

// Enhanced version of ContactPoint with typed integrations
// ⚠️ MergeDeep does not check if the property you are overriding exists in the base type and there is no "DeepOverrideProperties" helper
export type ContactPoint = MergeDeep<
  Receiver,
  {
    metadata: {
      annotations: ContactPointMetadataAnnotations;
    };
    spec: {
      integrations: Integration[];
    };
  }
>;

export type ContactPointMetadataAnnotations = AlertingEntityMetadataAnnotations &
  Partial<{
    // reading secrets is unique to contact points / receivers
    'grafana.com/access/canReadSecrets': 'true' | 'false';
    'grafana.com/inUse/routes': `${number}`;
    'grafana.com/inUse/rules': `${number}`;
  }>;

export type AlertingEntityMetadataAnnotations = Partial<{
  'grafana.com/access/canAdmin': 'true' | 'false';
  'grafana.com/access/canDelete': 'true' | 'false';
  'grafana.com/access/canWrite': 'true' | 'false';
  'grafana.com/canUse': 'true' | 'false';
  // used for provisioning to identify what system created the entity
  'grafana.com/provenance': string;
}>;

export type EnhancedListReceiverApiResponse = OverrideProperties<
  ListReceiverApiResponse,
  {
    items: ContactPoint[];
  }
>;
