import { useMemo } from "react";
import { Link, useParams, useSearchParams } from "react-router-dom";
import { useQuery } from "@tanstack/react-query";
import { PackageOpen, RefreshCw } from "lucide-react";
import {
  getPublicationPoint,
  listPublicationPointObjects,
} from "../api/service";
import { CopyableValue } from "../components/CopyableValue";
import { KpiCard } from "../components/KpiCard";
import {
  objectFiltersFromParams,
  objectFiltersToParams,
  ObjectsTable,
  type ObjectFilterValues,
} from "../components/ObjectsTable";
import { PageHeader } from "../components/PageHeader";
import { Panel } from "../components/Panel";
import { StatusPill } from "../components/StatusPill";
import { WorkflowStatus } from "../components/WorkflowStatus";
import { ErrorBlock, LoadingBlock, Notice } from "../components/StateBlock";
import { formatDurationMs, formatInt, formatUtc } from "../lib/format";
import { withRunParam } from "../lib/run";
import { useExportJob } from "../lib/useExportJob";
import { useRun } from "../lib/useRun";

export default function PublicationPointDetailPage() {
  const { ppId = "" } = useParams();
  const { runId } = useRun();
  const [searchParams, setSearchParams] = useSearchParams();
  // Object filters live in the URL so they survive reloads and stay shareable.
  const objectFilters = useMemo(() => objectFiltersFromParams(searchParams), [searchParams]);

  const setObjectFilters = (next: ObjectFilterValues) => {
    setSearchParams(objectFiltersToParams(next, searchParams), { preventScrollReset: true });
  };

  const ppQuery = useQuery({
    queryKey: ["pp", runId, ppId],
    queryFn: () => getPublicationPoint(runId, ppId),
  });
  const exportJob = useExportJob(runId, { scope: "publication_point", ppId });

  if (ppQuery.isError) {
    return (
      <div className="page">
        <PageHeader title="Publication point" />
        <ErrorBlock error={ppQuery.error} onRetry={() => ppQuery.refetch()} title="Failed to load publication point" />
      </div>
    );
  }
  if (ppQuery.isPending) {
    return (
      <div className="page">
        <PageHeader title="Publication point" />
        <LoadingBlock />
      </div>
    );
  }

  const pp = ppQuery.data;

  return (
    <div className="page">
      <nav className="breadcrumbs" aria-label="Breadcrumb">
        <Link to={withRunParam("/publication-points", runId)}>Publication Points</Link>
        <span aria-hidden="true">/</span>
        <span className="mono">{pp.ppId}</span>
      </nav>

      <PageHeader
        title={<span className="mono" style={{ fontSize: 16 }}>{pp.manifestRsyncUri ?? pp.ppId}</span>}
        subtitle={pp.repoSyncError ? `Sync error: ${pp.repoSyncError}` : undefined}
        actions={
          <>
            <StatusPill status={pp.repoTerminalState} label={`terminal ${pp.repoTerminalState ?? "unknown"}`} />
            <button
              type="button"
              className="btn"
              onClick={() => exportJob.startMutation.mutate()}
              disabled={exportJob.running}
            >
              {exportJob.startMutation.isPending ? (
                <RefreshCw size={13} aria-hidden="true" />
              ) : (
                <PackageOpen size={13} aria-hidden="true" />
              )}
              Export
            </button>
          </>
        }
      />

      {exportJob.startMutation.isError ? (
        <Notice kind="error">Export failed to start: {exportJob.startMutation.error.message}</Notice>
      ) : null}
      {exportJob.jobQuery.data ? <WorkflowStatus job={exportJob.jobQuery.data} runId={runId} /> : null}

      <div className="kpi-grid">
        <KpiCard label="Objects" value={formatInt(pp.objects)} />
        <KpiCard label="Rejected" value={formatInt(pp.rejectedObjects)} tone="red" />
        <KpiCard label="Warnings" value={formatInt(pp.warnings)} tone="amber" />
        <KpiCard label="Sync time" value={formatDurationMs(pp.repoSyncDurationMs)} />
      </div>

      <Panel title="Publication point details">
        <dl className="meta-grid">
          <dt>PP ID</dt>
          <dd><CopyableValue value={pp.ppId} max={48} label="publication point id" /></dd>
          <dt>Repository</dt>
          <dd>
            <Link to={withRunParam(`/repositories/${encodeURIComponent(pp.repoId)}`, runId)} className="mono">
              {pp.repoId}
            </Link>
          </dd>
          <dt>Manifest URI</dt>
          <dd><CopyableValue value={pp.manifestRsyncUri} max={96} label="manifest URI" /></dd>
          <dt>PP rsync URI</dt>
          <dd><CopyableValue value={pp.publicationPointRsyncUri} max={96} label="publication point rsync URI" /></dd>
          <dt>rsync base</dt>
          <dd><CopyableValue value={pp.rsyncBaseUri} max={96} label="rsync base URI" /></dd>
          <dt>RRDP notification</dt>
          <dd><CopyableValue value={pp.rrdpNotificationUri} max={96} label="RRDP notification URI" /></dd>
          <dt>Sync source</dt>
          <dd>{pp.repoSyncSource ?? pp.source ?? "—"}</dd>
          <dt>Sync phase</dt>
          <dd>{pp.repoSyncPhase ?? "—"}</dd>
          <dt>Terminal state</dt>
          <dd><StatusPill status={pp.repoTerminalState} /></dd>
          <dt>thisUpdate</dt>
          <dd>{formatUtc(pp.thisUpdate)}</dd>
          <dt>nextUpdate</dt>
          <dd>{formatUtc(pp.nextUpdate)}</dd>
        </dl>
      </Panel>

      <Panel title="Objects" flush>
        <ObjectsTable
          runId={runId}
          queryKeyScope={`pp:${ppId}`}
          fetcher={(filters) => listPublicationPointObjects(runId, ppId, filters)}
          filters={objectFilters}
          onFiltersChange={setObjectFilters}
        />
      </Panel>
    </div>
  );
}
