"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: "失败",
};

const services = [
  {
    id: "palm",
    name: "手相",
    title: "掌心解读",
    description: "上传掌心照片，生成生活、学习、事业与关系提醒。",
    status: "已开放",
  },
  {
    id: "face",
    name: "面相",
    title: "气色与五官",
    description: "未来支持面部特征与状态观察，适合做日常运势入口。",
    status: "规划中",
  },
  {
    id: "bazi",
    name: "八字",
    title: "生辰格局",
    description: "未来支持出生信息推演，沉淀长期个人档案。",
    status: "规划中",
  },
];

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);
  const [activeView, setActiveView] = useState<"home" | "palm" | "archive">("home");
  const [activeJobId, setActiveJobId] = useState("");

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

  useEffect(() => {
    return () => {
      if (preview) URL.revokeObjectURL(preview);
    };
  }, [preview]);

  const completedReports = reports.filter((item) => item.status === "completed").length;
  const latestReport = reports[0];
  const hasActiveJob = Boolean(activeJobId);

  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);
      const report = await apiFetch<Report>("/reports", {
        method: "POST",
        body: JSON.stringify({ image_id: upload.image_id, hand_side: handSide }),
      });
      setActiveReport(report);
      setActiveJobId(report.id);
      setBusyText("");
      setFile(null);
      setPreview("");
      void pollReport(report.id)
        .then(() => loadReports())
        .catch((err) => setError(err instanceof Error ? err.message : "报告生成失败"))
        .finally(() => setActiveJobId(""));
      await loadReports();
    } catch (err) {
      setError(err instanceof Error ? err.message : "生成失败");
      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">
      <header className="app-topbar">
        <button className="brand compact-button" onClick={() => setActiveView("home")}>
          <span className="seal">先</span>
          <span>
            <small>CYBER MISTER</small>
            <strong>赛博先生</strong>
          </span>
        </button>
        <nav className="desktop-nav" aria-label="主导航">
          <button className={activeView === "home" ? "active" : ""} onClick={() => setActiveView("home")}>首页</button>
          <button className={activeView === "palm" ? "active" : ""} onClick={() => setActiveView("palm")}>手相</button>
          <button className={activeView === "archive" ? "active" : ""} onClick={() => setActiveView("archive")}>档案</button>
        </nav>
      </header>

      {hasActiveJob ? (
        <button className="job-banner" onClick={() => activeJobId && openReport(activeJobId)}>
          <span className="pulse-dot" />
          <span>先生正在分析掌纹，完成后会自动放入档案。你可以继续浏览。</span>
          <strong>查看进度</strong>
        </button>
      ) : null}

      {activeView === "home" ? (
        <section className="home-screen">
          <div className="hero-copy">
            <p className="eyebrow">AI 玄学档案 · 娱乐占卜 · 自我反思</p>
            <h1>把日常困惑，交给先生慢慢看。</h1>
            <p>从手相开始，逐步扩展到面相、八字与个人长期档案。每一次解读都更贴近生活、学习、事业与关系。</p>
          </div>

          <div className="service-grid">
            {services.map((service) => (
              <button
                key={service.id}
                className={`service-card ${service.id !== "palm" ? "muted" : ""}`}
                onClick={() => service.id === "palm" && setActiveView("palm")}
              >
                <span>{service.status}</span>
                <strong>{service.name}</strong>
                <em>{service.title}</em>
                <small>{service.description}</small>
              </button>
            ))}
          </div>

          <div className="quick-row">
            <button className="primary-action" onClick={() => setActiveView("palm")}>开始手相测试</button>
            <button className="ghost-action" onClick={() => setActiveView("archive")}>
              {latestReport ? "查看最近档案" : "查看档案"}
            </button>
          </div>
        </section>
      ) : null}

      {activeView === "palm" ? (
        <section className="workspace">
          <div className="upload-card">
            <div className="section-label">PALM READING</div>
            <h2>上传掌心照片</h2>
            <p>掌心完整入镜、光线充足、纹路清晰。左右手不确定可以选“不确定”。</p>

            <label className={`drop-zone ${preview ? "has-preview" : ""}`}>
              {preview ? (
                <img src={preview} alt="掌心照片预览" />
              ) : (
                <span>
                  <strong>选择照片</strong>
                  <small>支持 JPG / PNG / WEBP</small>
                </span>
              )}
              <input type="file" accept="image/png,image/jpeg,image/webp" onChange={onPickFile} />
            </label>

            <div className="segmented" aria-label="选择左右手">
              {(["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>

          <aside className="side-panel">
            <div className="mini-card">
              <div className="section-label">生成方式</div>
              <h3>提交后可离开等待</h3>
              <p>照片上传成功后，系统会在后台生成报告。你可以继续看档案，完成后自动刷新。</p>
            </div>
            <div className="mini-card">
              <div className="stats">
                <Stat label="累计报告" value={reports.length} />
                <Stat label="已完成" value={completedReports} />
              </div>
            </div>
          </aside>
        </section>
      ) : null}

      {activeView === "archive" ? (
        <section className="archive-screen">
          <div className="archive-head">
            <div>
              <p className="section-label">MISTER ARCHIVE</p>
              <h2>个人玄学档案</h2>
            </div>
            <button className="ghost-action" onClick={() => setActiveView("palm")}>新建手相</button>
          </div>
          <div className="report-list">
            {reports.length ? (
              reports.map((item) => (
                <button key={item.id} className="archive-item" onClick={() => openReport(item.id)}>
                  <span>
                    <strong>手相报告</strong>
                    <small>{formatDate(item.created_at)}</small>
                    {item.overall_summary ? <b>{item.overall_summary}</b> : null}
                  </span>
                  <em>{statusText[item.status]}</em>
                </button>
              ))
            ) : (
              <p className="empty">暂无档案。生成第一份报告后会出现在这里。</p>
            )}
          </div>
        </section>
      ) : null}

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

      <nav className="mobile-tabbar" aria-label="移动端导航">
        <button className={activeView === "home" ? "active" : ""} onClick={() => setActiveView("home")}>
          <span>⌂</span>
          首页
        </button>
        <button className={activeView === "palm" ? "active" : ""} onClick={() => setActiveView("palm")}>
          <span>掌</span>
          手相
        </button>
        <button className={activeView === "archive" ? "active" : ""} onClick={() => setActiveView("archive")}>
          <span>册</span>
          档案
        </button>
      </nav>
    </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));
}
