"use client";

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

import { api } from "@/lib/api/client";
import { useToast } from "@/components/Toast";
import {
  AUTOSAVE_DELAY_MS,
  createDebouncedSaver,
  formatSavedAt,
  type DebouncedSaver,
} from "./autosave";

export type SaveStatus = "idle" | "saving" | "saved" | "error";

export interface UseAutosave {
  status: SaveStatus;
  savedLabel: string | null;
  onChange: (text: string) => void;
  flush: () => void;
}

// 防抖自动保存草稿：乐观置 saving → PUT 成功置 saved（落「保存于 hh:mm」）；
// 失败回滚状态 + toast，不丢正文（已在编辑器里）。
// `initialSavedText`：进页种入的已存草稿——非空时初始即「已保存」，修「加载已存草稿却显示尚未保存」的误导。
export function useAutosave(
  projectId: string,
  chapterNo: number,
  initialSavedText?: string,
): UseAutosave {
  // 归一为非空基线（undefined → ""），避免后续非空断言/强转。
  const initialDraft = initialSavedText ?? "";
  const hasInitialDraft = initialDraft.length > 0;
  const [status, setStatus] = useState<SaveStatus>(
    hasInitialDraft ? "saved" : "idle",
  );
  const [savedLabel, setSavedLabel] = useState<string | null>(
    hasInitialDraft ? "已保存" : null,
  );
  const toast = useToast();
  // 种入已存草稿为基线：用户未改动时不触发冗余保存（save 早退）。
  const lastSavedRef = useRef<string | null>(
    hasInitialDraft ? initialDraft : null,
  );

  const save = useCallback(
    async (text: string): Promise<void> => {
      if (text === lastSavedRef.current) return;
      setStatus("saving");
      const { error } = await api.PUT(
        "/projects/{project_id}/chapters/{chapter_no}/draft",
        {
          params: { path: { project_id: projectId, chapter_no: chapterNo } },
          body: { text },
        },
      );
      if (error) {
        setStatus("error");
        toast("自动保存失败，稍后重试（正文未丢失）", "error");
        return;
      }
      lastSavedRef.current = text;
      setSavedLabel(formatSavedAt(new Date()));
      setStatus("saved");
    },
    [projectId, chapterNo, toast],
  );

  const saver: DebouncedSaver = useMemo(
    () => createDebouncedSaver(save, AUTOSAVE_DELAY_MS),
    [save],
  );

  useEffect(() => () => saver.cancel(), [saver]);

  const onChange = useCallback(
    (text: string) => {
      saver.schedule(text);
    },
    [saver],
  );

  const flush = useCallback(() => saver.flush(), [saver]);

  return { status, savedLabel, onChange, flush };
}
