import { create } from 'zustand';
import type { Post } from '../../types';
import { CacheEntry, createCacheEntry, isCacheExpired, DEFAULT_TTL } from '../utils/cache';

export interface PostManagerState {
  listsMap: Map<string, CacheEntry<Post[]>>;
  detailsMap: Map<string, CacheEntry<Post | null>>;
  loadingListKeys: Set<string>;
  loadingDetailIds: Set<string>;
  pendingRequests: Map<string, Promise<any>>;
}

export interface PostManagerActions {
  getPostsList: (type: string, page: number, pageSize: number) => Post[] | null;
  getPostDetail: (postId: string) => Post | null;
  isListExpired: (type: string, page: number, pageSize: number) => boolean;
  isDetailExpired: (postId: string) => boolean;
  isLoadingList: (type: string, page: number, pageSize: number) => boolean;
  isLoadingDetail: (postId: string) => boolean;
  setPostsList: (type: string, page: number, pageSize: number, posts: Post[]) => void;
  setPostDetail: (postId: string, post: Post | null) => void;
  setLoadingList: (type: string, page: number, pageSize: number, loading: boolean) => void;
  setLoadingDetail: (postId: string, loading: boolean) => void;
  invalidateList: (type?: string, page?: number, pageSize?: number) => void;
  invalidateDetail: (postId: string) => void;
  invalidateAll: () => void;
  getPendingRequest: <T>(key: string) => Promise<T> | undefined;
  setPendingRequest: <T>(key: string, request: Promise<T>) => void;
  deletePendingRequest: (key: string) => void;
  clearPendingRequests: () => void;
  reset: () => void;
}

function buildListKey(type: string, page: number, pageSize: number): string {
  return `list:${type}:${page}:${pageSize}`;
}

const initialState: PostManagerState = {
  listsMap: new Map(),
  detailsMap: new Map(),
  loadingListKeys: new Set(),
  loadingDetailIds: new Set(),
  pendingRequests: new Map(),
};

export type PostManagerStore = PostManagerState & PostManagerActions;

export const usePostManagerStore = create<PostManagerStore>((set, get) => ({
  ...initialState,

  getPostsList: (type: string, page: number, pageSize: number) => {
    const key = buildListKey(type, page, pageSize);
    const entry = get().listsMap.get(key);
    if (!entry) return null;
    if (isCacheExpired(entry)) return null;
    return entry.data;
  },

  getPostDetail: (postId: string) => {
    const entry = get().detailsMap.get(postId);
    if (!entry) return null;
    if (isCacheExpired(entry)) return null;
    return entry.data;
  },

  isListExpired: (type: string, page: number, pageSize: number) => {
    const key = buildListKey(type, page, pageSize);
    const entry = get().listsMap.get(key);
    if (!entry) return true;
    return isCacheExpired(entry);
  },

  isDetailExpired: (postId: string) => {
    const entry = get().detailsMap.get(postId);
    if (!entry) return true;
    return isCacheExpired(entry);
  },

  isLoadingList: (type: string, page: number, pageSize: number) => {
    const key = buildListKey(type, page, pageSize);
    return get().loadingListKeys.has(key);
  },

  isLoadingDetail: (postId: string) => {
    return get().loadingDetailIds.has(postId);
  },

  setPostsList: (type: string, page: number, pageSize: number, posts: Post[]) => {
    const key = buildListKey(type, page, pageSize);
    set(state => {
      const newListsMap = new Map(state.listsMap);
      newListsMap.set(key, createCacheEntry(posts, DEFAULT_TTL.POST_LIST));
      return { listsMap: newListsMap };
    });
  },

  setPostDetail: (postId: string, post: Post | null) => {
    set(state => {
      const newDetailsMap = new Map(state.detailsMap);
      newDetailsMap.set(postId, createCacheEntry(post, DEFAULT_TTL.POST_DETAIL));
      return { detailsMap: newDetailsMap };
    });
  },

  setLoadingList: (type: string, page: number, pageSize: number, loading: boolean) => {
    const key = buildListKey(type, page, pageSize);
    set(state => {
      const newLoadingListKeys = new Set(state.loadingListKeys);
      if (loading) {
        newLoadingListKeys.add(key);
      } else {
        newLoadingListKeys.delete(key);
      }
      return { loadingListKeys: newLoadingListKeys };
    });
  },

  setLoadingDetail: (postId: string, loading: boolean) => {
    set(state => {
      const newLoadingDetailIds = new Set(state.loadingDetailIds);
      if (loading) {
        newLoadingDetailIds.add(postId);
      } else {
        newLoadingDetailIds.delete(postId);
      }
      return { loadingDetailIds: newLoadingDetailIds };
    });
  },

  invalidateList: (type?: string, page?: number, pageSize?: number) => {
    if (type !== undefined && page !== undefined && pageSize !== undefined) {
      const key = buildListKey(type, page, pageSize);
      set(state => {
        const newListsMap = new Map(state.listsMap);
        newListsMap.delete(key);
        return { listsMap: newListsMap };
      });
    } else {
      set({ listsMap: new Map() });
    }
  },

  invalidateDetail: (postId: string) => {
    set(state => {
      const newDetailsMap = new Map(state.detailsMap);
      newDetailsMap.delete(postId);
      return { detailsMap: newDetailsMap };
    });
  },

  invalidateAll: () => {
    set({
      listsMap: new Map(),
      detailsMap: new Map(),
      pendingRequests: new Map(),
    });
  },

  getPendingRequest: <T>(key: string) => {
    return get().pendingRequests.get(key) as Promise<T> | undefined;
  },

  setPendingRequest: <T>(key: string, request: Promise<T>) => {
    set(state => {
      const newPendingRequests = new Map(state.pendingRequests);
      newPendingRequests.set(key, request);
      return { pendingRequests: newPendingRequests };
    });
  },

  deletePendingRequest: (key: string) => {
    set(state => {
      const newPendingRequests = new Map(state.pendingRequests);
      newPendingRequests.delete(key);
      return { pendingRequests: newPendingRequests };
    });
  },

  clearPendingRequests: () => {
    set({ pendingRequests: new Map() });
  },

  reset: () => {
    set({
      ...initialState,
      listsMap: new Map(),
      detailsMap: new Map(),
      loadingListKeys: new Set(),
      loadingDetailIds: new Set(),
      pendingRequests: new Map(),
    });
  },
}));