"use client";

import { useEffect, useRef, useState } from "react";

import { api } from "@/lib/api/client";
import { useToast } from "@/components/Toast";
import {
  toCodexGroups,
  toOutlineRows,
  type CodexGroup,
  type ContextTabKey,
  type OutlineRow,
} from "./contextDrawer";

// 速查抽屉的数据层：抽屉打开且切到对应 Tab 时【懒加载】设定库 / 大纲（只读，绝不写库）。
// 加载成功后缓存（切走再切回不重复拉）；项目切换清缓存；失败可 reload 重试。

export type ResourceStatus = "idle" | "loading" | "ready" | "error";

export interface ContextResource<T> {
  status: ResourceStatus;
  data: T;
}

export interface UseContextDrawerData {
  codex: ContextResource<CodexGroup[]>;
  outline: ContextResource<OutlineRow[]>;
  reloadCodex: () => void;
  reloadOutline: () => void;
}

const CODEX_PATH = "/projects/{project_id}/world_entities" as const;
const OUTLINE_PATH = "/projects/{project_id}/outline" as const;
const EMPTY_CODEX: CodexGroup[] = [];
const EMPTY_OUTLINE: OutlineRow[] = [];

export function useContextDrawerData(
  projectId: string,
  activeTab: ContextTabKey,
  open: boolean,
): UseContextDrawerData {
  const [codex, setCodex] = useState<ContextResource<CodexGroup[]>>({
    status: "idle",
    data: EMPTY_CODEX,
  });
  const [outline, setOutline] = useState<ContextResource<OutlineRow[]>>({
    status: "idle",
    data: EMPTY_OUTLINE,
  });
  const toast = useToast();
  // 单飞哨兵：已发起过请求就不再重复（成功缓存 / 在途去重）；出错时重置以允许重试。
  const codexReqRef = useRef(false);
  const outlineReqRef = useRef(false);
  // reload 触发器：自增即重新拉取（配合把 req 哨兵复位）。
  const [codexNonce, setCodexNonce] = useState(0);
  const [outlineNonce, setOutlineNonce] = useState(0);

  // 项目切换 → 清缓存 + 复位哨兵，允许对新项目重新拉取。声明在拉取 effect 之前，
  // 保证同一次提交里先复位、后续 effect 才据此触发。
  useEffect(() => {
    codexReqRef.current = false;
    outlineReqRef.current = false;
    setCodex({ status: "idle", data: EMPTY_CODEX });
    setOutline({ status: "idle", data: EMPTY_OUTLINE });
  }, [projectId]);

  useEffect(() => {
    if (!open || activeTab !== "codex" || codexReqRef.current) return;
    codexReqRef.current = true;
    let cancelled = false;
    setCodex({ status: "loading", data: EMPTY_CODEX });
    void (async () => {
      try {
        const { data, error } = await api.GET(CODEX_PATH, {
          params: { path: { project_id: projectId } },
        });
        if (cancelled) return;
        if (error || !data) {
          codexReqRef.current = false;
          setCodex({ status: "error", data: EMPTY_CODEX });
          toast("设定库加载失败，请重试。", "error");
          return;
        }
        setCodex({
          status: "ready",
          data: toCodexGroups(data.world_entities ?? []),
        });
      } catch {
        if (cancelled) return;
        codexReqRef.current = false;
        setCodex({ status: "error", data: EMPTY_CODEX });
        toast("设定库加载异常，请检查网络。", "error");
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [open, activeTab, projectId, codexNonce, toast]);

  useEffect(() => {
    if (!open || activeTab !== "outline" || outlineReqRef.current) return;
    outlineReqRef.current = true;
    let cancelled = false;
    setOutline({ status: "loading", data: EMPTY_OUTLINE });
    void (async () => {
      try {
        const { data, error } = await api.GET(OUTLINE_PATH, {
          params: { path: { project_id: projectId } },
        });
        if (cancelled) return;
        if (error || !data) {
          outlineReqRef.current = false;
          setOutline({ status: "error", data: EMPTY_OUTLINE });
          toast("大纲加载失败，请重试。", "error");
          return;
        }
        setOutline({
          status: "ready",
          data: toOutlineRows(data.chapters ?? []),
        });
      } catch {
        if (cancelled) return;
        outlineReqRef.current = false;
        setOutline({ status: "error", data: EMPTY_OUTLINE });
        toast("大纲加载异常，请检查网络。", "error");
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [open, activeTab, projectId, outlineNonce, toast]);

  const reloadCodex = (): void => {
    codexReqRef.current = false;
    setCodex({ status: "idle", data: EMPTY_CODEX });
    setCodexNonce((n) => n + 1);
  };
  const reloadOutline = (): void => {
    outlineReqRef.current = false;
    setOutline({ status: "idle", data: EMPTY_OUTLINE });
    setOutlineNonce((n) => n + 1);
  };

  return { codex, outline, reloadCodex, reloadOutline };
}
