import { postRepository } from '../../data/repositories/PostRepository';
import type { Post } from '../../core/entities/Post';
import type {
  GetPostsParams,
  CreatePostData,
  UpdatePostData,
  PostsResult,
  SearchPostsParams,
} from '../../data/repositories/interfaces/IPostRepository';
import { PaginationStateManager } from '../../infrastructure/pagination/PaginationStateManager';
import type { PaginationState } from '../../infrastructure/pagination/types';
import { usePostListStore, type PostsState } from '../../stores/post/postListStore';
import { mergePostListWithFastPath, mergeRefreshWindow } from './postMerge';

export type { PostsState } from '../../stores/post/postListStore';

export interface PostDetailState {
  post: Post | null;
  isLoading: boolean;
  error: string | null;
}

const DEFAULT_PAGE_SIZE = 20;
const MERGE_PERF_WARN_THRESHOLD_MS = 12;

class PostSyncService {
  private static instance: PostSyncService;
  private paginationManager: PaginationStateManager;
  private currentUserId: string | null = null;

  private constructor() {
    this.paginationManager = new PaginationStateManager();
  }

  static getInstance(): PostSyncService {
    if (!PostSyncService.instance) {
      PostSyncService.instance = new PostSyncService();
    }
    return PostSyncService.instance;
  }

  initialize(currentUserId: string | null = null): void {
    this.currentUserId = currentUserId;
  }

  destroy(): void {
    usePostListStore.getState().clearAllStates();
    this.paginationManager.clear();
    this.currentUserId = null;
  }

  getPostsState(key: string = 'default'): PostsState {
    return usePostListStore.getState().getPostsState(key);
  }

  getPostDetailState(postId: string): PostDetailState {
    return usePostListStore.getState().getPostDetailState(postId);
  }

  applyShareCountUpdate(postId: string, sharesCount: number): void {
    usePostListStore.getState().applyShareCountUpdate(postId, sharesCount);
  }

  async fetchPosts(params?: GetPostsParams, key: string = 'default'): Promise<PostsResult> {
    const store = usePostListStore.getState();
    store.updatePostsState(key, { isLoading: true, error: null });

    try {
      const queryParams: GetPostsParams = {
        pageSize: params?.pageSize || DEFAULT_PAGE_SIZE,
        ...params,
        cursor: params?.cursor !== undefined ? params.cursor : '',
      };

      const result = await postRepository.getPosts(queryParams);
      const isCursorMode = result.nextCursor !== undefined && result.nextCursor !== null;

      const currentState = usePostListStore.getState().getPostsState(key);
      const incomingPosts = Array.isArray(result.posts) ? result.posts : [];
      const mergeStart = Date.now();
      const mergedPosts = mergeRefreshWindow(currentState.posts, incomingPosts);
      const mergeCost = Date.now() - mergeStart;
      if (mergeCost >= MERGE_PERF_WARN_THRESHOLD_MS) {
        console.log('[PostPerf] fetchPosts merge cost', { key, costMs: mergeCost, prev: currentState.posts.length, next: incomingPosts.length });
      }

      usePostListStore.getState().updatePostsState(key, {
        posts: mergedPosts,
        hasMore: result.hasMore,
        cursor: isCursorMode ? result.nextCursor : null,
        currentPage: isCursorMode ? undefined : 1,
        isLoading: false,
        lastLoadTime: Date.now(),
        lastParams: params,
      });

      return result;
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : '获取帖子列表失败';
      usePostListStore.getState().updatePostsState(key, { isLoading: false, error: errorMessage });
      throw error;
    }
  }

  async refreshPosts(key: string = 'default'): Promise<PostsResult> {
    const state = usePostListStore.getState().getPostsState(key);
    usePostListStore.getState().updatePostsState(key, { isRefreshing: true, error: null });

    try {
      const result = await postRepository.getPosts({
        pageSize: DEFAULT_PAGE_SIZE,
        ...state.lastParams,
        cursor: state.lastParams?.cursor !== undefined ? state.lastParams.cursor : '',
      });

      const isCursorMode = result.nextCursor !== undefined && result.nextCursor !== null;
      const incomingPosts = Array.isArray(result.posts) ? result.posts : [];
      const mergeStart = Date.now();
      const mergedPosts = mergeRefreshWindow(state.posts, incomingPosts);
      const mergeCost = Date.now() - mergeStart;
      if (mergeCost >= MERGE_PERF_WARN_THRESHOLD_MS) {
        console.log('[PostPerf] refreshPosts merge cost', { key, costMs: mergeCost, prev: state.posts.length, next: incomingPosts.length });
      }

      usePostListStore.getState().updatePostsState(key, {
        posts: mergedPosts,
        hasMore: result.hasMore,
        cursor: isCursorMode ? result.nextCursor : null,
        currentPage: isCursorMode ? undefined : 1,
        isRefreshing: false,
        lastLoadTime: Date.now(),
      });

      this.paginationManager.reset(key);
      return result;
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : '刷新帖子列表失败';
      usePostListStore.getState().updatePostsState(key, { isRefreshing: false, error: errorMessage });
      throw error;
    }
  }

  async loadMorePosts(key: string = 'default'): Promise<PostsResult> {
    const state = usePostListStore.getState().getPostsState(key);

    if (!state.hasMore) return { posts: [], hasMore: false };
    if (state.isLoading) return { posts: [], hasMore: state.hasMore };

    usePostListStore.getState().updatePostsState(key, { isLoading: true, error: null });

    try {
      const useCursorMode = state.cursor !== null && state.cursor !== undefined;
      const base = { ...(state.lastParams ?? {}) } as GetPostsParams;
      let queryParams: GetPostsParams;

      if (useCursorMode) {
        delete base.page;
        queryParams = { ...base, pageSize: DEFAULT_PAGE_SIZE, cursor: state.cursor! };
      } else {
        const nextPage = (state.currentPage || 1) + 1;
        delete base.cursor;
        queryParams = { ...base, pageSize: DEFAULT_PAGE_SIZE, page: nextPage };
      }

      const result = await postRepository.getPosts(queryParams);
      const incomingPosts = Array.isArray(result.posts) ? result.posts : [];
      const mergeStart = Date.now();
      const newPosts = mergePostListWithFastPath(state.posts, incomingPosts);
      const mergeCost = Date.now() - mergeStart;
      if (mergeCost >= MERGE_PERF_WARN_THRESHOLD_MS) {
        console.log('[PostPerf] loadMore merge cost', { key, costMs: mergeCost, prev: state.posts.length, incoming: incomingPosts.length, merged: newPosts.length });
      }

      const responseIsCursorMode = result.nextCursor !== undefined && result.nextCursor !== null;

      usePostListStore.getState().updatePostsState(key, {
        posts: newPosts,
        hasMore: result.hasMore,
        cursor: responseIsCursorMode ? result.nextCursor : null,
        currentPage: useCursorMode ? state.currentPage : ((state.currentPage || 1) + 1),
        isLoading: false,
        lastLoadTime: Date.now(),
      });

      return { posts: incomingPosts, hasMore: result.hasMore, nextCursor: result.nextCursor };
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : '加载更多帖子失败';
      console.error('[PostSyncService] Load more error:', errorMessage);
      usePostListStore.getState().updatePostsState(key, { isLoading: false, error: errorMessage });
      throw error;
    }
  }

  async fetchPostById(id: string): Promise<Post | null> {
    usePostListStore.getState().updatePostDetailState(id, { isLoading: true, error: null });

    try {
      const post = await postRepository.getPostById(id);
      usePostListStore.getState().updatePostDetailState(id, { post, isLoading: false });
      return post;
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : '获取帖子详情失败';
      usePostListStore.getState().updatePostDetailState(id, { isLoading: false, error: errorMessage });
      throw error;
    }
  }

  async createPost(data: CreatePostData): Promise<Post> {
    const post = await postRepository.createPost(data);
    const store = usePostListStore.getState();
    const newMap = new Map(store.postsStateMap);
    for (const [key, postsState] of newMap) {
      newMap.set(key, { ...postsState, posts: [post, ...postsState.posts] });
    }
    usePostListStore.setState({ postsStateMap: newMap });
    return post;
  }

  async updatePost(id: string, data: UpdatePostData): Promise<Post> {
    const post = await postRepository.updatePost(id, data);
    usePostListStore.getState().updatePostDetailState(id, { post });
    usePostListStore.getState().updatePostInLists(id, post);
    return post;
  }

  async deletePost(id: string): Promise<void> {
    await postRepository.deletePost(id);
    usePostListStore.getState().clearPostDetailState(id);
    usePostListStore.getState().removePostFromLists(id);
  }

  async likePost(id: string): Promise<Post> {
    const post = await postRepository.likePost(id);
    usePostListStore.getState().updatePostDetailState(id, { post });
    usePostListStore.getState().updatePostInLists(id, post);
    return post;
  }

  async unlikePost(id: string): Promise<Post> {
    const post = await postRepository.unlikePost(id);
    usePostListStore.getState().updatePostDetailState(id, { post });
    usePostListStore.getState().updatePostInLists(id, post);
    return post;
  }

  async favoritePost(id: string): Promise<Post> {
    const post = await postRepository.favoritePost(id);
    usePostListStore.getState().updatePostDetailState(id, { post });
    usePostListStore.getState().updatePostInLists(id, post);
    return post;
  }

  async unfavoritePost(id: string): Promise<Post> {
    const post = await postRepository.unfavoritePost(id);
    usePostListStore.getState().updatePostDetailState(id, { post });
    usePostListStore.getState().updatePostInLists(id, post);
    return post;
  }

  async searchPosts(params: SearchPostsParams, key: string = 'search'): Promise<PostsResult> {
    usePostListStore.getState().updatePostsState(key, { isLoading: true, error: null });

    try {
      const result = await postRepository.searchPosts(params);
      usePostListStore.getState().updatePostsState(key, {
        posts: result.posts,
        hasMore: result.hasMore,
        cursor: result.nextCursor || null,
        isLoading: false,
        lastLoadTime: Date.now(),
      });
      return result;
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : '搜索帖子失败';
      usePostListStore.getState().updatePostsState(key, { isLoading: false, error: errorMessage });
      throw error;
    }
  }

  async fetchPostsByUser(userId: string, params?: GetPostsParams, key?: string): Promise<PostsResult> {
    const listKey = key || `user_${userId}`;
    usePostListStore.getState().updatePostsState(listKey, { isLoading: true, error: null });

    try {
      const result = await postRepository.getPostsByUser(userId, params);
      usePostListStore.getState().updatePostsState(listKey, {
        posts: result.posts,
        hasMore: result.hasMore,
        cursor: result.nextCursor || null,
        isLoading: false,
        lastLoadTime: Date.now(),
      });
      return result;
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : '获取用户帖子失败';
      usePostListStore.getState().updatePostsState(listKey, { isLoading: false, error: errorMessage });
      throw error;
    }
  }

  clearPostsState(key: string = 'default'): void {
    usePostListStore.getState().clearPostsState(key);
    this.paginationManager.reset(key);
  }

  clearPostDetailState(postId: string): void {
    usePostListStore.getState().clearPostDetailState(postId);
  }

  clearAllStates(): void {
    usePostListStore.getState().clearAllStates();
    this.paginationManager.clear();
  }

  getCurrentUserId(): string | null {
    return this.currentUserId;
  }

  setCurrentUserId(userId: string | null): void {
    this.currentUserId = userId;
  }

  getPaginationState(key: string): PaginationState {
    return this.paginationManager.getState(key);
  }

  resetPagination(key: string): void {
    this.paginationManager.reset(key);
  }

  isLoading(key: string = 'default'): boolean {
    return usePostListStore.getState().getPostsState(key).isLoading;
  }

  hasError(key: string = 'default'): boolean {
    return usePostListStore.getState().getPostsState(key).error !== null;
  }

  getError(key: string = 'default'): string | null {
    return usePostListStore.getState().getPostsState(key).error;
  }
}

export const postSyncService = PostSyncService.getInstance();
export { PostSyncService };
export default postSyncService;
