import { useEffect, useMemo, useRef, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { PageHeader } from "../../components/layout/PageHeader";
import { Stepper } from "../../components/studio/Stepper";
import { Button } from "../../components/ui";
import { useData, useRepos } from "../../data/DataContext";
import { validatePlaySteps } from "../../domain/speakers";
import type { ThreadsAccount } from "../../domain/types";
import { useI18n } from "../../i18n/I18nContext";
import {
  clearDraft,
  draftToPlay,
  emptyDraft,
  loadDraft,
  saveDraft,
  type WizardDraft,
  WIZARD_STEPS,
} from "./wizardState";
import { CrewStep } from "./steps/CrewStep";
import { PreviewStep } from "./steps/PreviewStep";
import { ScheduleStep } from "./steps/ScheduleStep";
import { ScriptStep } from "./steps/ScriptStep";
import { SubmitStep } from "./steps/SubmitStep";
import { TopicStep } from "./steps/TopicStep";

export function WizardPage() {
  const { playId } = useParams();
  const isNew = !playId || playId === "new";
  const draftScope = isNew ? "new" : playId;
  const repos = useRepos();
  const { refresh } = useData();
  const navigate = useNavigate();
  const { t } = useI18n();

  const [draft, setDraft] = useState<WizardDraft>(() => loadDraft(draftScope));
  const scopeRef = useRef(draftScope);
  const skipSaveRef = useRef(false);
  const [accounts, setAccounts] = useState<ThreadsAccount[]>([]);
  const [error, setError] = useState("");
  const [busy, setBusy] = useState(false);

  useEffect(() => {
    void repos.accounts.list().then(setAccounts);
  }, [repos.accounts]);

  useEffect(() => {
    if (scopeRef.current !== draftScope) {
      scopeRef.current = draftScope;
      skipSaveRef.current = true;
      setDraft(loadDraft(draftScope));
    }
    if (!isNew && playId) {
      void repos.plays.get(playId).then((play) => {
        if (!play || scopeRef.current !== draftScope) return;
        setDraft({
          playId: play.id,
          stepIndex: 0,
          title: play.title,
          topic: play.topic,
          lead_account_id: play.lead_account_id,
          cast_account_ids: play.cast_account_ids,
          steps: play.steps,
          schedule_start_at: play.schedule_start_at,
          interval_minutes: Math.max(
            1,
            Math.round((play.steps[1]?.delay_from_previous_sec || 300) / 60),
          ),
        });
      }).catch((e: unknown) => {
        setError(e instanceof Error ? e.message : t("common.error"));
      });
    }
  }, [draftScope, isNew, playId, repos.plays, t]);

  useEffect(() => {
    if (skipSaveRef.current) {
      skipSaveRef.current = false;
      return;
    }
    saveDraft(draft, draftScope);
  }, [draft, draftScope]);

  const accountMap = useMemo(() => new Map(accounts.map((a) => [a.id, a])), [accounts]);

  function patch(partial: Partial<WizardDraft>) {
    setDraft((d) => ({ ...d, ...partial }));
    setError("");
  }

  function canNext(): string | null {
    if (draft.stepIndex === 0 && !draft.topic.trim()) return t("wizard.err.topic");
    if (draft.stepIndex === 1) {
      if (!draft.lead_account_id) return t("wizard.err.lead");
      const lead = accounts.find((a) => a.id === draft.lead_account_id);
      if (!lead?.is_usable) return t("wizard.err.leadUnusable");
    }
    if (draft.stepIndex === 2) {
      const play = draftToPlay(draft, t("wizard.unnamedPlay"));
      const code = validatePlaySteps(play);
      return code ? t(code) : null;
    }
    return null;
  }

  function goNext() {
    const err = canNext();
    if (err) {
      setError(err);
      return;
    }
    setDraft((d) => ({ ...d, stepIndex: Math.min(WIZARD_STEPS.length - 1, d.stepIndex + 1) }));
  }

  function goPrev() {
    setError("");
    setDraft((d) => ({ ...d, stepIndex: Math.max(0, d.stepIndex - 1) }));
  }

  async function handleSubmit() {
    setBusy(true);
    setError("");
    try {
      const play = draftToPlay(draft, t("wizard.unnamedPlay"));
      const code = validatePlaySteps(play);
      if (code) throw new Error(t(code));
      await repos.plays.save(play);
      const bundle = await repos.plays.submit(play.id);
      clearDraft(draftScope);
      setDraft(emptyDraft());
      refresh();
      navigate(`/app/outbox/${bundle.id}`);
    } catch (e) {
      const msg = e instanceof Error ? e.message : t("wizard.submitFail");
      setError(msg.startsWith("play.err.") ? t(msg) : msg);
    } finally {
      setBusy(false);
    }
  }

  const step = draft.stepIndex;

  return (
    <>
      <PageHeader title={isNew ? t("wizard.newTitle") : t("wizard.editTitle")} />
      <Stepper
        activeIndex={step}
        onSelect={(index) => {
          if (index <= draft.stepIndex) patch({ stepIndex: index });
        }}
      />

      {step === 0 && <TopicStep draft={draft} onChange={patch} />}
      {step === 1 && <CrewStep draft={draft} accounts={accounts} onChange={patch} />}
      {step === 2 && <ScriptStep draft={draft} accounts={accounts} onChange={patch} />}
      {step === 3 && <PreviewStep draft={draft} accountMap={accountMap} />}
      {step === 4 && <ScheduleStep draft={draft} onChange={patch} />}
      {step === 5 && (
        <SubmitStep draft={draft} accountMap={accountMap} busy={busy} onSubmit={() => void handleSubmit()} />
      )}

      {error ? (
        <p className="hb-form-error" role="alert">
          {error}
        </p>
      ) : null}

      <div className="hb-wizard-actions">
        <Button variant="ghost" type="button" onClick={goPrev} disabled={step === 0 || busy}>
          {t("wizard.prev")}
        </Button>
        {step < WIZARD_STEPS.length - 1 ? (
          <Button type="button" onClick={goNext} disabled={busy}>
            {t("wizard.next")}
          </Button>
        ) : null}
      </div>
    </>
  );
}
