import Phaser from 'phaser';
import type { NightState } from '../../data/types';
import { DAZZA_SIGNOFF, FAIL_TEXT, SUMMARY_UI } from '../../data/strings/door';
import { MAX_HEAT_STRIKES, NIGHT_DATES, type NightLog, type RunInfo } from './NightScene';
import { DOOR_PALETTE, MONO, panel, text } from './ui';

// Phase-2: run-aware summary. Still owes Phase 3 the incident-report form and
// the cross-night audit.

const W = 640;
const H = 360;

const NIGHT_NAMES = ['thursday', 'friday', 'saturday'] as const;

export function nightCash(log: NightLog, state: NightState): number {
  // Wage plus a hype bonus, minus a strike deduction. Vibe is not paid directly —
  // Dazza pays for the room feeling busy, not for you being right.
  const wage = 180;
  const hypeBonus = Math.round((log.hypePeak - 1) * 90);
  const doorBonus = log.admitted * 2;
  const strikes = state.heatStrikes.length * 60;
  return Math.max(0, wage + hypeBonus + doorBonus - strikes);
}

export function signoffFor(vibe: number, strikes: number): string {
  if (strikes >= 2) return DAZZA_SIGNOFF[0]!;
  const idx = vibe < 25 ? 0 : vibe < 50 ? 1 : vibe < 75 ? 2 : 3;
  return DAZZA_SIGNOFF[idx]!;
}

export class NightSummaryScene extends Phaser.Scene {
  private log!: NightLog;
  private state!: NightState;
  private run: RunInfo | null = null;

  constructor() {
    super('NightSummary');
  }

  init(data: { log: NightLog; state: NightState; run?: RunInfo }): void {
    this.log = data.log;
    this.state = data.state;
    this.run = data.run ?? null;
  }

  create(): void {
    const reason = this.log.endReason;
    const failed = reason !== 'clock';
    this.add.rectangle(W / 2, H / 2, W, H, failed ? 0x160a0e : 0x0a0a12);

    const title = reason !== 'clock' ? FAIL_TEXT[reason].title : SUMMARY_UI.title;
    const nightName = this.run ? (NIGHT_NAMES[this.run.nightIndex] ?? '') : '';

    this.add
      .text(W / 2, 26, title, {
        fontFamily: MONO,
        fontSize: '18px',
        color: failed ? '#ff8080' : '#f0e4d0',
      })
      .setOrigin(0.5);
    this.add
      .text(
        W / 2,
        46,
        failed
          ? `${this.run?.venue.name ?? this.state.venueId} · ${nightName} · night over early`
          : `${SUMMARY_UI.subtitle}${nightName ? ` · ${nightName}` : ''}`,
        {
          fontFamily: MONO,
          fontSize: '8px',
          color: DOOR_PALETTE.inkDim,
        },
      )
      .setOrigin(0.5);

    this.drawVibeGraph(30, 64, 300, 88);
    this.drawIncidents(30, 158, 300, 82);
    this.drawStats(354, 64);
    this.drawDazza(30, 250);

    const { prompt, next } = this.nextAction();
    this.add
      .text(W / 2, H - 14, `${prompt}   ·   seed ${this.log.seed}`, {
        fontFamily: MONO,
        fontSize: '8px',
        color: this.run?.runOver ? '#ff8080' : DOOR_PALETTE.inkDim,
      })
      .setOrigin(0.5);

    // The paperwork sits between the night and the next shift (design §3.3).
    const toReport = (): void => {
      this.scene.start('IncidentReport', {
        state: this.state,
        run: this.run?.game ?? null,
        seed: this.log.seed,
        next,
      });
    };
    this.input.once('pointerdown', toReport);
    this.input.keyboard?.once('keydown-SPACE', toReport);
  }

  /** What clicking through leads to: the next shift, or a fresh run. */
  private nextAction(): { prompt: string; next: () => void } {
    const r = this.run;
    if (!r) {
      return {
        prompt: SUMMARY_UI.replay,
        next: () => this.scene.start('Night', { seed: this.log.seed + 1 }),
      };
    }
    if (r.runOver) {
      return {
        prompt: 'licence gone · click to start a fresh week somewhere that has not heard of you',
        next: () => this.scene.start('Night', { freshRun: true, seed: this.log.seed + 13 }),
      };
    }
    if (r.seasonDone) {
      return {
        prompt: 'THE SEASON IS DONE. every door in the valley, held. click for a fresh run',
        next: () => this.scene.start('Night', { freshRun: true, seed: this.log.seed + 7 }),
      };
    }
    if (r.weekDone && r.promotedTo) {
      const v = r.promotedTo;
      return {
        // Dazza's pitch sells the next rung — the ladder is the reward.
        prompt: `WEEK SURVIVED — PROMOTED: ${v.name.toUpperCase()}. "${v.pitch}"`,
        next: () => this.scene.start('Night', {}),
      };
    }
    const failedNight = this.log.endReason !== 'clock';
    const nextName = failedNight
      ? (NIGHT_NAMES[r.nightIndex] ?? 'the same night')
      : (NIGHT_NAMES[r.nightIndex + 1] ?? 'the next night');
    return {
      prompt: failedNight ? `click to run ${nextName} back` : `click for ${nextName} · ${NIGHT_DATES[r.nightIndex + 1] ?? ''}`,
      next: () => this.scene.start('Night', {}),
    };
  }

  private drawVibeGraph(x: number, y: number, w: number, h: number): void {
    panel(this, x, y, w, h, 0x11111a, 0x2a2a38);
    text(this, x + 5, y + 4, 'VIBE ACROSS THE NIGHT', 7, DOOR_PALETTE.inkDim);

    // 50 is the line you started on — crossing below it is the story of the night
    const mid = y + h - 14 - (h - 34) * 0.5;
    this.add.rectangle(x + w / 2, mid, w - 10, 1, 0x33333f);

    const pts = this.log.vibeHistory;
    if (pts.length < 2) return;
    const g = this.add.graphics();
    g.lineStyle(2, DOOR_PALETTE.greenHot, 1);
    g.beginPath();
    pts.forEach((v, i) => {
      const px = x + 5 + ((w - 10) * i) / (pts.length - 1);
      const py = y + h - 14 - ((h - 34) * Math.max(0, Math.min(100, v))) / 100;
      if (i === 0) g.moveTo(px, py);
      else g.lineTo(px, py);
    });
    g.strokePath();

    text(this, x + 5, y + h - 12, '9PM', 7, DOOR_PALETTE.inkDim);
    text(this, x + w - 30, y + h - 12, '3AM', 7, DOOR_PALETTE.inkDim);
  }

  private drawStats(x: number, y: number): void {
    const w = 256;
    panel(this, x, y, w, 168, 0x11111a, 0x2a2a38);

    const cash = nightCash(this.log, this.state);
    const rows: Array<[string, string, string?]> = [
      ['admitted', String(this.log.admitted)],
      ['knocked back', String(this.log.denied)],
      ['sobriety tests', String(this.log.tested)],
      ['pat-downs', String(this.log.pattedDown)],
      ['peak hype', `x${this.log.hypePeak.toFixed(1)}`],
      ['final vibe', String(Math.round(this.state.vibe))],
      ['final aggro', String(Math.round(this.state.aggro))],
      [
        'clicker vs reality',
        `${this.state.capacity.clickerShown} vs ${this.state.capacity.inside}`,
        this.state.capacity.clickerShown === this.state.capacity.inside ? undefined : '#ffc060',
      ],
      [
        'heat strikes',
        `${this.state.heatStrikes.length}/3`,
        this.state.heatStrikes.length > 0 ? '#ff8080' : undefined,
      ],
    ];

    rows.forEach(([label, value, colour], i) => {
      const ry = y + 10 + i * 13;
      text(this, x + 8, ry, label, 8, DOOR_PALETTE.inkDim);
      this.add
        .text(x + w - 8, ry, value, {
          fontFamily: MONO,
          fontSize: '8px',
          color: colour ?? DOOR_PALETTE.inkHot,
        })
        .setOrigin(1, 0);
    });

    this.add.rectangle(x + w / 2, y + 138, w - 16, 1, 0x2a2a38);
    text(this, x + 8, y + 145, 'PAY', 9, '#d0b060');
    this.add
      .text(x + w - 8, y + 143, `$${cash}`, { fontFamily: MONO, fontSize: '14px', color: '#f0d060' })
      .setOrigin(1, 0);

  }

  /**
   * The strikes spelled out. A count alone tells you the run is over; the
   * reasons tell you which call did it, which is the only way the next night is
   * played differently. Lives in its own panel because the reasons are long
   * sentences and used to run straight off the right edge of the stats table.
   */
  private drawIncidents(x: number, y: number, w: number, h: number): void {
    panel(this, x, y, w, h, 0x11111a, 0x2a2a38);
    const strikes = this.state.heatStrikes;
    text(this, x + 5, y + 4, strikes.length > 0 ? 'THE INSPECTOR WROTE UP' : 'NOTHING ON THE RECORD', 7,
      strikes.length > 0 ? '#ff8080' : DOOR_PALETTE.inkDim);

    if (strikes.length === 0) {
      this.add.text(x + 5, y + 18, 'a clean sheet. no strikes, no questions.\nthe licence survives to friday.', {
        fontFamily: MONO, fontSize: '7px', color: DOOR_PALETTE.inkDim, wordWrap: { width: w - 12 }, lineSpacing: 2,
      });
      return;
    }

    let ry = y + 16;
    for (const s of strikes.slice(0, MAX_HEAT_STRIKES)) {
      const line = this.add.text(x + 5, ry, `· ${s.reason}`, {
        fontFamily: MONO, fontSize: '7px', color: '#ff9090', wordWrap: { width: w - 12 },
      });
      ry += line.height + 3;
    }
  }

  private drawDazza(x: number, y: number): void {
    const w = W - 60;
    panel(this, x, y, w, 74, 0x0d1116, 0x2c4a38);
    text(this, x + 8, y + 6, 'DAZZA', 8, '#7de08a');

    const reason = this.log.endReason;
    const body =
      reason !== 'clock'
        ? FAIL_TEXT[reason].dazza
        : signoffFor(this.state.vibe, this.state.heatStrikes.length);

    this.add.text(x + 8, y + 20, body, {
      fontFamily: MONO,
      fontSize: '9px',
      color: reason !== 'clock' ? '#ffb0b0' : '#bfe8c8',
      wordWrap: { width: w - 16 },
    });

    if (this.state.heatStrikes.length >= 3) {
      this.add.text(x + 8, y + 56, 'THREE STRIKES. THE LICENCE IS GONE. RUN OVER.', {
        fontFamily: MONO,
        fontSize: '9px',
        color: '#ff6060',
      });
    }
  }
}
