import { useRef, useCallback } from 'react';
import type { FormInstance } from 'antd';
import dayjs from 'dayjs';

const EXPIRY_MS = 24 * 60 * 60 * 1000; // 24小时
const DAYJS_TAG = '__dayjs__';

// 递归序列化：dayjs 对象标记为 { __dayjs__: true, value: ISO字符串 }
function serialize(value: any): any {
  if (dayjs.isDayjs(value)) {
    return { [DAYJS_TAG]: true, value: value.toISOString() };
  }
  if (Array.isArray(value)) return value.map(serialize);
  if (value && typeof value === 'object' && !(value instanceof Date)) {
    const result: Record<string, any> = {};
    for (const key of Object.keys(value)) {
      result[key] = serialize(value[key]);
    }
    return result;
  }
  return value;
}

// 递归反序列化：还原 dayjs 对象
function deserialize(value: any): any {
  if (value && typeof value === 'object' && !Array.isArray(value)) {
    if (value[DAYJS_TAG] === true && typeof value.value === 'string') {
      return dayjs(value.value);
    }
    const result: Record<string, any> = {};
    for (const key of Object.keys(value)) {
      result[key] = deserialize(value[key]);
    }
    return result;
  }
  if (Array.isArray(value)) return value.map(deserialize);
  return value;
}

interface DraftData {
  formValues: Record<string, any>;
  extraData?: Record<string, any>;
  savedAt: number;
}

interface UseFormDraftOptions {
  form: FormInstance;
  storageKey: string;
  debounceMs?: number;
  onRestore?: (extraData: Record<string, any>) => void;
}

interface UseFormDraftReturn {
  save: (extraData?: Record<string, any>) => void;
  restore: () => boolean;
  clear: () => void;
  hasDraft: () => boolean;
}

function useFormDraft(options: UseFormDraftOptions): UseFormDraftReturn {
  const { form, storageKey, debounceMs = 500, onRestore } = options;
  const timerRef = useRef<ReturnType<typeof setTimeout>>();
  const isRestoringRef = useRef(false);

  const save = useCallback((extraData?: Record<string, any>) => {
    const formValues = serialize(form.getFieldsValue(true));
    const data: DraftData = { formValues, extraData: serialize(extraData), savedAt: Date.now() };
    try {
      sessionStorage.setItem(storageKey, JSON.stringify(data));
    } catch {
      // sessionStorage 满了，忽略
    }
  }, [form, storageKey]);

  const restore = useCallback((): boolean => {
    const raw = sessionStorage.getItem(storageKey);
    if (!raw) return false;
    try {
      const data: DraftData = JSON.parse(raw);
      // 24小时过期检查
      if (Date.now() - data.savedAt > EXPIRY_MS) {
        sessionStorage.removeItem(storageKey);
        return false;
      }
      isRestoringRef.current = true;
      form.setFieldsValue(deserialize(data.formValues));
      if (data.extraData && onRestore) onRestore(deserialize(data.extraData));
      isRestoringRef.current = false;
      return true;
    } catch {
      sessionStorage.removeItem(storageKey);
      return false;
    }
  }, [form, storageKey, onRestore]);

  const clear = useCallback(() => {
    sessionStorage.removeItem(storageKey);
  }, [storageKey]);

  const hasDraft = useCallback((): boolean => {
    const raw = sessionStorage.getItem(storageKey);
    if (!raw) return false;
    try {
      const data: DraftData = JSON.parse(raw);
      if (Date.now() - data.savedAt > EXPIRY_MS) {
        sessionStorage.removeItem(storageKey);
        return false;
      }
      return true;
    } catch {
      sessionStorage.removeItem(storageKey);
      return false;
    }
  }, [storageKey]);

  // 防抖保存
  const debouncedSave = useCallback((extraData?: Record<string, any>) => {
    if (isRestoringRef.current) return;
    if (timerRef.current) clearTimeout(timerRef.current);
    timerRef.current = setTimeout(() => save(extraData), debounceMs);
  }, [save, debounceMs]);

  return { save: debouncedSave, restore, clear, hasDraft };
}

export default useFormDraft;
