/**
 * 消息服务
 * 处理私信/聊天消息功能
 * 使用新的 API 接口: /api/v1/conversations (RESTful action 风格)
 */

import { api } from './api';
import {
  ConversationListResponse,
  ConversationResponse,
  ConversationDetailResponse,
  MessageListResponse,
  MessageResponse,
  SendMessageRequest,
  UnreadCountResponse,
  ConversationUnreadCountResponse,
  SystemMessageListResponse,
  SystemMessageResponse,
  SystemUnreadCountResponse,
  MessageSegment,
  CursorPaginationRequest,
  CursorPaginationResponse,
} from '../types/dto';
import {
  getConversationCache,
  getConversationListCache,
  saveConversationCache,
  saveConversationsWithRelatedCache,
  updateConversationCacheUnreadCount,
} from './database';

/** 远端会话列表分页（offset / cursor）统一结果：拉取成功后均已执行本地缓存同步 */
export interface RemoteConversationListPageResult {
  items: ConversationResponse[];
  hasMore: boolean;
  /** cursor 模式：下一页游标；offset 模式固定为 null */
  nextCursor: string | null;
  /** offset 模式：下一次 loadNext 应请求的页码；cursor 模式为 undefined */
  nextPage?: number;
}

// 消息服务类
class MessageService {
  /** 与会话 offset 列表一致：将本页会话写入 SQLite，避免游标路径不落库导致冷启动未读与线上一致 */
  private async persistConversationListPageToLocalCache(
    list: ConversationResponse[]
  ): Promise<void> {
    if (!list.length) return;
    const users = list.flatMap(conv => [
      ...(conv.participants || []),
      ...(conv.last_message?.sender ? [conv.last_message.sender] : []),
    ]);
    const groups = list
      .map(conv => conv.group)
      .filter((group): group is NonNullable<typeof group> => Boolean(group));
    await saveConversationsWithRelatedCache(list, users, groups);
  }

  /** offset 会话列表单页：请求 + 落库 */
  private async requestOffsetConversationsPage(
    page: number,
    pageSize: number
  ): Promise<ConversationListResponse> {
    const response = await api.get<ConversationListResponse>('/conversations', {
      page,
      page_size: pageSize,
    });
    const list = response.data.list || [];
    await this.persistConversationListPageToLocalCache(list);
    return response.data;
  }

  /** cursor 会话列表单页：请求 + 落库 */
  private async requestCursorConversationsPage(
    params: CursorPaginationRequest
  ): Promise<CursorPaginationResponse<ConversationResponse>> {
    try {
      const response = await api.get<CursorPaginationResponse<ConversationResponse>>(
        '/conversations/cursor',
        params
      );
      const raw = response.data;
      const list = Array.isArray(raw?.list) ? raw.list : [];
      await this.persistConversationListPageToLocalCache(list);
      return {
        list,
        next_cursor: raw?.next_cursor ?? null,
        prev_cursor: raw?.prev_cursor ?? null,
        has_more: raw?.has_more ?? false,
      };
    } catch (error) {
      console.error('获取会话列表失败:', error);
      return {
        list: [],
        next_cursor: null,
        prev_cursor: null,
        has_more: false,
      };
    }
  }

  private async refreshConversationsFromServer(
    page = 1,
    pageSize = 20
  ): Promise<ConversationListResponse> {
    return this.requestOffsetConversationsPage(page, pageSize);
  }

  /**
   * 远端会话列表单页（offset / cursor 统一入口）
   * 两种模式均先写 SQLite 再返回，行为与 NetworkRemoteConversationListPagedSource 配套。
   */
  async fetchRemoteConversationListPage(args: {
    mode: 'offset' | 'cursor';
    pageSize: number;
    /** offset：本次页码，默认 1 */
    page?: number;
    /** cursor：本次游标；首屏不传或 null */
    cursor?: string | null;
    direction?: CursorPaginationRequest['direction'];
  }): Promise<RemoteConversationListPageResult> {
    if (args.mode === 'offset') {
      const page = args.page ?? 1;
      const data = await this.requestOffsetConversationsPage(page, args.pageSize);
      const totalPages = Math.max(0, data.total_pages ?? 0);
      const currentPage = data.page ?? page;
      const hasMore = totalPages > 0 && currentPage < totalPages;
      return {
        items: data.list || [],
        hasMore,
        nextCursor: null,
        nextPage: currentPage + 1,
      };
    }

    const raw = await this.requestCursorConversationsPage({
      page_size: args.pageSize,
      ...(args.cursor != null && args.cursor !== ''
        ? { cursor: args.cursor }
        : {}),
      ...(args.direction ? { direction: args.direction } : {}),
    });
    const items = raw.list || [];
    const nextCursor = raw.next_cursor ?? null;
    const hasMore = Boolean(raw.has_more && nextCursor != null);
    return { items, hasMore, nextCursor };
  }

  private async refreshConversationDetailFromServer(id: string): Promise<ConversationDetailResponse> {
    const response = await api.get<ConversationDetailResponse>(
      `/conversations/${encodeURIComponent(id)}`
    );
    await saveConversationCache(response.data);
    if (response.data.participants?.length) {
      await saveUsersCache(response.data.participants);
    }
    if (response.data.last_message?.sender) {
      await saveUsersCache([response.data.last_message.sender]);
    }
    return response.data;
  }

  private normalizeCachedDetail(
    id: string,
    cached: any
  ): ConversationDetailResponse {
    return {
      id: String(cached?.id || id),
      type: cached?.type || 'private',
      is_pinned: Boolean(cached?.is_pinned),
      last_seq: Number(cached?.last_seq || 0),
      last_message: cached?.last_message,
      last_message_at: cached?.last_message_at || cached?.updated_at || new Date().toISOString(),
      unread_count: Number(cached?.unread_count || 0),
      participants: Array.isArray(cached?.participants) ? cached.participants : [],
      my_last_read_seq: Number(cached?.my_last_read_seq || 0),
      other_last_read_seq: Number(cached?.other_last_read_seq || 0),
      created_at: cached?.created_at || new Date().toISOString(),
      updated_at: cached?.updated_at || new Date().toISOString(),
    };
  }

  // ==================== 会话相关 ====================

  /**
   * 获取会话列表
   * GET /api/v1/conversations/list
   */
  async getConversations(
    page = 1,
    pageSize = 20,
    forceRefresh = false
  ): Promise<ConversationListResponse> {
    // 如果强制刷新,直接从服务器获取,不使用缓存
    if (!forceRefresh) {
      const cachedList = await getConversationListCache();
      if (cachedList.length > 0) {
        // 后台刷新数据,但不阻塞当前返回
        this.refreshConversationsFromServer(page, pageSize).catch(error => {
          console.error('后台刷新会话列表失败:', error);
        });
        return {
          list: cachedList,
          total: cachedList.length,
          page: 1,
          page_size: cachedList.length,
          total_pages: 1,
        };
      }
    }

    // 强制刷新或没有缓存时,直接从服务器获取
    try {
      return await this.refreshConversationsFromServer(page, pageSize);
    } catch (error) {
      console.error('获取会话列表失败:', error);
      return {
        list: [],
        total: 0,
        page: 1,
        page_size: pageSize,
        total_pages: 0,
      };
    }
  }

  /**
   * 创建私聊会话
   * POST /api/v1/conversations
   * @param userId 目标用户ID (UUID格式)
   */
  async createConversation(userId: string): Promise<ConversationResponse> {
    const response = await api.post<ConversationResponse>('/conversations', {
      user_id: userId,
    });
    await saveConversationCache(response.data);
    if (response.data.participants?.length) {
      await saveUsersCache(response.data.participants);
    }
    return response.data;
  }

  /**
   * 获取会话详情
   * GET /api/v1/conversations/:id
   */
  async getConversationById(id: string): Promise<ConversationDetailResponse> {
    const cached = await getConversationCache(id);
    if (cached) {
      this.refreshConversationDetailFromServer(id).catch(error => {
        console.error('后台刷新会话详情失败:', error);
      });
      return this.normalizeCachedDetail(id, cached);
    }

    try {
      return await this.refreshConversationDetailFromServer(id);
    } catch (error) {
      console.error('获取会话详情失败:', error);
      throw error;
    }
  }

  /**
   * 仅自己删除会话
   * DELETE /api/v1/conversations/:id/self
   */
  async deleteConversationForSelf(conversationId: string): Promise<void> {
    await api.delete(`/conversations/${encodeURIComponent(conversationId)}/self`);
  }

  /**
   * 设置会话置顶
   * PUT /api/v1/conversations/:id/pinned
   */
  async setConversationPinned(conversationId: string, isPinned: boolean): Promise<void> {
    await api.put(`/conversations/${encodeURIComponent(conversationId)}/pinned`, {
      is_pinned: isPinned,
    });
  }

  // ==================== 消息相关 ====================

  /**
   * 获取消息列表（支持增量同步和历史消息加载）
   * GET /api/v1/conversations/:id/messages
   * @param conversationId 会话ID
   * @param afterSeq 获取此序号之后的消息（增量同步，获取新消息）
   * @param beforeSeq 获取此序号之前的历史消息（下拉加载更多，获取旧消息）
   * @param limit 返回消息数量限制
   */
  async getMessages(
    conversationId: string,
    afterSeq?: number,
    beforeSeq?: number,
    limit?: number
  ): Promise<MessageListResponse> {
    const params: Record<string, any> = {};
    if (afterSeq !== undefined) {
      params.after_seq = afterSeq;
    }
    if (beforeSeq !== undefined) {
      params.before_seq = beforeSeq;
    }
    if (limit !== undefined) {
      params.limit = limit;
    }

    try {
      const response = await api.get<any>(
        `/conversations/${encodeURIComponent(conversationId)}/messages`,
        params
      );
      
      // 处理增量同步响应（after_seq 或 before_seq）
      if ((afterSeq !== undefined || beforeSeq !== undefined) && response.data.messages !== undefined) {
        return {
          messages: response.data.messages,
          total: response.data.messages.length,
          page: 1,
          page_size: limit || 100,
        };
      }

      // 处理分页响应（后端返回 list 字段）
      const data = response.data;
      return {
        messages: data.list || [],
        total: data.total || 0,
        page: data.page || 1,
        page_size: data.page_size || 20,
      };
    } catch (error) {
      console.error('获取消息列表失败:', error);
      return {
        messages: [],
        total: 0,
        page: 1,
        page_size: 20,
      };
    }
  }

  /**
   * 发送消息（新格式）
   * POST /api/v1/conversations/:id/messages
   * Body: { detail_type, segments }
   */
  async sendMessage(
    conversationId: string,
    data: SendMessageRequest,
    detailType: 'private' | 'group' = 'private'
  ): Promise<MessageResponse> {
    // 直接使用传入的 segments
    if (!data.segments || data.segments.length === 0) {
      throw new Error('消息内容不能为空');
    }
    
    return this.sendMessageByAction(
      detailType,
      conversationId,
      data.segments,
      data.reply_to_id
    );
  }

  /**
   * 通过 HTTP POST 发送消息（新格式）
   * 请求格式: POST /api/v1/conversations/:id/messages
   * Body: { "detail_type": "private", "segments": [...] }
   * @param detailType 消息类型: 'private' 私聊, 'group' 群聊
   * @param conversationId 会话ID
   * @param message 消息段数组 [{"type": "text", "data": {"text": "xxx"}}]
   * @param replyToId 回复的消息ID（可选）
   * @returns 消息响应
   */
  async sendMessageByAction(
    detailType: 'private' | 'group',
    conversationId: string,
    message: MessageSegment[],
    replyToId?: string
  ): Promise<MessageResponse> {
    try {
      const body: Record<string, any> = {
        detail_type: detailType,
        segments: message,
      };
      if (replyToId) {
        body.reply_to_id = replyToId;
      }
      const response = await api.post<MessageResponse>(
        `/conversations/${encodeURIComponent(conversationId)}/messages`,
        body
      );
      return response.data;
    } catch (error) {
      console.error('发送消息失败:', error);
      throw error;
    }
  }

  /**
   * 发送文本消息（便捷方法）
   */
  async sendTextMessage(
    conversationId: string,
    content: string,
    detailType: 'private' | 'group' = 'private'
  ): Promise<MessageResponse> {
    return this.sendTextMessageByAction(detailType, conversationId, content);
  }

  /**
   * 通过 HTTP POST 发送文本消息
   * @param detailType 消息类型: 'private' 私聊, 'group' 群聊
   * @param conversationId 会话ID
   * @param text 文本内容
   * @returns 消息响应
   */
  async sendTextMessageByAction(
    detailType: 'private' | 'group',
    conversationId: string,
    text: string
  ): Promise<MessageResponse> {
    const message: MessageSegment[] = [
      {
        type: 'text',
        data: {
          text: text,
        },
      },
    ];
    return this.sendMessageByAction(detailType, conversationId, message);
  }

  /**
   * 发送图片消息（便捷方法）
   */
  async sendImageMessage(
    conversationId: string,
    mediaUrl: string,
    content?: string,
    detailType: 'private' | 'group' = 'private'
  ): Promise<MessageResponse> {
    const message: MessageSegment[] = [
      {
        type: 'image',
        data: {
          url: mediaUrl,
        },
      },
    ];
    // 如果有文本说明，添加一个文本段
    if (content) {
      message.unshift({
        type: 'text',
        data: { text: content },
      });
    }
    return this.sendMessageByAction(detailType, conversationId, message);
  }

  /**
   * 发送 segments 格式消息（新版统一格式）
   * @param conversationId 会话ID
   * @param segments 消息链数组
   * @param detailType 消息类型
   */
  async sendSegmentsMessage(
    conversationId: string,
    segments: MessageSegment[],
    detailType: 'private' | 'group' = 'private'
  ): Promise<MessageResponse> {
    return this.sendMessageByAction(detailType, conversationId, segments);
  }

  /**
   * 发送带回复的 segments 消息
   * @param conversationId 会话ID
   * @param segments 消息链数组
   * @param replyToId 被回复消息的ID
   * @param detailType 消息类型
   */
  async sendReplySegmentsMessage(
    conversationId: string,
    segments: MessageSegment[],
    replyToId: string,
    detailType: 'private' | 'group' = 'private'
  ): Promise<MessageResponse> {
    // 使用 reply_to_id 参数发送回复消息
    return this.sendMessageByAction(detailType, conversationId, segments, replyToId);
  }

  /**
   * 撤回/删除消息
   * POST /api/v1/messages/delete_msg
   * Body: { "message_id": "xxx" }
   */
  async recallMessage(messageId: string): Promise<void> {
    await api.post('/messages/delete_msg', {
      message_id: messageId,
    });
  }

  /**
   * 删除消息（同撤回）
   * POST /api/v1/messages/delete_msg
   */
  async deleteMessage(messageId: string): Promise<void> {
    await this.recallMessage(messageId);
  }

  // ==================== 已读相关 ====================

  /**
   * 标记已读
   * POST /api/v1/conversations/:id/read
   * @param conversationId 会话ID
   * @param seq 已读到的消息序号
   */
  async markAsRead(conversationId: string, seq: number): Promise<void> {
    await api.post(`/conversations/${encodeURIComponent(conversationId)}/read`, {
      last_read_seq: Number(seq),
    });
    // 立即清零本地缓存中的 unread_count，并写入已读游标，避免冷启动仍显示旧红点
    updateConversationCacheUnreadCount(conversationId, 0, Number(seq)).catch(error => {
      console.error('更新本地会话未读数失败:', error);
    });
  }

  /**
   * 上报输入状态
   * POST /api/v1/conversations/:id/typing
   */
  async sendTyping(conversationId: string): Promise<void> {
    await api.post(`/conversations/${encodeURIComponent(conversationId)}/typing`);
  }

  /**
   * 获取未读总数
   * GET /api/v1/conversations/unread/count
   */
  async getUnreadCount(): Promise<UnreadCountResponse> {
    try {
      const response = await api.get<UnreadCountResponse>(
        '/conversations/unread/count'
      );
      return response.data;
    } catch (error) {
      console.error('获取未读总数失败:', error);
      return { total_unread_count: 0 };
    }
  }

  /**
   * 获取单个会话未读数
   * GET /api/v1/conversations/unread/count?conversation_id=xxx
   */
  async getConversationUnreadCount(
    conversationId: string
  ): Promise<ConversationUnreadCountResponse> {
    try {
      const response = await api.get<ConversationUnreadCountResponse>(
        '/conversations/unread/count',
        { conversation_id: conversationId }
      );
      return response.data;
    } catch (error) {
      console.error('获取会话未读数失败:', error);
      return {
        conversation_id: conversationId,
        unread_count: 0,
      };
    }
  }

  // ==================== 系统消息相关 ====================

  /**
   * 获取系统消息列表
   * GET /api/v1/messages/system
   * @param limit 返回数量限制
   * @param beforeId 获取此ID之前的消息（用于分页）
   */
  async getSystemMessages(
    pageSize: number = 20,
    page: number = 1
  ): Promise<SystemMessageListResponse> {
    try {
      const response = await api.get<{
        list: any[];
        total: number;
        page: number;
        page_size: number;
        total_pages: number;
      }>('/messages/system', {
        page,
        page_size: pageSize,
      });
      
      const data = response.data;
      return {
        messages: data.list || [],
        total: data.total || 0,
        has_more: data.page < data.total_pages,
      };
    } catch (error) {
      console.error('获取系统消息列表失败:', error);
      return {
        messages: [],
        total: 0,
        has_more: false,
      };
    }
  }

  /**
   * 获取系统消息未读数
   * GET /api/v1/messages/system/unread-count
   */
  async getSystemUnreadCount(): Promise<SystemUnreadCountResponse> {
    try {
      const response = await api.get<SystemUnreadCountResponse>(
        '/messages/system/unread-count'
      );
      return response.data;
    } catch (error) {
      console.error('获取系统消息未读数失败:', error);
      return { unread_count: 0 };
    }
  }

  /**
   * 标记单条系统消息已读
   * PUT /api/v1/messages/system/:messageId/read
   * @param messageId 消息ID
   */
  async markSystemMessageRead(messageId: string): Promise<void> {
    await api.put(`/messages/system/${encodeURIComponent(messageId)}/read`);
  }

  /**
   * 标记所有系统消息已读
   * PUT /api/v1/messages/system/read-all
   */
  async markAllSystemMessagesRead(): Promise<void> {
    await api.put('/messages/system/read-all');
  }

  // ==================== 游标分页方法 ====================

  /**
   * 获取消息列表（游标分页）
   * GET /api/v1/conversations/:id/messages/cursor
   * @param conversationId 会话ID
   * @param params 游标分页请求参数
   */
  async getMessagesCursor(
    conversationId: string,
    params: CursorPaginationRequest = {}
  ): Promise<CursorPaginationResponse<MessageResponse>> {
    try {
      const response = await api.get<any>(
        `/conversations/${encodeURIComponent(conversationId)}/messages/cursor`,
        params
      );
      const raw = response.data;
      return {
        list: Array.isArray(raw?.list) ? raw.list : [],
        next_cursor: raw?.next_cursor ?? null,
        prev_cursor: raw?.prev_cursor ?? null,
        has_more: raw?.has_more ?? false,
      };
    } catch (error) {
      console.error('获取消息列表失败:', error);
      return {
        list: [],
        next_cursor: null,
        prev_cursor: null,
        has_more: false,
      };
    }
  }

  /**
   * 获取系统消息列表（游标分页）
   * GET /api/v1/messages/system/cursor
   * @param params 游标分页请求参数
   */
  async getSystemMessagesCursor(
    params: CursorPaginationRequest = {}
  ): Promise<CursorPaginationResponse<SystemMessageResponse>> {
    try {
      // 始终传递 cursor 参数（空字符串表示首次请求），确保使用游标分页
      const requestParams: Record<string, any> = {
        cursor: params.cursor || '',
        page_size: params.page_size,
      };
      
      const response = await api.get<any>('/messages/system', requestParams);
      
      const data = response.data;
      
      // 游标或带 page/total_pages 的分页（统一为 CursorPaginationResponse：list）
      if (data && typeof data === 'object') {
        const list = Array.isArray(data.list) ? data.list : null;
        if (list) {
          const isPageShape =
            typeof data.page === 'number' &&
            typeof data.total_pages === 'number' &&
            data.next_cursor === undefined &&
            data.prev_cursor === undefined;
          if (isPageShape) {
            const currentPage = data.page || 1;
            const totalPages = data.total_pages || 1;
            return {
              list,
              next_cursor: currentPage < totalPages ? String(currentPage + 1) : null,
              prev_cursor: currentPage > 1 ? String(currentPage - 1) : null,
              has_more: currentPage < totalPages,
            };
          }
          return {
            list,
            next_cursor: data.next_cursor ?? null,
            prev_cursor: data.prev_cursor ?? null,
            has_more: data.has_more ?? false,
          };
        }
      }

      return {
        list: [],
        next_cursor: null,
        prev_cursor: null,
        has_more: false,
      };
    } catch (error) {
      console.error('获取系统消息列表失败:', error);
      return {
        list: [],
        next_cursor: null,
        prev_cursor: null,
        has_more: false,
      };
    }
  }
}

// 导出消息服务实例
export const messageService = new MessageService();

// 导出类型以方便使用
export type {
  ConversationListResponse,
  ConversationResponse,
  ConversationDetailResponse,
  MessageListResponse,
  MessageResponse,
  SendMessageRequest,
  UnreadCountResponse,
  ConversationUnreadCountResponse,
  SystemMessageListResponse,
  SystemUnreadCountResponse,
};
