import { useQuery } from "@tanstack/react-query";
import {
  ArrowLeft,
  ArrowUpRight,
  Check,
  ChevronDown,
  Download,
  ExternalLink,
  Github,
  LoaderCircle,
  Shield,
} from "lucide-react";
import { useEffect, useMemo, useState } from "react";
import { Link, useLocation, useParams, useSearchParams } from "react-router-dom";
import { EmptyState } from "../../components/EmptyState";
import { ReportBody } from "../../components/ReportBody";
import { ScanDurationNotice } from "../../components/ScanDurationNotice";
import { SeverityBar } from "../../components/SeverityBar";
import { SeverityChip } from "../../components/SeverityChip";
import { ScanningSpinner, StatusBadge } from "../../components/StatusBadge";
import { api, apiUrl } from "../../shared/api/client";
import { useMe } from "../auth/useAuth";
import { OwnerFindings } from "./OwnerFindings";
import { VersionBar, type ViewJob } from "./VersionBar";
import { formatDate, formatStars, shortSha, totalFindings } from "../../shared/lib/format";

export function ProjectPage() {
  const [openKey, setOpenKey] = useState<string | null>(null);
  const { owner = "", repo = "" } = useParams();
  const [params, setParams] = useSearchParams();
  const tabParam = params.get("tab");
  const location = useLocation();
  const justSubmitted = Boolean(
    (location.state as { justSubmitted?: boolean } | null)?.justSubmitted,
  );

  const projectQ = useQuery({
    queryKey: ["public", "project", owner, repo],
    queryFn: () => api.getProject(owner, repo),
    enabled: Boolean(owner && repo),
    refetchInterval: (q) => {
      const s = q.state.data?.latest_scan?.state;
      if (s === "queued" || s === "dispatching" || s === "scanning") return 5000;
      return false;
    },
  });

  const project = projectQ.data;
  const meQ = useMe();
  // owner 探测：登录后尝试拉取全量 findings；200=有权限（显示 Manage findings tab），401/403=公众视图
  const ownerQ = useQuery({
    queryKey: ["owner-findings", project?.id],
    queryFn: () => api.ownerFindings(project!.id),
    enabled: Boolean(project?.id) && meQ.data?.authenticated === true,
    retry: false,
    staleTime: 30_000,
  });
  const isOwner = ownerQ.isSuccess;
  // 版本查看状态（fish No.1253：切换操作上移到头部）
  const [viewJob, setViewJob] = useState<ViewJob | null>(null);
  // Details 与 Manage findings 合并为 Findings（fish No.1252）；tab=details 兼容旧链接
  const tab = tabParam === "findings" || tabParam === "details" ? "findings" : "overview";
  const cweMax = useMemo(() => {
    const list = project?.cwe_distribution ?? [];
    return Math.max(1, ...list.map((c) => c.count));
  }, [project]);

  if (projectQ.isLoading) {
    return <ScanProgressPage owner={owner} repo={repo} state="loading" />;
  }

  if (projectQ.isError || !project) {
    return (
      <div className="mx-auto max-w-6xl px-6 py-16">
        <EmptyState
          icon={Shield}
          title="Project not found"
          description="This project is not on OpenVuln yet."
          action={
            <Link to="/#projects" className="text-sm text-accent-600 hover:underline">
              Back to projects
            </Link>
          }
        />
      </div>
    );
  }

  const state = project.latest_scan?.state;
  const scanning = state === "scanning" || state === "dispatching";
  const soFar = project.latest_scan?.findings_so_far ?? 0;
  const findingsTotal = totalFindings(project.severity_counts);

  if (state === "queued" || scanning) {
    return (
      <ScanProgressPage
        owner={project.owner_login}
        repo={project.name}
        htmlUrl={project.html_url}
        branch={project.default_branch}
        state={state}
        findingsSoFar={soFar}
        justSubmitted={justSubmitted}
      />
    );
  }

  return (
    <div className="mx-auto max-w-6xl px-6 py-8">
      <Link
        to="/#projects"
        className="inline-flex items-center gap-1.5 text-[13px] text-ink-secondary hover:text-ink"
      >
        <ArrowLeft size={14} /> Projects
      </Link>

      {justSubmitted && (
        <div
          className="mt-4 rounded-md border border-accent-100 bg-accent-50 px-4 py-3 text-sm text-accent-700"
          role="status"
        >
          Added to the scan queue.
        </div>
      )}

      {/* Header */}
      <div className="mt-4 border-b border-line pb-6">
        <div className="flex flex-wrap items-center gap-2">
          <h1 className="font-display text-xl font-semibold tracking-tight">
            <span className="text-ink-secondary">{project.owner_login}</span>
            <span className="text-ink-tertiary"> / </span>
            <span className="text-ink">{project.name}</span>
          </h1>
          <a
            href={project.html_url}
            target="_blank"
            rel="noreferrer"
            className="inline-flex items-center text-ink-secondary hover:text-accent-600"
            title="View on GitHub"
          >
            <ExternalLink size={14} />
          </a>
        </div>
        {project.description && (
          <p className="mt-2 max-w-prose text-sm text-ink-secondary">{project.description}</p>
        )}
        <div className="mt-2 flex flex-wrap items-center gap-x-2 gap-y-1 text-[13px] text-ink-tertiary">
          {project.language && (
            <span className="inline-flex items-center gap-1">
              <span className="h-1.5 w-1.5 rounded-full bg-accent-600/70" />
              {project.language}
            </span>
          )}
          <span>·</span>
          <span>★ {formatStars(project.stars)}</span>
          <span>·</span>
          <span>Added {formatDate(project.created_at)}</span>
        </div>
        {isOwner && (
          <div className="mt-3">
            <VersionBar projectId={project.id} viewJob={viewJob} onViewJob={setViewJob} />
          </div>
        )}
      </div>

      {/* Tabs */}
      <div className="mt-4 flex gap-1 border-b border-line">
        <TabButton active={tab === "overview"} onClick={() => setParams({})}>
          Overview
        </TabButton>
        <TabButton active={tab === "findings"} onClick={() => setParams({ tab: "findings" })}>
          Findings
        </TabButton>
      </div>

      {tab === "overview" && (
        <div className="py-6">
          <div className="flex flex-wrap items-center gap-x-3 gap-y-2 text-sm">
            <StatusBadge state={state} finishedAt={project.latest_scan?.finished_at} />
            {project.latest_scan?.finished_at && (
              <span className="text-ink-secondary">
                {formatDate(project.latest_scan.finished_at)}
              </span>
            )}
            {project.latest_scan?.commit_sha && (
              <a
                href={`${project.html_url}/commit/${project.latest_scan.commit_sha}`}
                target="_blank"
                rel="noreferrer"
                className="inline-flex items-center gap-0.5 font-mono text-[13px] text-ink-secondary hover:text-accent-600"
              >
                {shortSha(project.latest_scan.commit_sha)}
                <ArrowUpRight size={12} />
              </a>
            )}
          </div>
          <p className="mt-2 text-[13px] text-ink-secondary">
            {state === "completed" ? "Scanned" : scanning ? "Scanning" : "To be scanned"} by{" "}
            <span className="font-medium text-ink">VulnHunter AI engine</span>
            {project.default_branch ? ` · default branch (${project.default_branch})` : null}
          </p>

          {scanning && (
            <div className="mt-8 space-y-3">
              <ScanningSpinner
                label={
                  soFar > 0
                    ? `Scan in progress — ${soFar} finding${soFar === 1 ? "" : "s"} so far`
                    : "Scan in progress — stats will appear when complete."
                }
              />
              <div className="h-2 w-full max-w-xl animate-pulse rounded-full bg-surface-sunken" />
            </div>
          )}

          {state !== "completed" && !scanning && (
            <p className="mt-8 text-sm text-ink-secondary">This project is in the scan queue.</p>
          )}

          {state === "completed" && (
            <>
              <section className="mt-8">
                <p className="font-mono text-[11px] uppercase tracking-wider text-ink-tertiary">
                  Scan results
                </p>
                <h2 className="mt-1 font-display text-base font-semibold text-ink">
                  Findings overview
                </h2>
                {findingsTotal === 0 ? (
                  <p className="mt-3 max-w-prose text-sm text-ink-secondary">
                    No findings were confirmed in this scan. A clean scan does not prove a project is
                    free of vulnerabilities.
                  </p>
                ) : (
                  <>
                    <p className="mt-3 text-sm font-medium text-ink">
                      {findingsTotal} finding{findingsTotal === 1 ? "" : "s"} found
                    </p>
                    <div className="mt-4">
                      <SeverityBar
                        counts={project.severity_counts}
                        widthClass="w-full max-w-[80%]"
                        heightClass="h-2"
                      />
                    </div>
                  </>
                )}
              </section>

              {project.cwe_distribution.length > 0 && (
                <section className="mt-10">
                  <h2 className="font-display text-base font-semibold text-ink">
                    Top CWE categories
                  </h2>
                  <ul className="mt-4 max-w-[80%] space-y-2.5">
                    {project.cwe_distribution.slice(0, 5).map((c) => (
                      <li key={c.cwe} className="flex items-center gap-3 text-sm">
                        <a
                          href={`https://cwe.mitre.org/data/definitions/${c.cwe.replace(/^CWE-/i, "")}.html`}
                          target="_blank"
                          rel="noreferrer"
                          className="w-24 shrink-0 font-mono text-[13px] text-accent-700 hover:underline"
                        >
                          {c.cwe}
                        </a>
                        <div className="h-1.5 flex-1 overflow-hidden rounded-full bg-surface-sunken">
                          <div
                            className="h-full rounded-full bg-ink/40"
                            style={{ width: `${(c.count / cweMax) * 100}%` }}
                          />
                        </div>
                        <span className="w-8 text-right font-mono text-[13px] text-ink-secondary">
                          {c.count}
                        </span>
                      </li>
                    ))}
                  </ul>
                </section>
              )}

              <div className="mt-10 rounded-md border border-line bg-surface-raised p-5">
                <p className="text-sm leading-relaxed text-ink-secondary">
                  Detailed findings are visible to signed-in repository maintainers. Maintainers
                  review the full reports and choose what to disclose publicly.
                </p>
              </div>

              {project.disclosed_findings.length > 0 && (
                <section className="mt-10">
                  <div className="flex flex-wrap items-center justify-between gap-2">
                    <h2 className="font-display text-base font-semibold text-ink">
                      Disclosed findings
                    </h2>
                    <div className="flex items-center gap-3 text-[13px]">
                      <a
                        href={apiUrl(`/api/projects/${project.id}/report?format=zip`)}
                        className="inline-flex items-center gap-1 text-ink-secondary hover:text-accent-600"
                      >
                        <Download size={14} /> Download all (zip)
                      </a>
                    </div>
                  </div>
                  <div className="mt-3 overflow-hidden rounded-md border border-line">
                    <table className="w-full table-fixed text-left text-sm">
                      <thead className="border-b border-line bg-surface-sunken/50 text-xs uppercase tracking-wide text-ink-secondary">
                        <tr>
                          <th className="w-[92px] px-3 py-2.5 font-medium">Sev</th>
                          <th className="px-3 py-2.5 font-medium">Title</th>
                          <th className="w-[112px] px-3 py-2.5 font-medium">CWE</th>
                          <th className="w-[120px] px-3 py-2.5 font-medium">Status</th>
                          <th className="w-[52px] px-3 py-2.5 font-medium" />
                        </tr>
                      </thead>
                      <tbody>
                        {project.disclosed_findings.map((f) => (
                          <tr key={f.id} className="border-b border-line last:border-0">
                            <td className="px-3 py-3">
                              <SeverityChip severity={f.severity} />
                            </td>
                            <td className="max-w-0 truncate px-3 py-3 font-medium text-ink" title={f.title}>
                              {f.title}
                            </td>
                            <td className="px-3 py-3 font-mono text-[13px] text-ink-secondary">
                              {f.cwe ?? "—"}
                            </td>
                            <td className="px-3 py-3 text-[13px] text-success">Disclosed</td>
                            <td className="px-3 py-3 text-right">
                              <a
                                href={apiUrl(`/api/projects/${project.id}/report/${encodeURIComponent(f.finding_key)}`)}
                                className="text-ink-tertiary hover:text-accent-600"
                                title="Download full report (markdown)"
                                download
                              >
                                <Download size={14} className="inline" />
                              </a>
                            </td>
                          </tr>
                        ))}
                      </tbody>
                    </table>
                  </div>
                </section>
              )}
            </>
          )}
        </div>
      )}

      {tab === "findings" && !isOwner && (
        <div className="space-y-4 py-6">
          {project.disclosed_findings.length === 0 ? (
            <div className="rounded-md border border-line bg-surface-raised p-6">
              <h2 className="font-display text-base font-semibold text-ink">
                No disclosures yet
              </h2>
              <p className="mt-2 w-full text-sm leading-relaxed text-ink-secondary">
                Full finding details are visible to repository maintainers after sign-in. Disclosed
                findings appear here with the full report content, and on the Overview tab.
              </p>
            </div>
          ) : (
            project.disclosed_findings.map((f) => {
              const open = openKey === f.id;
              return (
                <article
                  key={f.id}
                  className="overflow-hidden rounded-md border border-line bg-surface-raised"
                >
                  <div
                    role="button"
                    tabIndex={0}
                    onClick={() => setOpenKey(open ? null : f.id)}
                    onKeyDown={(e) => {
                      if (e.key === "Enter" || e.key === " ") {
                        e.preventDefault();
                        setOpenKey(open ? null : f.id);
                      }
                    }}
                    aria-expanded={open}
                    className="flex w-full cursor-pointer items-start gap-3 px-5 py-4 text-left transition-colors hover:bg-surface-sunken/50 focus-ring sm:px-6"
                  >
                    <div className="min-w-0 flex-1 space-y-2">
                      <div className="flex flex-wrap items-center gap-2">
                        <SeverityChip severity={f.severity} />
                        {f.cwe && (
                          <span className="font-mono text-[12px] text-ink-secondary">{f.cwe}</span>
                        )}
                        <span className="text-[12px] text-success">Disclosed</span>
                      </div>
                      <h3
                        className="line-clamp-2 font-display text-[15px] font-semibold leading-snug text-ink"
                        title={f.title}
                      >
                        {f.title}
                      </h3>
                      <p className="font-mono text-[11px] text-ink-tertiary">{f.finding_key}</p>
                    </div>
                    <span className="flex shrink-0 items-center gap-2 self-center">
                      <a
                        href={apiUrl(`/api/projects/${project.id}/report/${encodeURIComponent(f.finding_key)}`)}
                        className="inline-flex items-center gap-1.5 rounded-md border border-line px-2.5 py-1.5 text-xs font-medium text-ink-secondary hover:border-accent-300 hover:text-accent-700"
                        download
                        onClick={(e) => e.stopPropagation()}
                        title="Download full report (markdown)"
                      >
                        <Download size={14} />
                        .md
                      </a>
                      <ChevronDown
                        size={16}
                        className={`text-ink-tertiary transition-transform ${open ? "rotate-180" : ""}`}
                      />
                    </span>
                  </div>
                  {open && (
                    <div className="border-t border-line px-5 pb-5 sm:px-6 sm:pb-6">
                      {f.report ? (
                        <ReportBody report={f.report} />
                      ) : (
                        <p className="mt-4 text-sm text-ink-tertiary">
                          Structured report is not available for this disclosure (older
                          summary-only disclose). Use the download button if a fidelity pack was
                          attached later.
                        </p>
                      )}
                    </div>
                  )}
                </article>
              );
            })
          )}
        </div>
      )}

      {tab === "findings" && isOwner && (
        <div className="py-6">
          <OwnerFindings
            projectId={project.id}
            currentFindings={ownerQ.data?.findings ?? []}
            viewJob={viewJob}
            onViewJob={setViewJob}
          />
        </div>
      )}
    </div>
  );
}

function ScanProgressPage({
  owner,
  repo,
  htmlUrl,
  branch,
  state,
  findingsSoFar = 0,
  justSubmitted = false,
}: {
  owner: string;
  repo: string;
  htmlUrl?: string;
  branch?: string | null;
  state: "loading" | "queued" | "dispatching" | "scanning";
  findingsSoFar?: number;
  justSubmitted?: boolean;
}) {
  useEffect(() => {
    document.body.classList.add("openvuln-running");
    return () => document.body.classList.remove("openvuln-running");
  }, []);

  const queued = state === "queued";
  const loading = state === "loading";
  const dispatching = state === "dispatching";
  const currentStage = queued ? 0 : dispatching ? 1 : 2;
  const stages = ["Queued", "Preparing", "Scanning", "Results"];
  const statusLabel = loading
    ? "Loading scan status"
    : queued
      ? "Waiting in scan queue"
      : dispatching
        ? "Preparing the scan"
        : "AI security analysis in progress";
  const detail = loading
    ? "Retrieving the latest status…"
    : queued
      ? "The repository is queued and will start automatically when a scanner is available."
      : dispatching
        ? "OpenVuln is packaging the repository and handing it to an available scanner."
        : findingsSoFar > 0
          ? `${findingsSoFar} confirmed finding${findingsSoFar === 1 ? "" : "s"} so far. Analysis is still running.`
          : "VulnHunter is analyzing the repository. Results will appear after the scan completes.";

  return (
    <div className="fixed inset-0 z-50 overflow-y-auto bg-surface text-ink">
      <div className="openvuln-glow pointer-events-none absolute inset-0 -z-10" />

      <header className="flex items-center justify-between px-5 py-5 sm:px-8 sm:py-7">
        <Link
          to="/"
          className="inline-flex items-center gap-2 rounded-full border border-line bg-surface-raised px-3.5 py-2 text-xs font-medium text-ink-secondary transition hover:border-line-strong hover:bg-surface-sunken hover:text-ink focus-ring"
        >
          <ArrowLeft size={14} />
          OpenVuln
        </Link>
        {htmlUrl && (
          <a
            href={htmlUrl}
            target="_blank"
            rel="noreferrer"
            className="inline-flex items-center gap-2 rounded-full border border-line bg-surface-raised px-3.5 py-2 text-xs font-medium text-ink-secondary transition hover:border-line-strong hover:bg-surface-sunken hover:text-ink focus-ring"
          >
            <Github size={14} />
            GitHub
          </a>
        )}
      </header>

      <main className="mx-auto flex min-h-[calc(100vh-88px)] w-full max-w-4xl flex-col items-center justify-center px-5 pb-16 pt-8 text-center sm:px-8">
        <div className="openvuln-brand flex h-16 w-16 items-center justify-center rounded-2xl border border-line bg-surface-raised shadow-[0_20px_56px_-20px_rgba(0,0,0,0.7)]">
          <LoaderCircle
            size={28}
            className="animate-spin text-accent-600 motion-reduce:animate-none"
            strokeWidth={1.7}
          />
        </div>

        <p className="mt-7 font-mono text-[11px] uppercase tracking-[0.22em] text-ink-tertiary">
          {justSubmitted ? "Repository added" : "Live scan status"}
        </p>
        <h1 className="openvuln-title mt-3 text-balance font-display text-3xl font-medium leading-tight sm:text-5xl">
          {statusLabel}
        </h1>

        <div className="mt-5 flex flex-wrap items-center justify-center gap-2 text-sm text-ink-secondary">
          <span className="text-ink">{owner}</span>
          <span className="text-ink-tertiary">/</span>
          <span className="text-ink">{repo}</span>
          {branch && (
            <>
              <span className="text-ink-tertiary">·</span>
              <span className="font-mono text-xs text-ink-tertiary">{branch}</span>
            </>
          )}
        </div>

        <div className="openvuln-composer mt-9 w-full max-w-2xl rounded-2xl border border-line bg-surface-raised px-5 py-5 text-left shadow-[0_24px_64px_-24px_rgba(0,0,0,0.7)] sm:px-6">
          <div className="flex items-center gap-3">
            <span className="relative flex h-2.5 w-2.5 shrink-0">
              <span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-accent-600 opacity-40 motion-reduce:animate-none" />
              <span className="relative inline-flex h-2.5 w-2.5 rounded-full bg-accent-600" />
            </span>
            <p className="text-sm font-medium text-ink">{statusLabel}</p>
          </div>
          <p className="mt-3 text-sm leading-6 text-ink-secondary">{detail}</p>
          {!loading && (
            <div className="mt-5 border-t border-line pt-4">
              <div className="flex items-center justify-between text-xs text-ink-tertiary">
                <span>Current stage</span>
                <span>
                  {currentStage + 1} of {stages.length}
                </span>
              </div>
              <ol className="mt-3 grid grid-cols-4 gap-2" aria-label="Scan stages">
                {stages.map((stageLabel, index) => {
                  const complete = index < currentStage;
                  const current = index === currentStage;
                  return (
                    <li
                      key={stageLabel}
                      className={`flex min-w-0 flex-col items-center gap-2 rounded-xl border px-2 py-3 text-center ${
                        current
                          ? "border-accent-200 bg-accent-50 text-ink"
                          : complete
                            ? "border-line bg-surface-sunken text-ink-secondary"
                            : "border-line bg-surface text-ink-tertiary"
                      }`}
                      aria-current={current ? "step" : undefined}
                    >
                      <span
                        className={`flex h-6 w-6 items-center justify-center rounded-full border text-[11px] ${
                          current
                            ? "border-transparent bg-ink text-surface"
                            : complete
                              ? "border-line bg-surface text-ink-secondary"
                              : "border-line text-ink-tertiary"
                        }`}
                      >
                        {complete ? <Check size={13} strokeWidth={2.2} /> : index + 1}
                      </span>
                      <span className="truncate text-[11px] font-medium sm:text-xs">
                        {stageLabel}
                      </span>
                    </li>
                  );
                })}
              </ol>
              <p className="mt-3 text-xs text-ink-tertiary">
                This shows status stages, not elapsed-time progress. Refreshes every 5 seconds.
              </p>
            </div>
          )}
        </div>

        <ScanDurationNotice className="mt-4 w-full max-w-2xl" />
      </main>
    </div>
  );
}

function TabButton({
  active,
  onClick,
  children,
}: {
  active: boolean;
  onClick: () => void;
  children: React.ReactNode;
}) {
  return (
    <button
      type="button"
      onClick={onClick}
      className={`-mb-px inline-flex items-center border-b-2 px-3 py-2.5 text-sm font-medium transition-colors focus-ring ${
        active
          ? "border-accent-600 text-accent-700"
          : "border-transparent text-ink-secondary hover:text-ink"
      }`}
    >
      {children}
    </button>
  );
}
