'use client';

import { create } from 'zustand';
import type { XiaobaoVersionRisk } from '@/lib/xiaobao-risk';
import {
  markXiaobaoWarningRead,
  type XiaobaoWarningReadState,
} from '@/lib/xiaobao-warning-view';
import { loadServerData, saveServerData, SERVER_DATA_CACHE_MS } from '@/lib/server-data';

interface XiaobaoWarningReadStoreState {
  readStates: XiaobaoWarningReadState[];
  readStateLoaded: boolean;
  error?: string;
  fetchReadStates: () => Promise<void>;
  markRiskRead: (userId: string, risk: XiaobaoVersionRisk, readAt?: string) => Promise<void>;
}

let readStateSaveQueue: Promise<void> = Promise.resolve();
let lastReadStatesFetchAt = 0;

async function loadReadStates(): Promise<XiaobaoWarningReadState[] | null> {
  try {
    const rows = await loadServerData<XiaobaoWarningReadState[]>('xiaobao-warning-views');
    return normalizeReadStates(rows);
  } catch {}
  return null;
}

function normalizeReadStates(rows: unknown): XiaobaoWarningReadState[] {
  if (!Array.isArray(rows)) return [];
  return rows.filter(isReadState);
}

function isReadState(row: unknown): row is XiaobaoWarningReadState {
  if (!row || typeof row !== 'object') return false;
  const item = row as Partial<XiaobaoWarningReadState>;
  return (
    typeof item.userId === 'string' &&
    typeof item.versionId === 'string' &&
    typeof item.signature === 'string' &&
    typeof item.readAt === 'string'
  );
}

function mergeReadStates(
  remoteRows: XiaobaoWarningReadState[] = [],
  localRows: XiaobaoWarningReadState[] = [],
): XiaobaoWarningReadState[] {
  const byKey = new Map<string, XiaobaoWarningReadState>();
  for (const row of [...remoteRows, ...localRows]) {
    const key = `${row.userId}::${row.versionId}`;
    const existing = byKey.get(key);
    if (!existing || row.readAt.localeCompare(existing.readAt) >= 0) {
      byKey.set(key, row);
    }
  }
  return Array.from(byKey.values()).sort((a, b) => b.readAt.localeCompare(a.readAt));
}

export const useXiaobaoWarningReadStore = create<XiaobaoWarningReadStoreState>((set, get) => ({
  readStates: [],
  readStateLoaded: false,
  error: undefined,

  fetchReadStates: async () => {
    if (get().readStateLoaded && Date.now() - lastReadStatesFetchAt < SERVER_DATA_CACHE_MS) return;
    const rows = await loadReadStates();
    if (get().readStateLoaded && Date.now() - lastReadStatesFetchAt < SERVER_DATA_CACHE_MS) return;
    lastReadStatesFetchAt = Date.now();
    set({
      readStates: rows ? mergeReadStates(rows, get().readStates) : get().readStates,
      readStateLoaded: rows !== null,
      error: rows === null ? '小宝预警查看状态加载失败' : undefined,
    });
  },

  markRiskRead: async (userId, risk, readAt = new Date().toISOString()) => {
    if (!userId) return;
    const optimistic = markXiaobaoWarningRead(get().readStates, userId, risk, readAt);
    set({ readStates: optimistic, error: undefined });

    const task = readStateSaveQueue.then(async () => {
      const remote = await loadServerData<XiaobaoWarningReadState[]>('xiaobao-warning-views', { force: true });
      const merged = mergeReadStates(normalizeReadStates(remote), get().readStates);
      set({ readStates: merged, readStateLoaded: true, error: undefined });
      await saveServerData('xiaobao-warning-views', merged);
    });
    readStateSaveQueue = task.catch(() => undefined);

    try {
      await task;
    } catch (error) {
      set({ error: '小宝预警查看状态保存失败' });
      throw error;
    }
  },
}));
