import { Director } from './Director';
import { Audio } from './Audio';
import { ANNOUNCE, CLUE_TEXT, DAY_TASKS, GREET, NPCS, TASKS } from '../data/content';

export type DChoiceOpt = { label: string; tone: 'gentle' | 'hesitant' | 'deny'; effect?: () => void; then?: DNode[] };
export type DLine = { speaker: string; text: string; npcId?: string; raw?: boolean };
export type DChoice = { choice: DChoiceOpt[] };
export type DNode = DLine | DChoice;

function line(speaker: string, text: string, npcId?: string, raw = false): DLine { return { speaker, text, npcId, raw }; }
function narr(text: string): DLine { return { speaker: '', text }; }

export function taskActive(id: string) { return Director.tasks[id] === 'active'; }
export function completeTask(id: string) {
  if (Director.tasks[id] !== 'active') return;
  Director.tasks[id] = 'done';
  Director.addHappiness(TASKS[id].reward);
  Director.emit('toast', `任务完成 · ${TASKS[id].title} +${TASKS[id].reward}`);
  Audio.sfxDing();
  checkDusk();
}
export function refuseTask(id: string) {
  if (Director.tasks[id] !== 'active') return;
  Director.tasks[id] = 'refused';
  Director.refusedTasks.add(id);
  Director.sadBehavior('拒绝任务');
  Director.emit('toast', '（拒绝被记录了。）');
  checkDusk();
}
function checkDusk() {
  const ts = DAY_TASKS[Director.day] || [];
  if (ts.every((id) => Director.tasks[id] === 'done' || Director.tasks[id] === 'refused')) {
    if (!Director.flags['dusk' + Director.day]) { Director.flags['dusk' + Director.day] = true; Director.emit('dusk'); }
  }
}
export function activateDay(day: number) {
  Director.day = day;
  Director.resetDaily();
  for (const id of DAY_TASKS[day] || []) if (!Director.tasks[id] || Director.tasks[id] === 'idle') Director.tasks[id] = 'active';
  Director.emit('change');
}

const breadTask = () => (Director.day === 4 ? 'T8' : Director.day === 1 ? 'T1' : null);
const waterTask = () => (Director.day === 4 ? 'T9' : Director.day === 1 ? 'T2' : null);
const greetTask = () => (Director.day === 4 ? 'T10' : Director.day === 1 ? 'T3' : null);

// ---------------- 公告板 ----------------
export function boardScript(): DNode[] {
  const s: DNode[] = [];
  s.push(line('阿福', ANNOUNCE[Director.day], 'afu', true)); // 逐字，不腐蚀
  const ts = DAY_TASKS[Director.day] || [];
  const pending = ts.filter((id) => Director.tasks[id] === 'active');
  if (pending.length) {
    s.push(narr('今日幸福任务：'));
    for (const id of pending) s.push(narr(`· ${TASKS[id].title}（+${TASKS[id].reward}）`));
  } else if (Director.day < 7) {
    s.push(narr('今天的任务都完成啦。'));
  }
  // Day5 擦公告板 (T12) —— 擦到一半浮现旧字迹 (C6)
  if (Director.day === 5 && taskActive('T12')) {
    s.push({
      choice: [
        { label: '（擦拭公告板）', tone: 'gentle', effect: () => { discover('C6'); completeTask('T12'); } , then: CLUE_TEXT.C6.map(narr) },
        { label: '（不想擦）', tone: 'deny', effect: () => refuseTask('T12') },
      ],
    });
  }
  return s;
}

function discover(id: string) { if (Director.discoverClue(id)) Director.emit('toast', '（你注意到了什么……）'); }

// ---------------- NPC 对话 ----------------
export function talkScript(npcId: string): DNode[] {
  const def = NPCS[npcId];
  const name = def?.name || npcId;
  const s: DNode[] = [];
  const first = !Director.greetedToday.has(npcId);
  Director.greetedToday.add(npcId);
  Director.talkCounts[npcId] = (Director.talkCounts[npcId] || 0) + 1;

  const g = GREET[npcId] || ['……'];
  s.push(line(name, g[(Director.talkCounts[npcId] - 1) % g.length], npcId));

  // ---- 任务钩子 ----
  const bt = breadTask();
  const lettersActive = taskActive('T4');
  if (npcId === 'yuan') {
    if (bt && taskActive(bt)) {
      const f = flag('bread' + Director.day, { taken: false, del: [] as string[] });
      if (!f.taken) { f.taken = true; s.push(line('圆圆', '给，热乎的蜂蜜面包。送给大宝、咪咪和龟爷爷吧。', 'yuan')); }
    }
    if (lettersActive && letterCarry()) deliverLetter(s, 'yuan', '圆圆');
    if (Director.day === 5 && taskActive('T11')) {
      s.push({
        choice: [
          { label: '好呀，我来帮你揉面。', tone: 'gentle', effect: () => completeTask('T11'), then: [line('圆圆', '谢谢你，面团都笑了呢。', 'yuan')] },
          { label: '今天……我想歇一歇。', tone: 'deny', effect: () => refuseTask('T11'), then: [line('圆圆', '没关系的，休息也很好。', 'yuan')] },
        ],
      });
    }
  } else if (npcId === 'dabao') {
    if (bt && taskActive(bt)) deliverBread(s, 'dabao', '大宝');
    if (lettersActive) {
      const f = flag('letters', { taken: false, del: [] as string[] });
      if (!f.taken) { f.taken = true; s.push(line('大宝', '这三封信，麻烦你送给圆圆、咪咪和芙医生啦！', 'dabao')); }
    }
    if (Director.day >= 3) s.push(line('大宝', '奇怪……这些信的邮戳，怎么都是同一天呢？', 'dabao'));
  } else if (npcId === 'mimi') {
    if (bt && taskActive(bt)) deliverBread(s, 'mimi', '咪咪');
    if (lettersActive && letterCarry()) deliverLetter(s, 'mimi', '咪咪');
  } else if (npcId === 'gui') {
    if (bt && taskActive(bt)) deliverBread(s, 'gui', '龟爷爷');
    // C9 三段递进（D2/D4/D6 起各一段）；C9 作为 9 处线索之一，最终段 +8
    if (!Director.flags.seen_C9a && Director.day >= 2) c9(s, 'C9a');
    else if (Director.flags.seen_C9a && !Director.flags.seen_C9b && Director.day >= 4) c9(s, 'C9b');
    else if (Director.flags.seen_C9b && !Director.flags.seen_C9c && Director.day >= 6) c9(s, 'C9c');
  } else if (npcId === 'fu') {
    if (lettersActive && letterCarry()) {
      // 第三封信（给芙医生）—— 署名乱码 C4
      deliverLetter(s, 'fu', '芙医生', true);
    }
  }

  // T3/T10 与三位村民问好
  const gt = greetTask();
  if (gt && taskActive(gt) && Director.greetedToday.size >= 3) completeTaskDeferred(gt, s);

  // 纠缠：一天内对同一 NPC ≥5 次
  if (Director.talkCounts[npcId] === 5) Director.sadBehavior('纠缠');
  return s;
}

function completeTaskDeferred(id: string, s: DNode[]) { s.push({ choice: [{ label: '（继续）', tone: 'gentle', effect: () => completeTask(id) }] } as any); }

function c9(s: DNode[], id: 'C9a' | 'C9b' | 'C9c') {
  for (const t of CLUE_TEXT[id]) s.push(line('龟爷爷', t, 'gui'));
  Director.flags['seen_' + id] = true;
  if (id === 'C9c') discover('C9'); // 链完成 = 第 9 处线索 +8
}
function letterCarry() { const f = Director.flags['letters']; return f && f.taken; }
function deliverBread(s: DNode[], target: string, disp: string) {
  const bt = breadTask(); if (!bt) return;
  const f = flag('bread' + Director.day, { taken: false, del: [] as string[] });
  if (!f.taken || f.del.includes(target)) return;
  f.del.push(target);
  s.push(line(disp, '谢谢你的面包，好甜呀！', target));
  if (f.del.length >= 3) completeTaskDeferred(bt, s);
}
function deliverLetter(s: DNode[], target: string, disp: string, glitch = false) {
  const f = Director.flags['letters']; if (!f || !f.taken || f.del.includes(target)) return;
  f.del.push(target);
  if (glitch) { Director.emit('glitch', 'C4'); if (Director.day === 2) discover('C4'); s.push(line(disp, '……谢谢。信我收下了。', target)); }
  else s.push(line(disp, '有我的信？谢谢你跑一趟！', target));
  if (f.del.length >= 3) completeTaskDeferred('T4', s);
}
function flag<T>(k: string, init: T): T { if (!Director.flags[k]) Director.flags[k] = init; return Director.flags[k]; }

// ---------------- 交互点 ----------------
export function interactScript(kind: string, props: any): DNode[] | null {
  switch (kind) {
    case 'calendar':
      if (Director.day >= 2) { discover('C1'); return CLUE_TEXT.C1.map(narr); }
      return [narr('床头的日历，画着一朵向日葵。')];
    case 'bed':
      Director.emit('sleep');
      return null;
    case 'recipe':
      if (Director.day >= 3) { discover('C2'); return CLUE_TEXT.C2.map(narr); }
      return [narr('圆圆的配方纸，字迹娟秀。')];
    case 'clinicform':
      if (Director.day >= 5) { discover('C8'); return CLUE_TEXT.C8.map(narr); }
      return [narr('医生桌上有一叠表格，看不太清。')];
    case 'mailbox':
      if (Director.day >= 2) { discover('C3'); return CLUE_TEXT.C3.map(narr); }
      return [narr('大宝的邮筒，红彤彤的。')];
    case 'shelf': {
      const s: DNode[] = [];
      if (Director.day >= 2) { discover('C5'); s.push(...CLUE_TEXT.C5.map(narr)); }
      else s.push(narr('满满一货架的货物，真丰富呀。'));
      if (taskActive('T5')) completeTaskDeferred('T5', s);
      return s;
    }
    case 'flowerbed': {
      const wt = waterTask();
      if (wt && taskActive(wt)) {
        const c = (Director.flags['water' + Director.day] = (Director.flags['water' + Director.day] || 0) + 1);
        if (c >= 3) { completeTask(wt); return [narr('花坛浇好水了，花儿抬起了头。')]; }
        return [narr(`浇水（${c}/3）……花儿咕嘟咕嘟地喝着。`)];
      }
      return small('water', '你给花浇了点水。心情好了一点点。');
    }
    case 'berry': {
      if (taskActive('T6')) {
        const set: number[] = flag('berries', [] as number[]);
        if (!set.includes(props.n)) set.push(props.n);
        if (set.length >= 5) { completeTask('T6'); return [narr('五颗莓果，红得像糖。采齐啦！')]; }
        return [narr(`采到一颗莓果（${set.length}/5）。`)];
      }
      return [narr('莓果丛，红艳艳的。')];
    }
    case 'picnic':
      if (taskActive('T7')) { Director.emit('picnic'); return null; }
      return [narr('铺好的野餐布，格子花纹真可爱。')];
    case 'ribbon': {
      if (taskActive('T13')) {
        const set: number[] = flag('ribbons', [] as number[]);
        if (!set.includes(props.n)) set.push(props.n);
        if (set.length >= 4) { completeTask('T13'); return [narr('四条彩带挂好了，广场热闹起来。')]; }
        return [narr(`挂上一条彩带（${set.length}/4）。`)];
      }
      return [narr('一卷彩带，五颜六色的。')];
    }
    case 'festival':
      Director.emit('festival');
      return null;
    case 'well':
      if (Director.day < 5) return [narr('（一位村民温柔地把你引开）现在还不是看井的时候哦。')];
      gaze('well');
      discover('C7');
      return CLUE_TEXT.C7.map(narr);
    case 'fog':
      if (Director.day < 5) return [narr('（一位村民温柔地把你引开）那边是村庄的尽头，别去啦。')];
      gaze('fog');
      Director.emit('fog');
      return null;
  }
  return null;
}
function gaze(id: string) { if (!Director.gazedToday.has(id)) { Director.gazedToday.add(id); Director.addAwareness(3); } }
function small(kind: string, msg: string): DNode[] {
  const n = Director.smallInteract[kind] || 0;
  if (n < 3) { Director.smallInteract[kind] = n + 1; Director.addHappiness(1); }
  return [narr(msg)];
}

// 对话选项语气效果 (§6.1/§6.2/§6.3)
export function applyTone(tone: 'gentle' | 'hesitant' | 'deny') {
  if (tone === 'gentle') Director.addHappiness(2);
  else if (tone === 'hesitant') Director.addAwareness(2);
  else if (tone === 'deny') { Director.addAwareness(2); Director.sadBehavior('否定选项'); }
}

// 结局判定 (§9 自上而下第一个满足者)
export function evalEnding(fromFog: boolean): string | null {
  const D = Director;
  if (D.escapeCount >= 3 && D.happiness <= 10) return 'E4';
  if (fromFog && D.awareness >= 70 && D.clues.size >= 6) return 'E3';
  if (D.awareness >= 30 && D.awareness <= 69) return 'E2';
  if (D.awareness <= 29 && D.happiness >= 90) return 'E1';
  return null;
}
