"use client";

import { ArrowLeft, ArrowRight, Check, CheckCircle2, Sparkles } from "lucide-react";
import { useRouter } from "next/navigation";
import { useEffect, useRef, useState } from "react";

import { ThinkingIndicator } from "@/components/ThinkingIndicator";
import { useToast } from "@/components/Toast";
import { Badge } from "@/components/ui/Badge";
import { Button } from "@/components/ui/Button";
import { Field } from "@/components/ui/Field";
import { SegmentedControl } from "@/components/ui/SegmentedControl";
import { Select } from "@/components/ui/Select";
import { TextArea } from "@/components/ui/TextArea";
import { TextInput } from "@/components/ui/TextInput";
import { api } from "@/lib/api/client";
import { buttonClass } from "@/lib/ui/variants";
import type { ProjectPlanView } from "@/lib/api/types";
import { useProjectPlan } from "@/lib/wizard/useProjectPlan";
import {
  ENDING_TYPES,
  GENRES,
  NARRATIVE_POVS,
  SELLING_POINT_PRESETS,
  STEP_TITLES,
  STRUCTURES,
  TONES,
  WIZARD_STEPS,
  applyPlanPatch,
  canAdvance,
  canGeneratePlan,
  canSubmit,
  clampStep,
  emptyWizardForm,
  mapPlanResultToWizardForm,
  toCreateRequest,
  toPlanSeedRequest,
  type WizardForm,
} from "@/lib/wizard/wizard";

// 立项向导（UX §6.2）。Client Component：收集字段 → POST /projects → 进工作台。
export function ProjectWizard() {
  const router = useRouter();
  const toast = useToast();
  const [step, setStep] = useState(1);
  const [form, setForm] = useState<WizardForm>(emptyWizardForm);
  const [submitting, setSubmitting] = useState(false);

  // 换步后把焦点移到新步标题，方便键盘/读屏用户感知步骤变化；首帧不抢第 1 步输入框的 autoFocus。
  const stepHeadingRef = useRef<HTMLParagraphElement>(null);
  const isFirstRender = useRef(true);
  useEffect(() => {
    if (isFirstRender.current) {
      isFirstRender.current = false;
      return;
    }
    stepHeadingRef.current?.focus();
  }, [step]);

  const update = (patch: Partial<WizardForm>): void =>
    setForm((prev) => ({ ...prev, ...patch }));

  const toggleSellingPoint = (point: string): void =>
    setForm((prev) => ({
      ...prev,
      sellingPoints: prev.sellingPoints.includes(point)
        ? prev.sellingPoints.filter((p) => p !== point)
        : [...prev.sellingPoints, point],
    }));

  // AI 立项方案按字段回填：只填当前为空的字段（保护作者已编辑内容，不 bulk 覆盖）。
  const applyPlan = (plan: ProjectPlanView): void => {
    const patch = mapPlanResultToWizardForm(plan);
    const filled = (Object.keys(patch) as Array<keyof WizardForm>).filter(
      (k) => typeof form[k] === "string" && (form[k] as string).trim() === "",
    );
    setForm((prev) => applyPlanPatch(prev, patch));
    toast(
      filled.length > 0
        ? `已回填 ${filled.length} 个空字段（已编辑内容不覆盖）`
        : "向导相关字段均已填写，未覆盖任何内容",
      filled.length > 0 ? "success" : "info",
    );
  };

  const goBack = (): void => setStep((s) => clampStep(s - 1));
  const goNext = (): void => setStep((s) => clampStep(s + 1));

  const submit = async (): Promise<void> => {
    if (!canSubmit(form)) {
      toast("请先填写书名", "error");
      setStep(1);
      return;
    }
    setSubmitting(true);
    const { data, error } = await api.POST("/projects", {
      body: toCreateRequest(form),
    });
    if (error || !data) {
      setSubmitting(false);
      toast("创建作品失败，请重试", "error");
      return;
    }
    router.push(`/projects/${data.id}/write`);
  };

  const isLast = step === WIZARD_STEPS;

  return (
    <div className="mx-auto max-w-2xl rounded border border-line bg-panel p-6 shadow-paper sm:p-8">
      <div className="mb-6 flex items-center justify-between">
        <h1 className="font-serif text-2xl text-ink">新建作品</h1>
        <StepDots current={step} />
      </div>
      <div className="mb-4">
        <Badge variant="accent">
          步骤 {step}/{WIZARD_STEPS}
        </Badge>
        <p
          ref={stepHeadingRef}
          tabIndex={-1}
          className="mt-2 text-sm text-ink-soft focus-visible:outline-none"
        >
          {STEP_TITLES[step - 1]}
        </p>
      </div>

      <div className="min-h-[220px]">
        {step === 1 && <StepBasics form={form} update={update} />}
        {step === 2 && (
          <StepStory
            form={form}
            update={update}
            toggleSellingPoint={toggleSellingPoint}
            onApplyPlan={applyPlan}
          />
        )}
        {step === 3 && <StepPremise form={form} update={update} />}
        {step === 4 && <StepProtagonist form={form} update={update} />}
        {step === 5 && <StepConfirm form={form} />}
      </div>

      <div className="mt-8 flex items-center justify-between">
        <Button onClick={goBack} disabled={step === 1} variant="secondary">
          <ArrowLeft className="h-4 w-4" aria-hidden="true" />
          上一步
        </Button>
        {isLast ? (
          <Button
            onClick={submit}
            disabled={submitting || !canSubmit(form)}
            variant="primary"
          >
            <CheckCircle2 className="h-4 w-4" aria-hidden="true" />
            {submitting ? "创建中…" : "完成立项"}
          </Button>
        ) : (
          <Button
            onClick={goNext}
            disabled={!canAdvance(step, form)}
            variant="primary"
          >
            下一步
            <ArrowRight className="h-4 w-4" aria-hidden="true" />
          </Button>
        )}
      </div>
    </div>
  );
}

function StepDots({ current }: { current: number }) {
  return (
    <div className="flex gap-1.5" aria-hidden="true">
      {Array.from({ length: WIZARD_STEPS }, (_, i) => (
        <span
          key={i}
          className={`h-2 w-2 rounded ${
            i + 1 <= current ? "bg-cinnabar" : "bg-line"
          }`}
        />
      ))}
    </div>
  );
}

interface StepProps {
  form: WizardForm;
  update: (patch: Partial<WizardForm>) => void;
}

function StepBasics({ form, update }: StepProps) {
  const titleMissing = form.title.trim().length === 0;
  return (
    <div>
      <Field
        label="书名"
        required
        help={titleMissing ? "请先填写书名才能继续" : undefined}
      >
        <TextInput
          value={form.title}
          onChange={(e) => update({ title: e.target.value })}
          placeholder="例：逐光而行"
          autoFocus
        />
      </Field>
      <Field label="题材">
        <Select
          value={form.genre}
          onChange={(e) => update({ genre: e.target.value })}
        >
          <option value="">未选择</option>
          {GENRES.map((g) => (
            <option key={g} value={g}>
              {g}
            </option>
          ))}
        </Select>
      </Field>
    </div>
  );
}

// AI 立项方案助手（灵感⑤）：种子（题材+logline）就绪后一键生成结构化方案 → 预览 → 按字段回填。
function PlanAssistant({
  form,
  onApplyPlan,
}: {
  form: WizardForm;
  onApplyPlan: (plan: ProjectPlanView) => void;
}) {
  const { status, plan, generate } = useProjectPlan();
  const ready = canGeneratePlan(form);
  const generating = status === "generating";

  return (
    <div className="my-4 rounded border border-line bg-bg p-3">
      <div className="flex items-center justify-between gap-3">
        <div className="min-w-0">
          <p className="flex items-center gap-1.5 text-sm text-ink">
            <Sparkles className="h-4 w-4 text-cinnabar" aria-hidden="true" />
            AI 立项方案
          </p>
          <p className="mt-0.5 text-xs text-ink-soft">
            {ready
              ? "根据题材 + 一句话故事推演书级蓝图，按字段回填（不覆盖已填内容）。"
              : "填好「题材」（上一步）与「一句话故事」后即可生成。"}
          </p>
        </div>
        <Button
          onClick={() => void generate(toPlanSeedRequest(form))}
          disabled={!ready || generating}
          variant="secondary"
        >
          {generating ? (
            <ThinkingIndicator label="生成中" />
          ) : (
            <>
              <Sparkles className="h-4 w-4" aria-hidden="true" />
              生成方案
            </>
          )}
        </Button>
      </div>

      {status === "done" && plan && (
        <div className="mt-3 border-t border-line pt-3">
          <dl className="space-y-1.5 text-sm">
            {plan.title_candidates && plan.title_candidates.length > 0 && (
              <PlanRow label="书名候选" value={plan.title_candidates.join("、")} />
            )}
            <PlanRow label="时空背景" value={plan.setting} />
            <PlanRow label="叙事结构" value={plan.narrative_structure} />
            <PlanRow label="故事核心" value={plan.story_core} />
            <PlanRow label="结局设计" value={plan.ending_design} />
            <PlanRow label="基调" value={plan.tone} />
          </dl>
          <div className="mt-3 flex justify-end">
            <Button onClick={() => onApplyPlan(plan)} variant="primary">
              <Check className="h-4 w-4" aria-hidden="true" />
              按字段回填向导
            </Button>
          </div>
        </div>
      )}
    </div>
  );
}

function PlanRow({ label, value }: { label: string; value: string }) {
  if (!value.trim()) return null;
  return (
    <div className="flex gap-3">
      <dt className="w-16 shrink-0 text-ink-soft">{label}</dt>
      <dd className="min-w-0 flex-1 whitespace-pre-wrap text-ink">{value}</dd>
    </div>
  );
}

function StepStory({
  form,
  update,
  toggleSellingPoint,
  onApplyPlan,
}: StepProps & {
  toggleSellingPoint: (p: string) => void;
  onApplyPlan: (plan: ProjectPlanView) => void;
}) {
  return (
    <div>
      <Field label="一句话故事（logline）">
        <TextArea
          className="h-20 resize-none"
          value={form.logline}
          onChange={(e) => update({ logline: e.target.value })}
          placeholder="废柴少年觉醒禁忌血脉，在仙门倾轧中逆势封神。"
        />
      </Field>
      <PlanAssistant form={form} onApplyPlan={onApplyPlan} />
      <Field label="故事结构">
        <SegmentedControl
          ariaLabel="故事结构"
          className="flex-wrap"
          value={form.structure}
          onChange={(structure) => update({ structure })}
          options={STRUCTURES.map((s) => ({ value: s, label: s }))}
        />
      </Field>
      <fieldset>
        <legend className="mb-1 block text-sm text-ink-soft">核心卖点</legend>
        <div className="flex flex-wrap gap-2">
          {SELLING_POINT_PRESETS.map((p) => {
            const selected = form.sellingPoints.includes(p);
            return (
              <button
                type="button"
                key={p}
                aria-pressed={selected}
                onClick={() => toggleSellingPoint(p)}
                className={buttonClass({
                  variant: selected ? "primary" : "secondary",
                  size: "sm",
                })}
              >
                {selected ? (
                  <Check className="h-3.5 w-3.5" aria-hidden="true" />
                ) : null}
                {p}
              </button>
            );
          })}
        </div>
      </fieldset>
    </div>
  );
}

function StepPremise({ form, update }: StepProps) {
  return (
    <div>
      <Field label="立意（premise）">
        <TextArea
          className="h-20 resize-none"
          value={form.premise}
          onChange={(e) => update({ premise: e.target.value })}
          placeholder="故事的核心命题与前提。"
        />
      </Field>
      <Field label="主题（theme）">
        <TextInput
          value={form.theme}
          onChange={(e) => update({ theme: e.target.value })}
          placeholder="例：抗争与代价"
        />
      </Field>
      <Field label="基调">
        <Select
          value={form.tone}
          onChange={(e) => update({ tone: e.target.value })}
        >
          <option value="">未选择</option>
          {TONES.map((t) => (
            <option key={t} value={t}>
              {t}
            </option>
          ))}
        </Select>
      </Field>
      <Field label="叙事视角">
        <SegmentedControl
          ariaLabel="叙事视角"
          className="flex-wrap"
          value={form.narrativePov}
          onChange={(narrativePov) => update({ narrativePov })}
          options={NARRATIVE_POVS.map((p) => ({ value: p, label: p }))}
        />
      </Field>
      <Field label="结局取向">
        <SegmentedControl
          ariaLabel="结局取向"
          className="flex-wrap"
          value={form.endingType}
          onChange={(endingType) => update({ endingType })}
          options={ENDING_TYPES.map((e) => ({ value: e, label: e }))}
        />
      </Field>
    </div>
  );
}

function StepProtagonist({ form, update }: StepProps) {
  // M1 projects 表无独立主角/金手指字段；提交时由 toCreateRequest 合并进 premise（与立意各占一段）。
  // 必须绑定独立的 form.protagonist，不能复用 form.premise，否则与第 3 步立意互相覆盖（QA H1）。
  return (
    <div>
      <p className="mb-3 text-sm text-ink-soft">
        主角与金手指（M1 暂并入总纲，后续设定库独立建模）。
      </p>
      <Field label="主角 / 金手指概要">
        <TextArea
          className="h-28 resize-none"
          value={form.protagonist}
          onChange={(e) => update({ protagonist: e.target.value })}
          placeholder="主角设定、金手指来源与限制……"
        />
      </Field>
    </div>
  );
}

// 第 5 步：确认/概览——回显已填字段供复核后提交（取代旧的空「世界观后续里程碑」说明）。
function StepConfirm({ form }: { form: WizardForm }) {
  const rows: Array<{ label: string; value: string }> = [
    { label: "书名", value: form.title.trim() || "未填写" },
    { label: "一句话故事", value: form.logline.trim() || "未填写" },
    { label: "题材", value: form.genre || "未选择" },
    { label: "故事结构", value: form.structure || "未选择" },
    {
      label: "核心卖点",
      value: form.sellingPoints.length > 0 ? form.sellingPoints.join("、") : "未选择",
    },
    { label: "基调", value: form.tone || "未选择" },
    { label: "叙事视角", value: form.narrativePov || "未选择" },
    { label: "结局取向", value: form.endingType || "未选择" },
  ];
  return (
    <div>
      <p className="mb-3 text-sm text-ink-soft">
        复核以下信息，确认无误后即可完成立项。其余设定可进工作台后在「设定库」继续完善。
      </p>
      <dl className="divide-y divide-line rounded border border-line bg-bg">
        {rows.map((row) => (
          <div key={row.label} className="flex gap-4 px-4 py-2.5 text-sm">
            <dt className="w-20 shrink-0 text-ink-soft">{row.label}</dt>
            <dd className="min-w-0 flex-1 text-ink">{row.value}</dd>
          </div>
        ))}
      </dl>
    </div>
  );
}
