import { create } from 'zustand';
import dayjs from 'dayjs';
import { ServeCollectionDates, ServeCollectionDetail } from '@/api/attendance';
import { useToast } from '@/utils/ui/toast';
import { createResettableStore } from '../registry';
import { useAuthStore } from '@/stores/auth';

// 轻量内存缓存与在途管理（不落盘）
const CACHE_TTL = 120 * 1000; // 120s
const CACHE_MAX = 5; // 每个模式最多5条

// 简易 LRU 缓存：Map 末尾为最近使用
function lruGet(cache, key) {
  if (!cache.has(key)) return null;
  const entry = cache.get(key);
  if (!entry) return null;
  if (Date.now() - entry.ts > CACHE_TTL) {
    cache.delete(key);
    return null;
  }
  // 触发 LRU：删除后再 set 到尾部
  cache.delete(key);
  cache.set(key, entry);
  return entry.data;
}
function lruSet(cache, key, data) {
  cache.set(key, { data, ts: Date.now() });
  if (cache.size > CACHE_MAX) {
    const firstKey = cache.keys().next().value;
    if (firstKey != null) cache.delete(firstKey);
  }
}

const dayCache = new Map();
const weekCache = new Map();
const monthCache = new Map();

// 静默刷新（后台刷新"今天"）的在途请求去重
const revalidatePendingMap = new Map();

// 稳定字符串化 + 短哈希，用于参与缓存键的"过滤参数摘要"
function getUserKey() {
  try {
    const u = useAuthStore.getState().getUser?.() || useAuthStore.getState().user;
    return u?.ID ? String(u.ID) : 'anon';
  } catch {
    return 'anon';
  }
}

// 在途去重键生成：按方法 + 人员 + 切片键（月份或周）隔离
const buildPendingKey = (method, staffUID, sliceKey) => {
    const s = typeof sliceKey === 'string' ? sliceKey : '';
    const valid = method === 'week' ? s.length > 0 : s.length === 7; // 月/日要求 YYYY-MM；周只需非空
    if (!valid) return null;
    const uid = (staffUID !== undefined && staffUID !== null) ? String(staffUID) : 'unknown';
    return `${method}:${uid}:${s}`;
};

const createStatisticsStore = () => create((set, get) => ({

    // 考勤统计模式: day-日, week-周, month-月
    activeStatisticsMode: 'day',
    // 设置考勤统计模式
    setActiveStatisticsMode: (mode) => set({ activeStatisticsMode: mode }),

    // 统计详情
    statisticsDetail: {},

    // 历史遗留的月级缓存，当前阶段暂时「不启用任何结果级缓存」
    // monthCache: new Map(),

    // 在途请求去重（不落盘、不缓存结果）
    // key 为 'YYYY-MM'（当前月），value 为进行中的 Promise；请求完成后立刻移除。
    pendingMap: new Map(),

    // day 请求的 takeLatest 守卫
    dayLatestReqId: 0,

    // month 请求的 takeLatest 守卫与可选的取消控制器
    monthLatestReqId: 0,
    monthAbortController: null,

    // week 请求的 takeLatest 守卫与可选的取消控制器
    weekLatestReqId: 0,
    weekAbortController: null,

    // 静默刷新"今天"数据的 takeLatest 守卫
    dayRevalidateReqId: 0,
    weekRevalidateReqId: 0,
    monthRevalidateReqId: 0,

    // 当前显示的数据 cacheKey（用于防止静默刷新的竞态覆盖）
    currentDisplayCacheKey: null,

    // 加载计数与上次成功更新时间
    loadingCount: 0,
    lastUpdateTime: null,

    // 静默刷新进行中计数（仅用于按钮禁用，不影响全局加载态）
    revalidatingCount: 0,

    // 增加/减少 接口请求loading 计数，避免出现负数
    incLoading: () => set((s) => ({ loadingCount: (s.loadingCount || 0) + 1 })),
    decLoading: () => set((s) => ({ loadingCount: Math.max(0, (s.loadingCount || 0) - 1) })),
    setLastUpdateTime: (ts) => set({ lastUpdateTime: ts }),

    // 增加/减少 静默刷新计数，避免出现负数
    incRevalidating: () => set((s) => ({ revalidatingCount: (s.revalidatingCount || 0) + 1 })),
    decRevalidating: () => set((s) => ({ revalidatingCount: Math.max(0, (s.revalidatingCount || 0) - 1) })),

    // 设置统计详情
    setStatisticsDetail: (statisticsDetail) => set({ statisticsDetail }),

    // ===== 内部工具：构建缓存键 =====
    _buildDayKey: (data) => {
      const uid = getUserKey();
      const monthKey = data?.monthKey; // 使用monthKey作为月份标识
      const dates = Array.isArray(data?.dates) ? data.dates : [];
      if (!monthKey || dates.length === 0) return null;
      // 使用dates数组的首尾构建唯一键
      const startDate = dates[0];
      const endDate = dates[dates.length - 1];
      return `${uid}|day|${monthKey}|${startDate}_${endDate}`;
    },

    _buildWeekKey: (data) => {
      const uid = getUserKey();
      const weekKey = data?.weekKey;
      const dates = Array.isArray(data?.dates) ? data.dates : [];
      if (!weekKey || dates.length === 0) return null;
      const startDate = dates[0];
      const endDate = dates[dates.length - 1];
      return `${uid}|week|${weekKey}|${startDate}_${endDate}`;
    },

    _buildMonthKey: (data) => {
      const uid = getUserKey();
      const monthKey = data?.month;
      if (!monthKey) return null;
      return `${uid}|month|${monthKey}`;
    },

    // ===== 内部工具：静默刷新"今天"相关 =====
    // 判断查询的数据是否包含今天
    _containsToday: (data, mode) => {
      const today = dayjs().format('YYYY-MM-DD');
      
      if (mode === 'day') {
        // 日模式：检查 dates 数组
        const dates = Array.isArray(data?.dates) ? data.dates : [];
        return dates.includes(today);
      } else if (mode === 'week') {
        // 周模式：检查 dates 数组
        const dates = Array.isArray(data?.dates) ? data.dates : [];
        return dates.includes(today);
      } else if (mode === 'month') {
        // 月模式：检查 month 字段
        const monthStr = data?.month; // 'YYYY-MM'
        const currentMonth = dayjs().format('YYYY-MM');
        return monthStr === currentMonth;
      }
      
      return false;
    },

    // 深度比较数据是否相同
    _isDataEqual: (data1, data2) => {
      try {
        return JSON.stringify(data1) === JSON.stringify(data2);
      } catch {
        return false;
      }
    },

    // 静默刷新包含"今天"的数据（无阈值，立即刷新）
    _refreshTodayData: async (cacheKey, data, mode, originalOptions = {}) => {
      const refreshKey = `${mode}:${cacheKey}`;
      
      // 防止重复刷新（在途去重）
      if (revalidatePendingMap.has(refreshKey)) {
        return;
      }

      // 根据模式选择合适的刷新ID
      const revalidateReqId = (get()[`${mode}RevalidateReqId`] || 0) + 1;
      set({ [`${mode}RevalidateReqId`]: revalidateReqId });

      // 进入静默刷新进行中计数（仅用于按钮禁用）
      get().incRevalidating();

      // 准备请求数据
      const origDates = Array.isArray(data?.dates) ? data.dates : [];
      const today = dayjs().startOf('day');
      const clippedDates = origDates.filter((d) => !dayjs(d).isAfter(today, 'day'));

      // 选择正确的API
      let apiCall;
      if (mode === 'month') {
        apiCall = ServeCollectionDetail({
          collectionType: data.collectionType,
          staffUID: data.staffUID,
          month: data.month,
        }, { ...originalOptions, signal: undefined }); // 静默请求不使用 AbortController
      } else {
        // day 或 week 模式
        apiCall = ServeCollectionDates({
          collectionType: data.collectionType,
          staffUID: data.staffUID,
          dates: clippedDates.length ? clippedDates : data.dates,
        }, { ...originalOptions, signal: undefined });
      }

      const promise = apiCall
        .then((res) => {
          // 检查是否是最新请求
          if (revalidateReqId !== get()[`${mode}RevalidateReqId`]) {
            return;
          }

          if (res && res.status === 0) {
            const newData = res?.data || {};
            
            // 获取对应模式的缓存
            let cache;
            if (mode === 'day') cache = dayCache;
            else if (mode === 'week') cache = weekCache;
            else cache = monthCache;
            
            const cachedData = lruGet(cache, cacheKey);

            // 数据变化才更新
            if (!get()._isDataEqual(cachedData, newData)) {
              // 更新缓存
              lruSet(cache, cacheKey, newData);

              // 更新UI（检查模式匹配 && cacheKey匹配）
              const currentMode = get().activeStatisticsMode;
              const currentKey = get().currentDisplayCacheKey;
              
              // 只有当前显示的模式和cacheKey都匹配时才更新UI，避免竞态覆盖
              if (currentMode === mode && currentKey === cacheKey) {
                set({ 
                  statisticsDetail: newData, 
                  lastUpdateTime: Date.now() 
                });
              }
            }
          }
          // 静默请求成功但状态非0，或被取消，不做任何处理
        })
        .catch(() => {
          // 静默失败，不影响用户
        })
        .finally(() => {
          revalidatePendingMap.delete(refreshKey);
          // 退出静默刷新进行中计数
          get().decRevalidating();
        });

      revalidatePendingMap.set(refreshKey, promise);
    },

    /**
     * 获取日考勤统计详情数据
     * - 轻量优化：
     *   1) LRU 缓存（120s TTL，最多5条）
     *   2) 在途请求去重（pendingMap）
     *   3) 支持 AbortController 取消过时请求
     *   4) Store 侧 takeLatest 守卫，避免乱序覆盖
     *   5) 写回前校验 activeStatisticsMode === 'day'，避免跨模式覆盖
     */
    fetchStatisticsDetail: async (data, options = {}) => {
        const monthKey = data?.monthKey; // 切片键（自然月）

        // 最小短路与裁剪：过滤掉未来日期，若全部为未来则直接短路
        const origDates = Array.isArray(data?.dates) ? data.dates : [];
        const today = dayjs().startOf('day');
        const clippedDates = origDates.filter((d) => !dayjs(d).isAfter(today, 'day'));
        if (origDates.length > 0 && clippedDates.length === 0) {
            set({ statisticsDetail: {} });
            return { status: 0, data: {}, shortCircuited: true };
        }

        // 构建缓存键（使用裁剪后的日期）
        const dataWithClippedDates = { ...data, dates: clippedDates.length ? clippedDates : origDates };
        const cacheKey = get()._buildDayKey(dataWithClippedDates);

        // 缓存命中
        if (cacheKey) {
            const cached = lruGet(dayCache, cacheKey);
            if (cached) {
                const prev = get().statisticsDetail;
                if (prev !== cached && get().activeStatisticsMode === 'day') {
                    set({ statisticsDetail: cached, currentDisplayCacheKey: cacheKey });
                } else if (get().activeStatisticsMode === 'day') {
                    // 即使数据未变化，也更新 currentDisplayCacheKey
                    set({ currentDisplayCacheKey: cacheKey });
                }

                // 检测是否包含今天，如果包含则静默刷新（无阈值）
                if (get()._containsToday(dataWithClippedDates, 'day')) {
                    get()._refreshTodayData(cacheKey, dataWithClippedDates, 'day', options);
                }

                return { status: 0, data: cached, cache: true };
            }
        }

        // 在途去重：同月Key的请求直接复用进行中的 Promise（不落缓存）
        const pendingMap = get().pendingMap;
        const pendingKey = buildPendingKey('day', data?.staffUID, monthKey);
        if (pendingKey && pendingMap.has(pendingKey)) {
            return await pendingMap.get(pendingKey);
        }

        // 进入加载态
        get().incLoading();

        // 生成并记录本次请求的序号（用于 takeLatest 守卫）
        const reqId = (get().dayLatestReqId || 0) + 1;
        set({ dayLatestReqId: reqId });

        const promise = ServeCollectionDates({
            collectionType: data.collectionType,
            staffUID: data.staffUID,
            dates: clippedDates.length ? clippedDates : data.dates,
        }, options)
            .then((res) => {
                // 仅最新请求可落盘，旧请求结果直接丢弃
                if (reqId !== get().dayLatestReqId) {
                    return res;
                }
                if (res && res.status === 0) {
                    const statisticsData = res?.data || {};
                    // 仅在日模式下落盘，避免跨模式覆盖
                    if (get().activeStatisticsMode === 'day') {
                        set({ 
                            statisticsDetail: statisticsData, 
                            lastUpdateTime: Date.now(),
                            currentDisplayCacheKey: cacheKey 
                        });
                    }
                    // 写入缓存
                    if (cacheKey) {
                        lruSet(dayCache, cacheKey, statisticsData);
                    }
                } else if (res && res.canceled) {
                    // 被取消的请求，静默处理
                } else {
                    // 失败时若仍是最新且处于日模式，则清空已加载数据
                    if (reqId === get().dayLatestReqId && get().activeStatisticsMode === 'day') {
                        set({ statisticsDetail: {}, lastUpdateTime: null });
                    }
                    useToast.showError(res?.msg || res?.err || res?.error || '请求失败');
                }
                return res;
            })
            .catch((err) => {
                // 若不是最新请求，直接吞掉错误（如被后续请求取消）
                if (reqId !== get().dayLatestReqId) {
                    return { status: -999, canceled: true };
                }
                const msg = err?.message || err?.msg || '';
                const code = err?.code || '';
                if (code === 'ERR_CANCELED' || /cancel|取消/i.test(msg)) {
                    return { status: -999, canceled: true };
                }
                // 非取消错误且仍是最新时清空已加载数据
                if (reqId === get().dayLatestReqId && get().activeStatisticsMode === 'day') {
                    set({ statisticsDetail: {}, lastUpdateTime: null });
                }
                useToast.showError(msg || '网络或服务异常');
                return { status: -1, error: err };
            })
            .finally(() => {
                if (pendingKey) {
                    pendingMap.delete(pendingKey);
                }
                // 退出加载态
                get().decLoading();
            });

        if (pendingKey) {
            pendingMap.set(pendingKey, promise);
        }

        return await promise;
    },

    /**
     * 获取月考勤统计详情数据（takeLatest + 在途去重 + 可取消）
     * - 轻量优化：
     *   1) LRU 缓存（120s TTL，最多5条）
     *   2) 在途请求去重（pendingMap）
     *   3) 支持 AbortController 取消过时请求
     *   4) Store 侧 takeLatest 守卫，避免乱序覆盖
     */
    fetchAttendanceMonthDetail: async (data, options = {}) => {
        const monthKey = data?.monthKey; // 切片键（自然月）

        // 最小短路：未来月份直接短路（自然月比较）
        const monthStr = data?.month;
        if (typeof monthStr === 'string' && monthStr.length === 7) {
            const now = dayjs();
            const todayMonth = now.startOf('month');
            const targetMonth = dayjs(`${monthStr}-01`).startOf('month');
            // 标签月豁免：若目标月是当前考勤周期的标签月（26~25规则），不短路
            const labelMonthStart = (now.date() >= 26 ? now.add(1, 'month') : now).startOf('month');
            const isFutureNaturalMonth = targetMonth.isAfter(todayMonth, 'month');
            const isLabelMonth = targetMonth.isSame(labelMonthStart, 'month');
            if (isFutureNaturalMonth && !isLabelMonth) {
                set({ statisticsDetail: {} });
                return { status: 0, data: {}, shortCircuited: true };
            }
        }

        // 构建缓存键
        const cacheKey = get()._buildMonthKey(data);

        // 缓存命中
        if (cacheKey) {
            const cached = lruGet(monthCache, cacheKey);
            if (cached) {
                const prev = get().statisticsDetail;
                if (prev !== cached) {
                    set({ statisticsDetail: cached, currentDisplayCacheKey: cacheKey });
                } else {
                    // 即使数据未变化，也更新 currentDisplayCacheKey
                    set({ currentDisplayCacheKey: cacheKey });
                }

                // 检测是否包含今天，如果包含则静默刷新（无阈值）
                if (get()._containsToday(data, 'month')) {
                    get()._refreshTodayData(cacheKey, data, 'month', options);
                }

                return { status: 0, data: cached, cache: true };
            }
        }

        // 在途去重：同月Key的请求直接复用进行中的 Promise（不落缓存）
        const pendingMap = get().pendingMap;
        const pendingKey = buildPendingKey('month', data?.staffUID, monthKey);
        if (pendingKey && pendingMap.has(pendingKey)) {
            return await pendingMap.get(pendingKey);
        }

        // 进入加载态
        get().incLoading();

        // 生成并记录本次请求的序号（用于 takeLatest 守卫）
        const reqId = (get().monthLatestReqId || 0) + 1;
        set({ monthLatestReqId: reqId });

        // 若组件未传入 signal，则在 Store 层提供一个可取消的 controller，并取消上一次
        let { signal } = options || {};
        let usedStoreController = false;
        if (!signal && typeof AbortController !== 'undefined') {
            const prevController = get().monthAbortController;
            if (prevController) {
                try { prevController.abort(); } catch {}
            }
            const controller = new AbortController();
            set({ monthAbortController: controller });
            signal = controller.signal;
            usedStoreController = true;
        }

        const promise = ServeCollectionDetail({
            collectionType: data.collectionType,
            staffUID: data.staffUID,
            month: data.month,
        }, { ...(options || {}), ...(signal ? { signal } : {}) })
            .then((res) => {
                // 仅最新请求可落盘，旧请求结果直接丢弃
                if (reqId !== get().monthLatestReqId) {
                    return res;
                }
                if (res && res.status === 0) {
                    const statisticsData = res?.data || {};
                    set({ 
                        statisticsDetail: statisticsData, 
                        lastUpdateTime: Date.now(),
                        currentDisplayCacheKey: cacheKey 
                    });
                    // 写入缓存
                    if (cacheKey) {
                        lruSet(monthCache, cacheKey, statisticsData);
                    }
                } else if (res && res.canceled) {
                    // 被取消的请求，静默处理
                } else {
                    // 失败时若仍是最新则清空已加载数据（月）
                    if (reqId === get().monthLatestReqId) {
                        set({ statisticsDetail: {}, lastUpdateTime: null });
                    }
                    useToast.showError(res?.msg || res?.err || res?.error || '请求失败');
                }
                return res;
            })
            .catch((err) => {
                // 若不是最新请求，直接吞掉错误（如被后续请求取消）
                if (reqId !== get().monthLatestReqId) {
                    return { status: -999, canceled: true };
                }
                const msg = err?.message || err?.msg || '';
                const code = err?.code || '';
                if (code === 'ERR_CANCELED' || /cancel|取消/i.test(msg)) {
                    return { status: -999, canceled: true };
                }
                // 非取消错误且仍是最新时清空已加载数据（月）
                if (reqId === get().monthLatestReqId) {
                    set({ statisticsDetail: {}, lastUpdateTime: null });
                }
                useToast.showError(msg || '网络或服务异常');
                return { status: -1, error: err };
            })
            .finally(() => {
                if (pendingKey) {
                    pendingMap.delete(pendingKey);
                }
                // 仅当本次仍是最新请求时，清理 store 级别的 controller
                if (usedStoreController && reqId === get().monthLatestReqId) {
                    set({ monthAbortController: null });
                }
                // 退出加载态
                get().decLoading();
            });

        if (pendingKey) {
            pendingMap.set(pendingKey, promise);
        }

        return await promise;
    },
    // 兼容旧方法名
    fetchStatisticsMonth: async (data, options = {}) => {
        return await get().fetchAttendanceMonthDetail(data, options);
    },

    /**
     * 获取周考勤统计详情数据
     * - 用于考勤周切片数据拉取
     * - 轻量优化：
     *   1) LRU 缓存（120s TTL，最多5条）
     *   2) 在途请求去重（pendingMap）
     *   3) 支持 AbortController 取消过时请求
     */
    fetchAttendanceWeekDetail: async (data, options = {}) => {
        const weekKey = data?.weekKey; // 切片键（周一日期）

        // 最小短路与裁剪：过滤掉未来日期，若全部为未来则直接短路
        const origDates = Array.isArray(data?.dates) ? data.dates : [];
        const today = dayjs().startOf('day');
        const clippedDates = origDates.filter((d) => !dayjs(d).isAfter(today, 'day'));
        if (origDates.length > 0 && clippedDates.length === 0) {
            set({ statisticsDetail: {} });
            return { status: 0, data: {}, shortCircuited: true };
        }

        // 构建缓存键（使用裁剪后的日期）
        const dataWithClippedDates = { ...data, dates: clippedDates.length ? clippedDates : origDates };
        const cacheKey = get()._buildWeekKey(dataWithClippedDates);

        // 缓存命中
        if (cacheKey) {
            const cached = lruGet(weekCache, cacheKey);
            if (cached) {
                const prev = get().statisticsDetail;
                if (prev !== cached) {
                    set({ statisticsDetail: cached, currentDisplayCacheKey: cacheKey });
                } else {
                    // 即使数据未变化，也更新 currentDisplayCacheKey
                    set({ currentDisplayCacheKey: cacheKey });
                }

                // 检测是否包含今天，如果包含则静默刷新（无阈值）
                if (get()._containsToday(dataWithClippedDates, 'week')) {
                    get()._refreshTodayData(cacheKey, dataWithClippedDates, 'week', options);
                }

                return { status: 0, data: cached, cache: true };
            }
        }

        // 在途去重：同周Key的请求直接复用进行中的 Promise
        const pendingMap = get().pendingMap;
        const pendingKey = buildPendingKey('week', data?.staffUID, weekKey);
        if (pendingKey && pendingMap.has(pendingKey)) {
            return await pendingMap.get(pendingKey);
        }

        // 进入加载态
        get().incLoading();

        // 生成并记录本次请求的序号（用于 takeLatest 守卫）
        const reqId = (get().weekLatestReqId || 0) + 1;
        set({ weekLatestReqId: reqId });

        // 若组件未传入 signal，则在 Store 层提供一个可取消的 controller，并取消上一次
        let { signal } = options || {};
        let usedStoreController = false;
        if (!signal && typeof AbortController !== 'undefined') {
            const prevController = get().weekAbortController;
            if (prevController) {
                try { prevController.abort(); } catch {}
            }
            const controller = new AbortController();
            set({ weekAbortController: controller });
            signal = controller.signal;
            usedStoreController = true;
        }

        const promise = ServeCollectionDates({
            collectionType: data.collectionType,
            staffUID: data.staffUID,
            dates: clippedDates.length ? clippedDates : data.dates,
        }, { ...(options || {}), ...(signal ? { signal } : {}) })
            .then((res) => {
                // 仅最新请求可落盘，旧请求结果直接丢弃
                if (reqId !== get().weekLatestReqId) {
                    return res;
                }
                if (res && res.status === 0) {
                    const statisticsData = res?.data || {};
                    set({ 
                        statisticsDetail: statisticsData, 
                        lastUpdateTime: Date.now(),
                        currentDisplayCacheKey: cacheKey 
                    });
                    // 写入缓存
                    if (cacheKey) {
                        lruSet(weekCache, cacheKey, statisticsData);
                    }
                } else if (res && res.canceled) {
                    // 被取消的请求，静默处理
                } else {
                    // 失败时若仍是最新则清空已加载数据（周）
                    if (reqId === get().weekLatestReqId) {
                        set({ statisticsDetail: {}, lastUpdateTime: null });
                    }
                    useToast.showError(res?.msg || res?.err || res?.error || '请求失败');
                }
                return res;
            })
            .catch((err) => {
                const msg = err?.message || err?.msg || '';
                const code = err?.code || '';
                if (code === 'ERR_CANCELED' || /cancel|取消/i.test(msg)) {
                    return { status: -999, canceled: true };
                }
                // 非取消错误且仍是最新时清空已加载数据（周）
                if (reqId === get().weekLatestReqId) {
                    set({ statisticsDetail: {}, lastUpdateTime: null });
                }
                useToast.showError(msg || '网络或服务异常');
                return { status: -1, error: err };
            })
            .finally(() => {
                if (pendingKey) {
                    pendingMap.delete(pendingKey);
                }
                // 仅当本次仍是最新请求时，清理 store 级别的 controller
                if (usedStoreController && reqId === get().weekLatestReqId) {
                    set({ weekAbortController: null });
                }
                // 退出加载态
                get().decLoading();
            });

        if (pendingKey) {
            pendingMap.set(pendingKey, promise);
        }

        return await promise;
    },
}));

const resettableStatistics = createResettableStore('statisticsStore', createStatisticsStore);
export const useStatisticsStore = resettableStatistics.useStore;