import type { FeatureToggles } from '@grafana/data';
import { t } from '@grafana/i18n';
import { config } from '@grafana/runtime';
import { ComboboxOption } from '@grafana/ui';
import { useAppNotification } from 'app/core/copy/appNotification';
import {
  AlertEnrichment,
  AlertEnrichmentSpec,
  CreateAlertEnrichmentApiArg,
  ReplaceAlertEnrichmentApiArg,
  EnricherConfig,
  Matcher,
  Step,
  generatedAPI,
} from 'app/extensions/api/clients/alertenrichment/v1beta1/endpoints.gen';
import { logError } from 'app/features/alerting/unified/Analytics';
import { stringifyErrorLike } from 'app/features/alerting/unified/utils/misc';

import { trackEnrichmentFormError, trackEnrichmentSaved } from '../analytics/Analytics';
import { getEnrichmentTrackingPropsFromFormData } from '../analytics/utils';

export type EnrichmentScope = 'global' | 'label' | 'annotation';
export type EnrichmentCreationOrigin = 'ruleDrawer' | 'enrichmentForm' | 'enrichmentContent';

export interface AlertEnrichmentFormData {
  title: string;
  description?: string;
  steps: Step[];
  scope: EnrichmentScope;
  labelMatchers?: Matcher[];
  annotationMatchers?: Matcher[];
  alertRuleUids?: string[];
}

export type EnrichmentType = EnricherConfig['type'];

export const DEFAULT_ENRICHMENT_TIMEOUT = '30s';
export const ENRICHMENT_NAME_PREFIX = 'enrichment-';

/**
 * Creates an AlertEnrichment object from form data for creation
 * @param formData - The form data to convert
 * @returns AlertEnrichment object ready for API creation
 */
export function createAlertEnrichmentFromFormData(formData: AlertEnrichmentFormData): AlertEnrichment {
  return {
    metadata: { generateName: ENRICHMENT_NAME_PREFIX },
    spec: formDataToEnrichmentSpec(formData),
  };
}

/**
 * Custom hook for handling enrichment creation with built-in tracking
 * @param origin - The origin of the creation ('ruleDrawer' | 'enrichmentForm')
 * @param onSuccess - Optional callback to execute on successful creation
 * @param onError - Optional callback to execute on error (if not provided, uses default error handling)
 * @returns Object with createEnrichment function and loading state
 */
export function useEnrichmentCreation(
  origin: EnrichmentCreationOrigin,
  onSuccess?: () => void,
  onError?: (err: any) => void
) {
  const [createAlertEnrichment, { isLoading }] = generatedAPI.useCreateAlertEnrichmentMutation();
  const notifyApp = useAppNotification();

  const createEnrichment = async (formData: AlertEnrichmentFormData): Promise<void> => {
    const alertEnrichment = createAlertEnrichmentFromFormData(formData);
    const apiArg: CreateAlertEnrichmentApiArg = { alertEnrichment };

    // Get tracking props for analytics
    const trackingProps = getEnrichmentTrackingPropsFromFormData(formData, 'create');

    try {
      await createAlertEnrichment(apiArg).unwrap();
      notifyApp.success(t('alert-enrichment.success', 'Alert enrichment created successfully!'));

      // Track successful creation with origin
      trackEnrichmentSaved({
        ...trackingProps,
        origin,
      });

      onSuccess?.();
    } catch (err) {
      // Track creation error with origin
      trackEnrichmentFormError({
        form_action: 'create',
        error_field: stringifyErrorLike(err),
        origin,
      });

      if (onError) {
        onError(err);
      } else {
        logError(new Error('Failed to create alert enrichment'));
        notifyApp.error(t('alert-enrichment.error', 'Failed to create alert enrichment'), stringifyErrorLike(err));
      }
    }
  };

  return {
    createEnrichment,
    isLoading,
  };
}

/**
 * Custom hook for handling enrichment updates with built-in tracking
 * @param origin - The origin of the update ('ruleDrawer' | 'enrichmentForm')
 * @param onSuccess - Optional callback to execute on successful update
 * @param onError - Optional callback to execute on error (if not provided, uses default error handling)
 * @returns Object with updateEnrichment function and loading state
 */
export function useEnrichmentUpdate(
  origin: EnrichmentCreationOrigin,
  onSuccess?: () => void,
  onError?: (err: any) => void
) {
  const [replaceAlertEnrichment, { isLoading }] = generatedAPI.useReplaceAlertEnrichmentMutation();
  const notifyApp = useAppNotification();

  const updateEnrichment = async (enrichment: AlertEnrichment, formData: AlertEnrichmentFormData): Promise<void> => {
    if (!enrichment.metadata) {
      notifyApp.error(t('alert-enrichment.metadata-error', 'Invalid enrichment metadata'));
      return;
    }

    const updatedEnrichment: AlertEnrichment = {
      metadata: { name: enrichment.metadata.name },
      spec: formDataToEnrichmentSpec(formData),
    };

    const apiArg: ReplaceAlertEnrichmentApiArg = {
      name: enrichment.metadata.name || '',
      alertEnrichment: updatedEnrichment,
    };

    // Get tracking props for analytics
    const trackingProps = getEnrichmentTrackingPropsFromFormData(formData, 'update');

    try {
      await replaceAlertEnrichment(apiArg).unwrap();
      notifyApp.success(t('alert-enrichment.update-success', 'Alert enrichment updated successfully!'));

      // Track successful update with origin
      trackEnrichmentSaved({
        ...trackingProps,
        origin,
      });

      onSuccess?.();
    } catch (err) {
      // Track update error with origin
      trackEnrichmentFormError({
        form_action: 'update',
        error_field: stringifyErrorLike(err),
        origin,
      });

      if (onError) {
        onError(err);
      } else {
        logError(new Error('Failed to update alert enrichment'));
        notifyApp.error(
          t('alert-enrichment.update-error', 'Failed to update alert enrichment'),
          stringifyErrorLike(err)
        );
      }
    }
  };

  return {
    updateEnrichment,
    isLoading,
  };
}

export function getInitialFormData(enrichment?: AlertEnrichment): AlertEnrichmentFormData {
  const scope = enrichment?.spec ? determineScope(enrichment.spec) : 'global';

  return {
    scope,
    title: enrichment?.spec?.title || '',
    description: enrichment?.spec?.description || '',
    steps: [
      enrichment?.spec?.steps?.[0] || {
        timeout: DEFAULT_ENRICHMENT_TIMEOUT,
        type: 'enricher',
        enricher: { type: 'assign', assign: { annotations: [] } },
      },
    ],
    labelMatchers: enrichment?.spec?.labelMatchers || [],
    annotationMatchers: enrichment?.spec?.annotationMatchers || [],
    alertRuleUids: enrichment?.spec?.alertRuleUids || [],
  };
}

export function getMatcherTypeOptions() {
  return [
    { label: t('alert-enrichment-form.matcher-type.equals', 'Equals (=)'), value: '=' },
    { label: t('alert-enrichment-form.matcher-type.not-equals', 'Not Equals (!=)'), value: '!=' },
    { label: t('alert-enrichment-form.matcher-type.regex-match', 'Regex Match (=~)'), value: '=~' },
    { label: t('alert-enrichment-form.matcher-type.regex-not-match', 'Regex Not Match (!~)'), value: '!~' },
  ];
}

export function getEnricherTypeOptions(): Array<ComboboxOption<EnrichmentType>> {
  const options: Array<ComboboxOption<EnrichmentType>> = [
    {
      label: t('alert-enrichment-form.enricher-type.assign', 'Assign'),
      value: 'assign',
      description: t('alert-enrichment-form.enricher-type.assign-description', 'Add annotations to alerts'),
    },
    {
      label: t('alert-enrichment-form.enricher-type.external', 'External'),
      value: 'external',
      description: t(
        'alert-enrichment-form.enricher-type.external-description',
        'Call external webhook for enrichment'
      ),
    },
    {
      label: t('alert-enrichment-form.enricher-type.dsquery', 'Data Source Query'),
      value: 'dsquery',
      description: t(
        'alert-enrichment-form.enricher-type.dsquery-description',
        'Query data sources for additional context'
      ),
    },
    {
      label: t('alert-enrichment-form.enricher-type.asserts', 'Asserts'),
      value: 'asserts',
    },
    {
      label: t('alert-enrichment-form.enricher-type.sift', 'Sift'),
      value: 'sift',
      description: t('alert-enrichment-form.enricher-type.sift-description', 'Run Sift investigation'),
    },
    {
      label: t('alert-enrichment-form.enricher-type.explain', 'Explain'),
      value: 'explain',
      description: t(
        'alert-enrichment-form.enricher-type.explain-description',
        'Generate AI-powered explanations for alerts'
      ),
    },
  ];

  const toggleKey: keyof FeatureToggles = 'alertingEnrichmentAssistantInvestigations';
  if (config.featureToggles[toggleKey]) {
    options.push({
      label: t('alert-enrichment-form.enricher-type.assistant-investigations', 'Assistant Investigations'),
      value: 'assistant' as const,
      description: t(
        'alert-enrichment-form.enricher-type.assistant-description',
        'Start Assistant Investigation for alerts'
      ),
    });
  }

  return options;
}

export function getDsTypeOptions() {
  return [
    { label: t('alert-enrichment-form.ds-type.logs', 'Logs'), value: 'logs' },
    { label: t('alert-enrichment-form.ds-type.raw', 'Raw'), value: 'raw' },
  ];
}

/**
 * Determines the scope of the enrichment based on the presence of matchers
 */
function determineScope(enrichmentSpec: AlertEnrichmentSpec): EnrichmentScope {
  if (enrichmentSpec.labelMatchers && enrichmentSpec.labelMatchers.length > 0) {
    return 'label';
  }
  if (enrichmentSpec.annotationMatchers && enrichmentSpec.annotationMatchers.length > 0) {
    return 'annotation';
  }
  return 'global';
}

/**
 * Processes AlertEnrichmentFormData and cleans it based on scope settings.
 * When scope is 'global' (all alerts), both labelMatchers and annotationMatchers are cleared.
 */
export function formDataToEnrichmentSpec(formData: AlertEnrichmentFormData): AlertEnrichmentSpec {
  const scope = formData.scope;

  return {
    title: formData.title,
    description: formData.description,
    steps: formData.steps,
    // Only save matchers for selected scope
    labelMatchers: scope === 'label' ? formData.labelMatchers : undefined,
    annotationMatchers: scope === 'annotation' ? formData.annotationMatchers : undefined,
    alertRuleUids: formData.alertRuleUids,
  };
}

/**
 * Get the initial form data for a given enrichment type
 * @param enrichmentType
 * @returns AlertEnrichmentFormData
 */
export function getInitialFormDataForType(enrichmentType: EnrichmentType): AlertEnrichmentFormData {
  return {
    scope: 'global',
    title: '',
    description: '',
    steps: [
      {
        timeout: DEFAULT_ENRICHMENT_TIMEOUT,
        type: 'enricher',
        enricher: { type: enrichmentType },
      },
    ],
    labelMatchers: [],
    annotationMatchers: [],
  };
}
