import { useEffect, useState } from "react";
import { Link, useNavigate, useParams } from "react-router-dom";
import { PageHeader } from "../components/layout/PageHeader";
import { Badge, Button, Card, EmptyState } from "../components/ui";
import { useData, useRepos } from "../data/DataContext";
import { useJobLive } from "../data/JobLiveContext";
import type { Job } from "../domain/types";
import { useI18n } from "../i18n/I18nContext";
import { useFormatApiError } from "../lib/apiErrors";
import {
  canDeleteJob,
  isRecurringTokenRenew,
  jobStatusLabel,
  jobStatusTone,
  jobSubtitle,
  jobTemplateLabel,
} from "../lib/jobLabels";
import {
  parseComposeMimicResultPayload,
  saveComposeDraftBody,
} from "../lib/composeBridge";
import { formatLocalDateTime } from "../lib/time";

export function JobDetailPage() {
  const { id } = useParams();
  const navigate = useNavigate();
  const repos = useRepos();
  const { refresh, tick } = useData();
  const { jobs: liveJobs, revision } = useJobLive();
  const { t } = useI18n();
  const formatApiError = useFormatApiError();
  const [job, setJob] = useState<Job | null>(null);
  const [deleting, setDeleting] = useState(false);
  const [error, setError] = useState("");
  const [loading, setLoading] = useState(true);
  const [loadFailed, setLoadFailed] = useState(false);
  const [applying, setApplying] = useState(false);
  const displayedJobStatus = job?.status;
  const isActive =
    displayedJobStatus === "pending" ||
    displayedJobStatus === "queued" ||
    displayedJobStatus === "running";
  const needsPayload = displayedJobStatus === "succeeded" && !job?.payload;

  useEffect(() => {
    if (!id) return;
    const fromLive = liveJobs.find((j) => j.id === id);
    if (fromLive) {
      setJob(fromLive);
      setLoading(false);
      setLoadFailed(false);
      return;
    }
    void repos.jobs
      .get(id)
      .then((j) => {
        setJob(j);
        setLoadFailed(false);
      })
      .catch((e: unknown) => {
        // 讀不到跟「這個任務不存在」是兩件事，分開記才不會謊稱找不到。
        setLoadFailed(true);
        setError(formatApiError(e, "jobs.detailLoadFail"));
      })
      .finally(() => setLoading(false));
  }, [id, repos.jobs, tick, liveJobs, revision, formatApiError]);

  // 進行中：額外直接 get，避免 list 延遲
  useEffect(() => {
    if (!id || !isActive) return;
    // 只看 isActive，不看整個 job：否則每次輪詢寫回新物件都會重建 interval，計時器一直被歸零。
    const timer = window.setInterval(() => {
      void repos.jobs.get(id).then(
        (j) => {
          if (j) setJob(j);
        },
        () => {},
      );
    }, 1500);
    return () => window.clearInterval(timer);
  }, [id, isActive, repos.jobs]);

  // succeeded 但 list 可能沒 payload → 補 get
  useEffect(() => {
    if (!id || !needsPayload) return;
    void repos.jobs.get(id).then(
      (j) => {
        if (j) setJob(j);
      },
      () => {},
    );
  }, [id, needsPayload, repos.jobs]);

  useEffect(() => {
    if (!id || !displayedJobStatus) return;
    let cancelled = false;
    const acknowledge = async () => {
      const list = await repos.notifications.list();
      if (cancelled) return;
      const unread = list.filter(
        (notification) =>
          !notification.read_at && notification.ref_type === "job" && notification.ref_id === id,
      );
      if (!unread.length) return;
      await Promise.all(unread.map((notification) => repos.notifications.markRead(notification.id)));
      if (!cancelled) window.dispatchEvent(new Event("harbor:store"));
    };
    void acknowledge().catch(() => {});
    const retry = window.setTimeout(() => void acknowledge().catch(() => {}), 1000);
    return () => {
      cancelled = true;
      window.clearTimeout(retry);
    };
  }, [id, displayedJobStatus, repos.notifications]);

  useEffect(() => {
    const onStore = () => refresh();
    window.addEventListener("harbor:store", onStore);
    return () => window.removeEventListener("harbor:store", onStore);
  }, [refresh]);

  async function applyMimicToCompose() {
    if (!job || job.template_type !== "compose_mimic") return;
    setApplying(true);
    setError("");
    try {
      let payload = job.payload;
      if (!payload) {
        const full = await repos.jobs.get(job.id);
        payload = full?.payload;
      }
      const text = parseComposeMimicResultPayload(payload);
      if (!text) {
        setError(t("jobs.mimicNoResult"));
        return;
      }
      saveComposeDraftBody(text);
      navigate("/app/studio?tab=compose");
    } catch (e) {
      setError(formatApiError(e, "jobs.mimicApplyFail"));
    } finally {
      setApplying(false);
    }
  }

  async function removeJob() {
    if (!job || !canDeleteJob(job)) {
      setError(t("jobs.deleteRunningHint"));
      return;
    }
    const name = jobTemplateLabel(job.template_type, t);
    if (!window.confirm(t("jobs.deleteConfirm", { name }))) return;
    setDeleting(true);
    setError("");
    try {
      await repos.jobs.remove(job.id);
      refresh();
      navigate("/app/jobs");
    } catch (e) {
      setError(formatApiError(e, "jobs.deleteFail"));
    } finally {
      setDeleting(false);
    }
  }

  if (!job && loading) {
    return <EmptyState title={t("common.loading")} />;
  }

  if (!job && loadFailed) {
    return (
      <>
        <p className="hb-banner-error" role="alert">
          {error || t("jobs.detailLoadFail")}
        </p>
        <Link to="/app/jobs" className="hb-btn hb-btn--ghost">
          {t("common.back")}
        </Link>
      </>
    );
  }

  if (!job) {
    return (
      <EmptyState
        title={t("jobs.notFound")}
        action={
          <Link to="/app/jobs" className="hb-btn hb-btn--ghost">{t("common.back")}</Link>
        }
      />
    );
  }

  return (
    <>
      <PageHeader title={jobTemplateLabel(job.template_type, t)} description={job.id} />
      <Card>
        <div className="hb-stack">
          <div style={{ display: "flex", flexWrap: "wrap", gap: "0.5rem" }}>
            {isRecurringTokenRenew(job) ? (
              <Badge tone="brand">{t("jobs.template.tokenRenewBadge")}</Badge>
            ) : null}
            <Badge tone={jobStatusTone(job.status)}>{jobStatusLabel(job.status, t)}</Badge>
          </div>
          <p>{jobSubtitle(job, t, formatLocalDateTime)}</p>
          <div className="hb-progress">
            <div className="hb-progress__bar" style={{ width: `${job.progress_percent}%` }} />
          </div>
          <p className="text-muted">{t("jobs.progress", { n: job.progress_percent })}</p>
          <p className="text-muted">
            {t("jobs.updated", { time: formatLocalDateTime(job.updated_at) })}
          </p>
          {job.status === "succeeded" || job.status === "failed" || job.status === "cancelled" ? (
            <p className="text-muted" style={{ fontSize: "var(--hb-text-sm)" }}>
              {t("jobs.retentionHint")}
            </p>
          ) : null}
          {error ? (
            <p className="hb-form-error" role="alert">
              {error}
            </p>
          ) : null}
          {job.error ? <p className="hb-form-error">{job.error}</p> : null}
          {job.template_type === "compose_mimic" && job.status === "succeeded" ? (
            <p className="text-muted" style={{ fontSize: "var(--hb-text-sm)", margin: 0 }}>
              {t("jobs.mimicApplyHint")}
            </p>
          ) : null}
          <div className="hb-wizard-actions">
            {job.template_type === "compose_mimic" && job.status === "succeeded" ? (
              <Button type="button" disabled={applying} onClick={() => void applyMimicToCompose()}>
                {applying ? t("common.loading") : t("jobs.mimicApplyCompose")}
              </Button>
            ) : null}
            {job.template_type === "compose_mimic" ? (
              <Link to="/app/studio?tab=compose" className="hb-btn hb-btn--secondary">
                {t("jobs.backCompose")}
              </Link>
            ) : null}
            {canDeleteJob(job) ? (
              <Button
                variant="secondary"
                type="button"
                disabled={deleting}
                onClick={() => void removeJob()}
              >
                {deleting ? t("common.loading") : t("jobs.delete")}
              </Button>
            ) : null}
            <Link to="/app/jobs" className="hb-btn hb-btn--ghost">{t("jobs.backList")}</Link>
          </div>
        </div>
      </Card>
    </>
  );
}
