"use client";

import { ChangeEvent, useEffect, useMemo, useState } from "react";
import {
  Dimension,
  HandSide,
  Report,
  ReportData,
  ReportSummary,
  apiFetch,
  ensureToken,
  uploadPalmImage,
} from "@/lib/api";

const handText: Record<HandSide, string> = {
  left: "左手",
  right: "右手",
  unknown: "不确定",
};

const statusText: Record<Report["status"], string> = {
  pending: "等待中",
  processing: "生成中",
  completed: "已完成",
  failed: "失败",
};

export default function PalmWebApp() {
  const [ready, setReady] = useState(false);
  const [file, setFile] = useState<File | null>(null);
  const [preview, setPreview] = useState("");
  const [handSide, setHandSide] = useState<HandSide>("unknown");
  const [busyText, setBusyText] = useState("");
  const [error, setError] = useState("");
  const [reports, setReports] = useState<ReportSummary[]>([]);
  const [activeReport, setActiveReport] = useState<Report | null>(null);

  useEffect(() => {
    ensureToken()
      .then(() => Promise.all([loadReports()]))
      .then(() => setReady(true))
      .catch((err) => {
        setError(err.message || "初始化失败");
        setReady(true);
      });
  }, []);

  const completedReports = reports.filter((item) => item.status === "completed").length;

  function onPickFile(event: ChangeEvent<HTMLInputElement>) {
    const selected = event.target.files?.[0];
    if (!selected) return;
    setFile(selected);
    setError("");
    if (preview) URL.revokeObjectURL(preview);
    setPreview(URL.createObjectURL(selected));
  }

  async function loadReports() {
    const data = await apiFetch<ReportSummary[]>("/reports");
    setReports(data);
  }

  async function startReport() {
    if (!file) {
      setError("请先选择一张清晰的掌心照片。");
      return;
    }
    setBusyText("正在接入掌纹照片...");
    setError("");
    try {
      const upload = await uploadPalmImage(file);
      setBusyText("先生正在解读掌纹...");
      const report = await apiFetch<Report>("/reports", {
        method: "POST",
        body: JSON.stringify({ image_id: upload.image_id, hand_side: handSide }),
      });
      await pollReport(report.id);
      await loadReports();
    } catch (err) {
      setError(err instanceof Error ? err.message : "生成失败");
    } finally {
      setBusyText("");
    }
  }

  async function pollReport(reportId: string) {
    for (let i = 0; i < 80; i += 1) {
      const report = await apiFetch<Report>(`/reports/${reportId}`);
      setActiveReport(report);
      if (report.status === "completed") return report;
      if (report.status === "failed") throw new Error(report.error_message || "报告生成失败");
      await sleep(2200);
    }
    throw new Error("生成时间较长，请稍后在档案中查看。");
  }

  async function openReport(reportId: string) {
    setError("");
    const report = await apiFetch<Report>(`/reports/${reportId}`);
    setActiveReport(report);
    window.scrollTo({ top: 0, behavior: "smooth" });
  }

  async function deleteReport(reportId: string) {
    await apiFetch(`/reports/${reportId}`, { method: "DELETE" });
    if (activeReport?.id === reportId) setActiveReport(null);
    await loadReports();
  }

  return (
    <main className="shell">
      <section className="hero">
        <div className="brand">
          <span className="seal">掌</span>
          <div>
            <p className="kicker">CYBER MISTER</p>
            <h1>赛博先生</h1>
          </div>
        </div>
        <div className="hero-copy">
          <p className="eyebrow">AI 手相报告 · 娱乐占卜 · 自我反思</p>
          <h2>把掌心里的线索，翻译成更贴近日常的提醒。</h2>
          <p>
            上传一张清晰掌心照片，生成面向生活、学习、事业与关系的手相报告。高级东方玄学的仪式感，配上现代 AI 的分析速度。
          </p>
        </div>
        <div className="hero-orbit" aria-hidden="true">
          <div className="palm-mark">掌</div>
        </div>
      </section>

      <section className="workspace">
        <div className="upload-card">
          <div className="section-label">01 · 请先生看掌</div>
          <h3>上传掌心照片</h3>
          <p>掌心完整入镜、光线充足、纹路清晰。左右手不知道也没关系。</p>

          <label className="drop-zone">
            {preview ? <img src={preview} alt="掌心照片预览" /> : <span>点击选择照片</span>}
            <input type="file" accept="image/png,image/jpeg,image/webp" onChange={onPickFile} />
          </label>

          <div className="segmented">
            {(["left", "right", "unknown"] as HandSide[]).map((side) => (
              <button key={side} className={handSide === side ? "active" : ""} onClick={() => setHandSide(side)}>
                {handText[side]}
              </button>
            ))}
          </div>

          <button className="primary-action" disabled={!ready || Boolean(busyText)} onClick={startReport}>
            {busyText || "生成手相报告"}
          </button>
          {error ? <p className="error">{error}</p> : null}
        </div>

        <div className="archive-card">
          <div className="section-label">02 · 解读档案</div>
          <div className="stats">
            <Stat label="累计报告" value={reports.length} />
            <Stat label="已完成" value={completedReports} />
          </div>
          <div className="report-list">
            {reports.length ? (
              reports.slice(0, 6).map((item) => (
                <button key={item.id} className="archive-item" onClick={() => openReport(item.id)}>
                  <span>
                    <strong>手相报告</strong>
                    <small>{formatDate(item.created_at)}</small>
                  </span>
                  <em>{statusText[item.status]}</em>
                </button>
              ))
            ) : (
              <p className="empty">暂无档案。生成第一份报告后会出现在这里。</p>
            )}
          </div>
        </div>
      </section>

      {activeReport ? (
        <ReportPanel
          report={activeReport}
          onDelete={() => deleteReport(activeReport.id)}
        />
      ) : null}
    </main>
  );
}

function ReportPanel({
  report,
  onDelete,
}: {
  report: Report;
  onDelete: () => void;
}) {
  const data = report.report_data;
  const score = useMemo(() => getScore(data), [data]);
  if (!data) {
    return (
      <section className="report-panel">
        <h3>{statusText[report.status]}</h3>
        <p>{report.error_message || "先生正在整理报告。"}</p>
      </section>
    );
  }

  return (
    <section className="report-panel">
      <div className="report-hero">
        <div>
          <p className="section-label">PALM REPORT · {handText[report.hand_side]}</p>
          <h3>赛博先生手相报告</h3>
          <p>{data.overall_summary}</p>
        </div>
        <div className="score">
          <strong>{score}</strong>
          <span>/100</span>
        </div>
      </div>

      <div className="keywords">
        {data.lucky_keywords.map((word) => (
          <span key={word}>{word}</span>
        ))}
      </div>

      <div className="dimension-grid">
        {data.dimensions.map((dimension, index) => (
          <DimensionCard key={`${dimension.name}-${index}`} dimension={dimension} index={index} />
        ))}
      </div>

      <div className="summary-grid">
        <SummaryList title="优势倾向" items={data.strengths} />
        <SummaryList title="需要留意" items={data.challenges} />
        <SummaryList title="近期建议" items={data.suggestions} />
      </div>

      <p className="disclaimer">{data.disclaimer}</p>
      <button className="delete-action" onClick={onDelete}>删除这份报告</button>
    </section>
  );
}

function DimensionCard({ dimension, index }: { dimension: Dimension; index: number }) {
  return (
    <article className="dimension-card">
      <div className="dimension-head">
        <span>0{index + 1}</span>
        <strong>{dimension.name}</strong>
        <em>{Math.round(dimension.confidence * 100)}%</em>
      </div>
      <p>{dimension.interpretation}</p>
      <div className="observations">
        {dimension.observations.map((item) => (
          <span key={item}>{item}</span>
        ))}
      </div>
      <div className="advice">先生建议：{dimension.advice}</div>
    </article>
  );
}

function SummaryList({ title, items }: { title: string; items: string[] }) {
  return (
    <article className="summary-list">
      <h4>{title}</h4>
      {items.map((item) => (
        <p key={item}>{item}</p>
      ))}
    </article>
  );
}

function Stat({ label, value }: { label: string; value: number }) {
  return (
    <div className="stat">
      <strong>{value}</strong>
      <span>{label}</span>
    </div>
  );
}

function getScore(data?: ReportData | null) {
  if (!data?.dimensions?.length) return 68;
  const average = data.dimensions.reduce((sum, item) => sum + item.confidence, 0) / data.dimensions.length;
  const quality = data.quality_check?.confidence || 0.7;
  return Math.max(60, Math.min(96, Math.round((average * 0.65 + quality * 0.35) * 100)));
}

function formatDate(value: string) {
  return value.replace("T", " ").slice(0, 16);
}

function sleep(ms: number) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}
