import { useEffect, useRef, useState } from "react";
import { Link, useNavigate, useSearchParams } from "react-router-dom";
import { ImageAttach } from "../../components/studio/ImageAttach";
import { Badge, Button, Card, Input, Select, Textarea } from "../../components/ui";
import { useData, useRepos } from "../../data/DataContext";
import { THREADS_REPLY_CONTROLS } from "../../domain/types";
import { useJobLive } from "../../data/JobLiveContext";
import { useI18n } from "../../i18n/I18nContext";
import {
  anyImageUploadFailed,
  anyImageUploading,
  resolvePublishImageUrls,
  type AttachedImage,
} from "../../lib/attachImage";
import { takeComposeDraftBody, takeComposeMimicBridge } from "../../lib/composeBridge";
import {
  fromDatetimeLocalValue,
  nowUnixNano,
  toDatetimeLocalValue,
} from "../../lib/time";

type Props = {
  accountId: string;
  personaId: string;
  personaReady: boolean;
};

function parseMimicResult(payload?: string): string {
  if (!payload) return "";
  try {
    const o = JSON.parse(payload) as { result_text?: string };
    return String(o.result_text ?? "").trim();
  } catch {
    return "";
  }
}

export function ComposerPanel({ accountId, personaId, personaReady }: Props) {
  const repos = useRepos();
  const { refresh } = useData();
  const { jobs, reload: reloadJobs } = useJobLive();
  const { t } = useI18n();
  const navigate = useNavigate();
  const [params] = useSearchParams();

  const [text, setText] = useState("");
  const [title, setTitle] = useState("");
  /** Threads 話題標籤（topic_tag） */
  const [topicTag, setTopicTag] = useState("");
  const [replyControl, setReplyControl] = useState("everyone");
  const [showMimic, setShowMimic] = useState(false);
  const [sourceText, setSourceText] = useState("");
  const [mimicDirection, setMimicDirection] = useState("");
  /** 從「我的貼文」帶來的結構分析備註（仿寫時一併送後端） */
  const [structureNotes, setStructureNotes] = useState("");
  const [images, setImages] = useState<AttachedImage[]>([]);
  /** 預計發送時間（unix nano）；預設現在 */
  const [scheduleAt, setScheduleAt] = useState(() => nowUnixNano());
  /** true＝立即發（送 0 給後端）；手動改 datetime 後為 false */
  const [scheduleImmediate, setScheduleImmediate] = useState(true);
  const [busy, setBusy] = useState("");
  const [message, setMessage] = useState("");
  const bodyLength = [...text].length;
  /** 進行中的仿寫 job id（session 保留，重整後仍可接回） */
  const [mimicJobId, setMimicJobId] = useState(() => {
    try {
      return sessionStorage.getItem("harbor.compose.mimicJobId") || "";
    } catch {
      return "";
    }
  });
  const appliedMimicJob = useRef("");

  function trackMimicJob(id: string) {
    setMimicJobId(id);
    try {
      if (id) sessionStorage.setItem("harbor.compose.mimicJobId", id);
      else sessionStorage.removeItem("harbor.compose.mimicJobId");
    } catch {
      /* ignore */
    }
  }

  useEffect(() => {
    // 0) 從任務詳情「套用到寫一則」帶回來的正文
    const draft = takeComposeDraftBody();
    if (draft) {
      setText(draft);
      setShowMimic(false);
      setMessage(t("compose.mimic.done"));
    }
    // 1) session bridge（我的貼文 → 仿寫，含結構分析）
    const bridge = takeComposeMimicBridge();
    if (bridge?.sourceText) {
      setSourceText(bridge.sourceText);
      setShowMimic(true);
      if (bridge.structureNotes) {
        setStructureNotes(bridge.structureNotes);
        setMessage(t("compose.mimic.broughtAnalysis"));
      } else {
        setMessage(t("compose.mimic.broughtSource"));
      }
    }
    // 2) 舊 query：?mimic=原文（相容）
    const mimic = params.get("mimic");
    if (!bridge && mimic && mimic !== "1") {
      setSourceText(mimic);
      setShowMimic(true);
    }
    if (!bridge && params.get("from") === "own-post" && params.get("mimic") === "1") {
      setShowMimic(true);
    }
    const seed = params.get("text");
    if (seed && !draft) setText(seed);
    // 只在進入頁面時吃一次 query／bridge
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // 監聽仿寫 Job 完成 → 填正文
  useEffect(() => {
    if (!mimicJobId) return;
    const j = jobs.find((x) => x.id === mimicJobId);
    if (!j) {
      void (async () => {
        const full = await repos.jobs.get(mimicJobId);
        if (!full) return;
        if (full.status === "succeeded" && appliedMimicJob.current !== full.id) {
          appliedMimicJob.current = full.id;
          const result = parseMimicResult(full.payload);
          if (result) {
            setText(result);
            setMessage(t("compose.mimic.done"));
            setShowMimic(true);
          } else {
            setMessage(t("compose.mimic.jobFail", { err: "empty result" }));
          }
          setBusy("");
          trackMimicJob("");
          refresh();
        } else if (full.status === "failed") {
          setMessage(t("compose.mimic.jobFail", { err: full.error || full.progress_summary || "failed" }));
          setBusy("");
          trackMimicJob("");
        } else if (full.status === "running" || full.status === "queued" || full.status === "pending") {
          setBusy("mimic");
          if (full.progress_summary) setMessage(full.progress_summary);
        }
      })();
      return;
    }
    if (j.status === "running" || j.status === "queued" || j.status === "pending") {
      setBusy("mimic");
      if (j.progress_summary) setMessage(j.progress_summary);
      return;
    }
    if (j.status === "succeeded" && appliedMimicJob.current !== j.id) {
      appliedMimicJob.current = j.id;
      void (async () => {
        const full = (await repos.jobs.get(j.id)) || j;
        const result = parseMimicResult(full.payload);
        if (result) {
          setText(result);
          setMessage(
            structureNotes.trim()
              ? t("compose.mimic.doneWithStructure")
              : t("compose.mimic.done"),
          );
          setShowMimic(true);
        } else {
          setMessage(t("compose.mimic.jobFail", { err: "empty result" }));
        }
        setBusy("");
        trackMimicJob("");
        refresh();
      })();
      return;
    }
    if (j.status === "failed") {
      setMessage(t("compose.mimic.jobFail", { err: j.error || j.progress_summary || "failed" }));
      setBusy("");
      trackMimicJob("");
    }
  }, [jobs, mimicJobId, repos.jobs, refresh, structureNotes, t]);

  async function runMimic() {
    setBusy("mimic");
    setMessage("");
    appliedMimicJob.current = "";
    try {
      const out = await repos.compose.mimic(
        sourceText,
        personaId,
        mimicDirection || undefined,
        structureNotes || undefined,
      );
      if (out.async && out.jobId) {
        trackMimicJob(out.jobId);
        setMessage(t("compose.mimic.queued"));
        void reloadJobs();
        return;
      }
      if (out.text) {
        setText(out.text);
        setMessage(
          structureNotes.trim()
            ? t("compose.mimic.doneWithStructure")
            : t("compose.mimic.done"),
        );
      }
      setBusy("");
    } catch (e) {
      setMessage(e instanceof Error ? e.message : t("compose.fail"));
      setBusy("");
    }
  }

  /** datetime-local 分鐘精度：超過 1 分鐘才視為過期 */
  const SCHEDULE_PAST_GRACE_NS = 60_000_000_000;

  async function publish() {
    const now = nowUnixNano();
    // 立即發：送 0；否則預計時間不可早於現在（超過 1 分鐘才擋）
    let startAt = 0;
    if (!scheduleImmediate) {
      if (!scheduleAt || scheduleAt < now - SCHEDULE_PAST_GRACE_NS) {
        setMessage(t("compose.schedulePast"));
        return;
      }
      startAt = scheduleAt;
    }
    if (anyImageUploading(images)) {
      setMessage(t("compose.waitImageUpload"));
      return;
    }
    if (anyImageUploadFailed(images)) {
      setMessage(t("compose.imageUploadNeedRetry"));
      return;
    }
    // 圖應在選檔時已上傳完；此處只組 https URL（毫秒級）
    const imageUrls = resolvePublishImageUrls(images);
    if (images.length > 0 && imageUrls.length === 0) {
      setMessage(t("compose.imageUploadNeedRetry"));
      return;
    }

    setBusy("pub");
    setMessage("");
    try {
      const bundle = await repos.compose.publishSingle({
        accountId,
        text,
        title,
        imageUrls,
        schedule_start_at: startAt,
        topicTag: topicTag.trim() || undefined,
        replyControl: replyControl || "everyone",
      });
      // 先跳 outbox（worker 非同步發 Threads），refresh 不擋導航
      navigate(`/app/outbox/${bundle.id}`);
      void refresh();
    } catch (e) {
      setMessage(e instanceof Error ? e.message : t("compose.publishFail"));
      setBusy("");
    }
  }

  function setScheduleNow() {
    setScheduleAt(nowUnixNano());
    setScheduleImmediate(true);
  }

  const schedulePast =
    !scheduleImmediate && !!scheduleAt && scheduleAt < nowUnixNano() - SCHEDULE_PAST_GRACE_NS;

  return (
    <div className="hb-stack">
      <p className="text-muted" style={{ fontSize: "var(--hb-text-sm)", margin: 0 }}>
        {t("compose.hint")} <Link to="/app/studio?tab=plays">{t("compose.playsLink")}</Link>
        {t("compose.hintEnd")}
      </p>
      {!personaReady ? (
        <p className="text-muted" style={{ fontSize: "var(--hb-text-sm)" }}>
          {t("compose.personaOff")}
        </p>
      ) : null}
      {message ? (
        <p className="hb-banner-ok" role="status">
          {message}
        </p>
      ) : null}

      <Card>
        <div className="hb-stack">
          <Input
            label={t("compose.title")}
            value={title}
            onChange={(e) => setTitle(e.target.value)}
            placeholder={t("compose.titlePh")}
          />
          <Textarea
            label={t("compose.body")}
            value={text}
            onChange={(e) => setText(e.target.value)}
            placeholder={t("compose.bodyPh")}
            rows={8}
          />
          <p className="text-muted" role={bodyLength > 500 ? "status" : undefined}>
            {t("compose.bodyCount", { n: bodyLength })}
            {bodyLength > 500 ? ` · ${t("compose.bodyLongWarning")}` : ""}
          </p>
          <Input
            label={t("compose.topicTag")}
            value={topicTag}
            onChange={(e) => setTopicTag(e.target.value)}
            placeholder={t("compose.topicTagPh")}
            hint={t("compose.topicTagHint")}
          />
          <Select
            label={t("posts.whoCanReply")}
            name="reply_control"
            hint={t("compose.whoCanReplyHint")}
            value={replyControl}
            onChange={(e) => setReplyControl(e.target.value)}
          >
            {THREADS_REPLY_CONTROLS.map((id) => (
              <option key={id} value={id}>
                {t(`posts.replyControl.${id}`)}
              </option>
            ))}
          </Select>
          <ImageAttach
            images={images}
            onChange={setImages}
            disabled={busy === "pub"}
            upload={async (dataUrl) => {
              const up = await repos.auth.uploadImage(dataUrl, "temp");
              if (!up?.url) throw new Error(t("compose.uploadImageFail"));
              return up.url;
            }}
          />
          <div className="hb-compose-schedule">
            <Input
              label={t("compose.scheduleAt")}
              type="datetime-local"
              value={toDatetimeLocalValue(scheduleAt)}
              onChange={(e) => {
                setScheduleAt(fromDatetimeLocalValue(e.target.value));
                setScheduleImmediate(false);
              }}
              hint={
                schedulePast
                  ? t("compose.schedulePast")
                  : scheduleImmediate
                    ? t("compose.scheduleHintNow")
                    : t("compose.scheduleHint")
              }
            />
            <Button
              type="button"
              variant="ghost"
              className="hb-compose-schedule__now"
              onClick={setScheduleNow}
              disabled={busy === "pub"}
            >
              {t("compose.scheduleNow")}
            </Button>
          </div>
          <div className="hb-wizard-actions">
            <Button
              type="button"
              variant={showMimic ? "primary" : "ghost"}
              onClick={() => setShowMimic((v) => !v)}
            >
              {t("compose.tool.mimic")}
            </Button>
          </div>
        </div>
      </Card>

      {showMimic ? (
        <Card title={t("compose.mimic.title")}>
          <Textarea
            label={t("compose.mimic.source")}
            value={sourceText}
            onChange={(e) => setSourceText(e.target.value)}
            rows={5}
            placeholder={t("compose.mimic.sourcePh")}
          />
          <Textarea
            label={t("compose.mimic.direction")}
            value={mimicDirection}
            onChange={(e) => setMimicDirection(e.target.value)}
            rows={3}
            placeholder={t("compose.mimic.directionPh")}
            hint={t("compose.mimic.directionHint")}
          />
          <Textarea
            label={t("compose.mimic.structureNotes")}
            value={structureNotes}
            onChange={(e) => setStructureNotes(e.target.value)}
            rows={6}
            placeholder={t("compose.mimic.structureNotesPh")}
            hint={t("compose.mimic.structureNotesHint")}
          />
          <Button
            type="button"
            onClick={() => void runMimic()}
            disabled={!personaReady || busy === "mimic" || !sourceText.trim()}
          >
            {busy === "mimic" ? t("compose.mimic.running") : t("compose.mimic.run")}
          </Button>
        </Card>
      ) : null}

      <div className="hb-wizard-actions">
        <Button
          type="button"
          onClick={() => void publish()}
          disabled={
            busy === "pub" ||
            !text.trim() ||
            !accountId ||
            schedulePast ||
            anyImageUploading(images) ||
            anyImageUploadFailed(images)
          }
        >
          {busy === "pub"
            ? t("compose.publishing")
            : anyImageUploading(images)
              ? t("compose.waitImageUploadBtn")
              : t("compose.publish")}
        </Button>
        {images.length > 0 ? <Badge tone="neutral">{t("compose.attachN", { n: images.length })}</Badge> : null}
        <Badge tone="neutral">
          {t("compose.personaStatus", {
            status: personaReady ? t("compose.ready") : t("compose.notReady"),
          })}
        </Badge>
      </div>
    </div>
  );
}
