import { useEffect, useState } from 'react';
import { useNavigate, useParams, useSearchParams } from 'react-router';
import { Alert, Button, useToast } from '@cameleer/design-system';
import { PageLoader } from '../../../components/PageLoader';
import {
  useAlertRule,
  useCreateAlertRule,
  useUpdateAlertRule,
} from '../../../api/queries/alertRules';
import {
  initialForm,
  toRequest,
  validateStep,
  WIZARD_STEPS,
  type FormState,
  type WizardStep,
} from './form-state';
import { ScopeStep } from './ScopeStep';
import { ConditionStep } from './ConditionStep';
import { TriggerStep } from './TriggerStep';
import { NotifyStep } from './NotifyStep';
import { ReviewStep, computeSaveBlockReason } from './ReviewStep';
import { prefillFromPromotion, type PrefillWarning } from './promotion-prefill';
import { useCatalog } from '../../../api/queries/catalog';
import { useOutboundConnections } from '../../../api/queries/admin/outboundConnections';
import { useSelectedEnv } from '../../../api/queries/alertMeta';
import { describeApiError } from '../../../api/errors';
import sectionStyles from '../../../styles/section-card.module.css';
import css from './wizard.module.css';

const STEP_LABELS: Record<WizardStep, string> = {
  scope: '1. Scope',
  condition: '2. Condition',
  trigger: '3. Trigger',
  notify: '4. Notify',
  review: '5. Review',
};

export default function RuleEditorWizard() {
  const navigate = useNavigate();
  const { id } = useParams<{ id?: string }>();
  const [search] = useSearchParams();
  const { toast } = useToast();

  const isEdit = !!id;
  const existingQuery = useAlertRule(isEdit ? id : undefined);

  // Promotion prefill uses a separate query against the source env. In
  // Plan 03 we reuse `useAlertRule` (current-env scoped); cross-env
  // fetching is handled server-side in the promote query hook when wired.
  const promoteFrom = search.get('promoteFrom') ?? undefined;
  const promoteRuleId = search.get('ruleId') ?? undefined;
  const sourceRuleQuery = useAlertRule(promoteFrom ? promoteRuleId : undefined);

  // Target-env data for promotion warnings.
  const env = useSelectedEnv();
  const targetEnv = search.get('targetEnv') ?? env;
  const { data: targetCatalog } = useCatalog(targetEnv ?? undefined);
  const { data: connections } = useOutboundConnections();

  const targetAppSlugs = (targetCatalog ?? []).map((a) => a.slug);
  const targetAllowedConnIds = (connections ?? [])
    .filter((c) => c.allowedEnvironmentIds.length === 0 || (!!targetEnv && c.allowedEnvironmentIds.includes(targetEnv)))
    .map((c) => c.id);

  const [step, setStep] = useState<WizardStep>('scope');
  const [form, setForm] = useState<FormState | null>(null);
  const [warnings, setWarnings] = useState<PrefillWarning[]>([]);

  // Initialize form once the existing or source rule loads.
  useEffect(() => {
    if (form) return;
    if (isEdit && existingQuery.data) {
      setForm(initialForm(existingQuery.data));
      return;
    }
    if (promoteFrom && sourceRuleQuery.data) {
      const { form: prefilled, warnings: w } = prefillFromPromotion(sourceRuleQuery.data, {
        targetEnvAppSlugs: targetAppSlugs,
        targetEnvAllowedConnectionIds: targetAllowedConnIds,
      });
      setForm(prefilled);
      setWarnings(w);
      return;
    }
    if (!isEdit && !promoteFrom) {
      setForm(initialForm());
    }
    // Intentionally depend on join()'d slug/id strings so the effect
    // doesn't retrigger on new array identities when contents are equal.
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [
    form,
    isEdit,
    existingQuery.data,
    promoteFrom,
    sourceRuleQuery.data,
    targetAppSlugs.join(','),
    targetAllowedConnIds.join(','),
  ]);

  const create = useCreateAlertRule();
  const update = useUpdateAlertRule(id ?? '');

  if (!form) return <PageLoader />;

  const idx = WIZARD_STEPS.indexOf(step);
  const errors = validateStep(step, form);

  const onNext = () => {
    if (errors.length > 0) {
      toast({ title: 'Fix validation errors before continuing', description: errors.join(' \u00b7 '), variant: 'error' });
      return;
    }
    if (idx < WIZARD_STEPS.length - 1) setStep(WIZARD_STEPS[idx + 1]);
  };
  const onBack = () => {
    if (idx > 0) setStep(WIZARD_STEPS[idx - 1]);
  };

  const onSave = async () => {
    try {
      if (isEdit) {
        await update.mutateAsync(toRequest(form));
        toast({ title: 'Rule updated', description: form.name, variant: 'success' });
      } else {
        await create.mutateAsync(toRequest(form));
        toast({ title: 'Rule created', description: form.name, variant: 'success' });
      }
      navigate('/alerts/rules');
    } catch (e) {
      toast({ title: 'Save failed', description: describeApiError(e), variant: 'error' });
    }
  };

  const body =
    step === 'scope' ? (
      <ScopeStep form={form} setForm={setForm} />
    ) : step === 'condition' ? (
      <ConditionStep form={form} setForm={setForm} />
    ) : step === 'trigger' ? (
      <TriggerStep form={form} setForm={setForm} ruleId={id} />
    ) : step === 'notify' ? (
      <NotifyStep form={form} setForm={setForm} ruleId={id} />
    ) : (
      <ReviewStep form={form} setForm={setForm} ruleId={id} />
    );

  return (
    <div className={css.wizard}>
      <div className={css.header}>
        <h2 className={css.pageTitle}>{isEdit ? `Edit rule: ${form.name}` : 'New alert rule'}</h2>
      </div>

      {promoteFrom && (
        <Alert variant="info" title="Promoting a rule">
          Promoting from <code>{promoteFrom}</code> — review and adjust, then save.
        </Alert>
      )}

      {warnings.length > 0 && (
        <Alert variant="warning" title="Review before saving">
          <ul style={{ margin: '4px 0 0 16px', padding: 0 }}>
            {warnings.map((w) => (
              <li key={w.field}>
                <code>{w.field}</code>: {w.message}
              </li>
            ))}
          </ul>
        </Alert>
      )}

      <nav className={css.steps}>
        {WIZARD_STEPS.map((s, i) => (
          <button
            key={s}
            type="button"
            className={`${css.step} ${step === s ? css.stepActive : ''} ${i < idx ? css.stepDone : ''}`}
            onClick={() => setStep(s)}
          >
            {STEP_LABELS[s]}
          </button>
        ))}
      </nav>

      <section className={`${sectionStyles.section} ${css.stepBody}`}>{body}</section>

      <div className={css.footer}>
        <Button variant="secondary" onClick={onBack} disabled={idx === 0}>
          Back
        </Button>
        {idx < WIZARD_STEPS.length - 1 ? (
          <Button variant="primary" onClick={onNext}>
            Next
          </Button>
        ) : (
          <Button
            variant="primary"
            onClick={onSave}
            disabled={create.isPending || update.isPending || computeSaveBlockReason(form) !== null}
          >
            {isEdit ? 'Save changes' : 'Create rule'}
          </Button>
        )}
      </div>
    </div>
  );
}
