import type {
  ProjectCreateRequest,
  ProjectPlanGenerateRequest,
  ProjectPlanView,
} from "@/lib/api/types";

// 立项向导 5 步（UX §6.2）。表单状态用字符串/数组，提交时归一为 ProjectCreateRequest。
export interface WizardForm {
  title: string;
  genre: string;
  logline: string;
  sellingPoints: string[];
  structure: string;
  premise: string;
  protagonist: string;
  theme: string;
  // 立项书级常量（灵感④）：基调 / 结局取向 / 叙事视角。
  tone: string;
  endingType: string;
  narrativePov: string;
}

export const WIZARD_STEPS = 5;

// 各步标题（与 WIZARD_STEPS 一一对应）。第 5 步为「确认/概览」：回显已填字段供复核后提交。
export const STEP_TITLES = [
  "书名 + 题材",
  "一句话故事 + 卖点 + 结构",
  "立意 / 总纲",
  "主角 / 金手指",
  "确认与提交",
] as const;

export const emptyWizardForm: WizardForm = {
  title: "",
  genre: "",
  logline: "",
  sellingPoints: [],
  structure: "",
  premise: "",
  protagonist: "",
  theme: "",
  tone: "",
  endingType: "",
  narrativePov: "",
};

export const GENRES = ["玄幻", "仙侠", "都市", "科幻", "历史", "悬疑"];
export const STRUCTURES = ["三幕", "故事圈", "雪花"];
export const SELLING_POINT_PRESETS = ["逆袭", "打脸", "系统流", "双男主", "群像"];
// 立项书级常量预设（灵感④ / D 枚举）——free text 单选，命不中预设可留空。
export const TONES = ["热血", "轻松", "沉重", "治愈", "暗黑", "爽文"];
export const ENDING_TYPES = ["HE", "BE", "开放", "正剧"];
export const NARRATIVE_POVS = ["第一人称", "第三人称限知", "第三人称全知", "多视角"];

// 每一步可否前进：仅第 1 步（书名）必填，其余可空着继续（草稿式立项）。
export function canAdvance(step: number, form: WizardForm): boolean {
  if (step === 1) return form.title.trim().length > 0;
  return true;
}

// 整个向导可否提交：书名必填。
export function canSubmit(form: WizardForm): boolean {
  return form.title.trim().length > 0;
}

export function clampStep(step: number): number {
  if (step < 1) return 1;
  if (step > WIZARD_STEPS) return WIZARD_STEPS;
  return step;
}

// AI 立项方案 → 向导表单补丁（灵感⑤）。按字段回填：
// - 有对应向导输入的字段直接映射（书名候选→title、叙事结构→structure、基调→tone）；
// - 无独立向导输入的字段（时空背景/结局设计）折进立意/总纲（premise，带标签），**不静默丢内容**；
// - 结局取向/叙事视角这类预设枚举无法从自由文本可靠反推 → 不臆造，留给作者手选（不进 patch）。
// 返回补丁而非整表覆盖，由 applyPlanPatch 按字段并入（保护已编辑字段）。
export function mapPlanResultToWizardForm(
  plan: ProjectPlanView,
): Partial<WizardForm> {
  const patch: Partial<WizardForm> = {};
  const firstTitle = plan.title_candidates?.[0]?.trim();
  if (firstTitle) patch.title = firstTitle;
  const structure = plan.narrative_structure.trim();
  if (structure) patch.structure = structure;
  const tone = plan.tone.trim();
  if (tone) patch.tone = tone;
  // 立意/总纲 = 故事核心 + 无独立向导字段的时空背景/结局设计（带标签，逐段拼接不丢内容）。
  const premiseParts: string[] = [];
  const core = plan.story_core.trim();
  if (core) premiseParts.push(core);
  const setting = plan.setting.trim();
  if (setting) premiseParts.push(`时空背景：${setting}`);
  const ending = plan.ending_design.trim();
  if (ending) premiseParts.push(`结局设计：${ending}`);
  if (premiseParts.length > 0) patch.premise = premiseParts.join("\n\n");
  return patch;
}

// WizardForm 中值为字符串的字段键（排除 sellingPoints: string[]）——方案 patch 只回填这些。
type WizardStringKey = {
  [K in keyof WizardForm]: WizardForm[K] extends string ? K : never;
}[keyof WizardForm];

// 把方案补丁按字段并入向导表单：**仅回填当前为空的字段**（保护作者已编辑内容，
// 非 bulk 覆盖）。只处理字符串字段（方案 patch 只产字符串值）；空 = trim 后为空串。
export function applyPlanPatch(
  form: WizardForm,
  patch: Partial<WizardForm>,
): WizardForm {
  const next: WizardForm = { ...form };
  for (const key of Object.keys(patch) as WizardStringKey[]) {
    const value = patch[key];
    // 守卫短路：非字符串值（如误传数组键）直接跳过，绝不触达 .trim()。
    if (typeof value === "string" && form[key].trim() === "") {
      next[key] = value;
    }
  }
  return next;
}

// AI 立项方案的种子门控：题材 + 一句话故事（logline）都非空才允许生成（后端亦校验，防 slop）。
export function canGeneratePlan(form: WizardForm): boolean {
  return form.genre.trim().length > 0 && form.logline.trim().length > 0;
}

// 向导草稿 → 立项方案生成请求（snake_case；空值省略）。genre+logline 为种子，其余有则贴合。
export function toPlanSeedRequest(
  form: WizardForm,
): ProjectPlanGenerateRequest {
  const trimOrUndef = (s: string): string | undefined => {
    const v = s.trim();
    return v.length > 0 ? v : undefined;
  };
  return {
    genre: trimOrUndef(form.genre),
    logline: trimOrUndef(form.logline),
    title: trimOrUndef(form.title),
    premise: trimOrUndef(form.premise),
    theme: trimOrUndef(form.theme),
    structure: trimOrUndef(form.structure),
    tone: trimOrUndef(form.tone),
    ending_type: trimOrUndef(form.endingType),
    narrative_pov: trimOrUndef(form.narrativePov),
    selling_points: form.sellingPoints,
  };
}

// 归一为后端请求体（snake_case，空值落 null/省略）。
export function toCreateRequest(form: WizardForm): ProjectCreateRequest {
  const trim = (s: string): string | null => {
    const v = s.trim();
    return v.length > 0 ? v : null;
  };
  // 立意（premise）与主角/金手指（protagonist）是两个独立输入，但 M1 projects 表只有
  // premise 一个字段 → 合并进 premise，二者各占一段，互不覆盖（QA H1：此前共用同一字段）。
  const premise =
    [trim(form.premise), form.protagonist.trim() ? `主角/金手指：${form.protagonist.trim()}` : null]
      .filter((s): s is string => s !== null)
      .join("\n\n") || null;
  return {
    title: form.title.trim(),
    genre: trim(form.genre),
    logline: trim(form.logline),
    premise,
    theme: trim(form.theme),
    selling_points: form.sellingPoints,
    structure: trim(form.structure),
    tone: trim(form.tone),
    ending_type: trim(form.endingType),
    narrative_pov: trim(form.narrativePov),
  };
}
