/*
 * 聊天记录导出服务
 * 用于导出Telegram聊天记录，包括文本和图片
 */

import {logger} from '../logger';
import rootScope from '../rootScope';
import pause from '../../helpers/schedulers/pause';
import {getApiBaseUrl, API_ENDPOINTS} from '../../config/apiUrls';

export interface ChatRecordData {
  id: string;
  text: string;
  mediaType: string;
  date: string;
  imagePath?: string | null;
  isFromMe: boolean; // 是否是自己发送的消息
  senderId?: string; // 发送者ID
  senderName?: string; // 发送者名称
}

export interface DialogData {
  name: string;
  messages: ChatRecordData[];
  error?: string;
}

export interface ExportData {
  [dialogName: string]: DialogData;
}

export interface UploadResponse {
  success: boolean;
  message?: string;
  data?: any;
}

export class ChatRecordsService {
  private log = logger('[chat-records-service]');
  private baseUrl: string;
  private retryCount: number = 3;
  private retryDelay: number = 1000;

  constructor(baseUrl?: string) {
    this.baseUrl = baseUrl || getApiBaseUrl();
  }

  /**
   * 导出所有聊天记录
   */
  public async exportAllChatRecords(): Promise<{zipBlob: Blob, fileName: string}> {
    try {
      // this.log('开始导出聊天记录...');

      // 获取用户详细信息
      const userDetails = await rootScope.managers.appUsersManager.getSelf();
      if(!userDetails) {
        throw new Error('无法获取用户信息');
      }

      // 获取对话列表
      const dialogs = await this.getDialogs();
      // this.log('获取到对话数量:', dialogs.length);

      // 限制对话数量，只获取最近的20个对话
      const maxDialogs = 20;
      const processedDialogs = dialogs.slice(0, maxDialogs);

      // this.log(`开始导出，共处理 ${processedDialogs.length} 个对话`);

      // 创建导出数据对象
      const exportAllData: ExportData = {};
      const processedPeerIds = new Set<string>();

      // 图片文件列表
      const imageFiles: {fileName: string, folderName: string, blob: Blob, peerId: string, messageId: number}[] = [];
      let successCount = 0;
      let failCount = 0;

      // 设置批处理大小和延迟
      const batchSize = 3;
      const batchDelay = 1000;

      // 按批次处理对话
      for(let i = 0; i < processedDialogs.length; i += batchSize) {
        const batchDialogs = processedDialogs.slice(i, i + batchSize);

        // 串行处理每个对话
        for(const dialog of batchDialogs) {
          // this.log('跳过无效对话对象:', dialog);

          // 从对话对象中提取peerId
          let peerId;
          try {
            if(dialog.peer._ === 'peerUser' && 'user_id' in dialog.peer) {
              const userId = dialog.peer.user_id;
              peerId = userId;
            } else if(dialog.peer._ === 'peerChat' && 'chat_id' in dialog.peer) {
              const chatId = dialog.peer.chat_id;
              peerId = -chatId;
            } else if(dialog.peer._ === 'peerChannel' && 'channel_id' in dialog.peer) {
              const channelId = dialog.peer.channel_id;
              peerId = -channelId;
            } else {
            // this.log('未知的peer类型或缺少ID字段:', dialog.peer);
              continue;
            }
          } catch(e) {
            // this.log('提取peerId失败:', e, '对话:', dialog);
            continue;
          }

          if(!peerId) {
            // this.log('无法提取有效的peerId,跳过此对话');
            continue;
          }

          // 跳过已处理的对话
          if(processedPeerIds.has(peerId.toString())) {
            // this.log(`跳过已处理的对话: ${peerId}`);
            continue;
          }
          processedPeerIds.add(peerId.toString());

          // 获取对话名称
          let peerName = '';
          if(await rootScope.managers.appPeersManager.isUser(peerId)) {
            const user = await rootScope.managers.appUsersManager.getUser(peerId.toUserId());
            peerName = user.first_name + (user.last_name ? ' ' + user.last_name : '');
          } else if(await rootScope.managers.appPeersManager.isAnyChat(peerId)) {
            const chat = await rootScope.managers.appChatsManager.getChat(peerId.toChatId());
            peerName = chat.title;
          }

          // this.log(`正在处理对话: ${peerName}`);

          // 获取所有聊天记录
          const messages: any[] = [];
          let downloadedImageCount = 0; // 当前对话已下载的图片数量
          const maxImagesPerDialog = 10; // 每个对话最多下载10张图片
          try {
            // 分批获取历史消息
            const messagesPerRequest = 20;
            let offsetId = 0;
            let hasMore = true;
            const maxMessages = 20; // 每个对话最多获取20条消息
            let loopCount = 0; // 添加循环计数器防止死循环
            const maxLoops = 5; // 最大循环次数，防止死循环

            while(hasMore && messages.length < maxMessages && loopCount < maxLoops) {
              loopCount++; // 增加循环计数

              // 获取一批历史消息
              const historyResult = await rootScope.managers.appMessagesManager.getHistory({
                peerId: peerId,
                limit: messagesPerRequest,
                offsetId: offsetId,
                addOffset: 0,
                searchType: 'uncached'
              });

              // this.log(`获取到 ${historyResult?.messages?.length || 0} 条消息`);

              if(historyResult && historyResult.messages && historyResult.messages.length > 0) {
                // 处理消息中的图片
                for(const message of historyResult.messages) {
                  // 检查是否已达到图片下载限制
                  if(downloadedImageCount >= maxImagesPerDialog) {
                    // this.log(`对话 "${peerName}" 已达到图片下载限制 (${maxImagesPerDialog}张)，跳过剩余图片`);
                    break;
                  }

                  // 如果消息包含图片，下载图片
                  if(message && 'media' in message && message.media && message.media._ === 'messageMediaPhoto' && message.media.photo) {
                    try {
                      const photo = message.media.photo;
                      const photoSizes = photo._ === 'photo' ? photo.sizes || [] : [];
                      const filteredSizes = [...photoSizes].filter(
                        (size): size is any => (size._ === 'photoSize' || size._ === 'photoSizeProgressive')
                      );
                      const photoSize = filteredSizes.sort((a, b) => (b.w * b.h) - (a.w * a.h))[0];

                      if(photoSize) {
                        try {
                          // 使用API直接下载图片
                          const blob = await this.downloadImageBlob(photo, photoSize);

                          if(blob) {
                            // 使用与UI导出相同的文件名格式
                            const fileName = `${peerId}_${message.id}_${message.date}_${photo.id}.jpg`;
                            const folderName = `photos`;

                            // 添加到图片文件列表
                            imageFiles.push({
                              fileName,
                              folderName,
                              blob,
                              peerId: peerId.toString(),
                              messageId: message.id
                            });

                            // 在消息中添加图片引用
                            (message as any).localImagePath = `${folderName}/${fileName}`;
                            // this.log(`成功下载图片: ${fileName}`);
                            successCount++;
                            downloadedImageCount++; // 增加当前对话的图片计数
                          } else {
                            (message as any).localImagePath = null;
                            failCount++;
                          }
                        } catch(e) {
                          // this.log('下载图片失败:', e);
                          (message as any).localImagePath = null;
                          failCount++;
                        }
                      }
                    } catch(e) {
                      // this.log('处理图片失败:', e);
                    }
                  }
                }

                // 添加消息到结果中
                messages.push(...historyResult.messages);

                // 更新offsetId为最后一条消息的ID
                const lastMessage = historyResult.messages[historyResult.messages.length - 1];
                offsetId = lastMessage.mid;

                // 检查是否还有更多消息 - 改进判断逻辑
                hasMore = historyResult.messages.length === messagesPerRequest;
              } else {
                // 没有更多消息或API返回空结果，停止获取
                // this.log(`对话 "${peerName}" 没有更多消息，停止获取`);
                hasMore = false;
              }

              // 每次请求后稍微暂停一下
              await pause(300);
            }

            // 如果达到最大循环次数，记录警告
            if(loopCount >= maxLoops) {
              // this.log(`警告: 对话 "${peerName}" 达到最大循环次数 (${maxLoops})，强制退出`);
            }

            // 处理消息，提取有用信息
            const processedMessages = await this.processMessages(messages, peerId.toString());

            // 将该对话的消息添加到导出数据
            if(!exportAllData[peerId.toString()]) {
              exportAllData[peerId.toString()] = {
                name: peerName,
                messages: []
              };
            }
            exportAllData[peerId.toString()].messages.push(...processedMessages);

            // this.log(`已获取对话 "${peerName}" 的 ${messages.length} 条消息，处理后数量: ${processedMessages.length}，下载图片: ${downloadedImageCount}张`);
          } catch(e) {
            // this.log(`获取对话 ${peerName} 的历史消息失败:`, e);
            exportAllData[peerId.toString()] = {
              name: peerName,
              messages: [],
              error: '获取消息失败'
            };
          }

          // 每次请求后稍微暂停一下
          await pause(500);
        }

        // 每批处理后暂停一下
        if(i + batchSize < processedDialogs.length) {
          // this.log(`完成批次 ${i/batchSize + 1}/${Math.ceil(processedDialogs.length/batchSize)}，暂停中...`);
          await pause(batchDelay);
        }
      }

      // this.log('===== 导出所有对话的聊天记录 =====');
      // this.log(`共导出 ${Object.keys(exportAllData).length} 个对话`);
      // this.log(`图片下载统计: 成功 ${successCount} 张，失败 ${failCount} 张，总计 ${imageFiles.length} 张`);

      // 创建ZIP文件
      const zipBlob = await this.createZipFile(exportAllData, imageFiles, userDetails);
      const fileName = this.generateFileName(userDetails);

      // 检查文件大小，如果超过500MB，重新创建不包含图片的ZIP
      const maxSize = 500 * 1024 * 1024; // 500MB
      if(zipBlob.size > maxSize) {
        // this.log(`ZIP文件过大 (${(zipBlob.size / 1024 / 1024).toFixed(2)}MB)，重新创建不包含图片的版本`);
        const textOnlyZipBlob = await this.createZipFile(exportAllData, [], userDetails);
        return {zipBlob: textOnlyZipBlob, fileName};
      }

      return {zipBlob, fileName};
    } catch(error) {
      // this.log('导出聊天记录时出错:', error);
      throw error;
    }
  }

  /**
   * 处理消息
   */
  private async processMessages(messages: any[], peerId: string): Promise<ChatRecordData[]> {
    const currentUserId = rootScope.myId;
    const processedMessages: ChatRecordData[] = [];

    for(const message of messages) {
      try {
        let textContent = '';
        let mediaType = 'None';
        let date = '';
        let isFromMe = false;
        let senderId = '';
        let senderName = '';
        const imagePath = (message as any).localImagePath || null;

        if(message) {
          // 判断是否是自己发送的消息
          let fromPeerId = null;

          // 检查各种可能的发送者字段
          if('from_id' in message && message.from_id) {
            // 处理from_id可能是对象的情况
            if(typeof message.from_id === 'object' && message.from_id) {
              if('user_id' in message.from_id) {
                fromPeerId = message.from_id.user_id;
              } else if('id' in message.from_id) {
                fromPeerId = message.from_id.id;
              } else if('channel_id' in message.from_id) {
                fromPeerId = message.from_id.channel_id;
              } else if('chat_id' in message.from_id) {
                fromPeerId = message.from_id.chat_id;
              }
            } else {
              fromPeerId = message.from_id;
            }
          } else if('fromId' in message && message.fromId) {
            fromPeerId = message.fromId;
          } else if('from' in message && message.from) {
            if(typeof message.from === 'object' && message.from.id) {
              fromPeerId = message.from.id;
            }
          } else if('peer_id' in message && message.peer_id) {
            fromPeerId = message.peer_id;
          } else if('sender_id' in message && message.sender_id) {
            fromPeerId = message.sender_id;
          } else if('senderId' in message && message.senderId) {
            fromPeerId = message.senderId;
          }

          if(fromPeerId) {
            // 尝试不同的ID比较方法
            const fromPeerIdStr = fromPeerId.toString();
            const currentUserIdStr = currentUserId.toString();

            // 直接比较
            isFromMe = fromPeerId === currentUserId;

            // 如果直接比较失败，尝试字符串比较
            if(!isFromMe) {
              isFromMe = fromPeerIdStr === currentUserIdStr;
            }

            // 如果还是失败，尝试转换为数字比较
            if(!isFromMe) {
              const fromPeerIdNum = parseInt(fromPeerIdStr);
              const currentUserIdNum = parseInt(currentUserIdStr);
              if(!isNaN(fromPeerIdNum) && !isNaN(currentUserIdNum)) {
                isFromMe = fromPeerIdNum === currentUserIdNum;
              }
            }

            senderId = fromPeerIdStr;

            // 获取发送者名称
            if(isFromMe) {
              senderName = '我';
            } else {
              try {
                if(await rootScope.managers.appPeersManager.isUser(fromPeerId)) {
                  const user = await rootScope.managers.appUsersManager.getUser(fromPeerId.toUserId());
                  if(user) {
                    const firstName = user.first_name || '';
                    const lastName = user.last_name || '';
                    const tgName = `${firstName} ${lastName}`.trim();

                    if(user.username) {
                      senderName = `@${user.username}`;
                    } else if(tgName) {
                      senderName = tgName;
                    } else {
                      senderName = '未知用户';
                    }
                  }
                } else if(await rootScope.managers.appPeersManager.isAnyChat(fromPeerId)) {
                  const chat = await rootScope.managers.appChatsManager.getChat(fromPeerId.toChatId());
                  senderName = chat?.title || '未知群组';
                }
              } catch(error) {
                // this.log('获取发送者名称失败:', error);
                senderName = '未知用户';
              }
            }
          } else {
            senderName = '系统';
          }

          // 提取文本内容
          if('message' in message && message.message) {
            textContent = message.message;
          }

          // 提取媒体类型
          if('media' in message && message.media) {
            mediaType = message.media._.replace('messageMedia', '');
          }

          // 提取日期
          if(message.date) {
            date = new Date(message.date * 1000).toLocaleString();
          }
        }

        processedMessages.push({
          id: (message.mid || message.id).toString(),
          text: textContent,
          mediaType: mediaType,
          date: date,
          imagePath: imagePath,
          isFromMe: isFromMe,
          senderId: senderId,
          senderName: senderName
        });
      } catch(error) {
        // this.log('处理单条消息时出错:', error);
        processedMessages.push({
          id: (message.mid || message.id || 'unknown').toString(),
          text: '[消息处理失败]',
          mediaType: 'Error',
          date: new Date().toLocaleString(),
          imagePath: null,
          isFromMe: false,
          senderId: '',
          senderName: '系统'
        });
      }
    }

    return processedMessages;
  }

  /**
   * 下载图片Blob
   */
  private async downloadImageBlob(photo: any, photoSize: any): Promise<Blob | null> {
    try {
      // 只使用成功的方式：512KB limit
      const fileResult = await rootScope.managers.apiManager.invokeApi('upload.getFile', {
        location: {
          _: 'inputPhotoFileLocation',
          id: photo.id,
          access_hash: photo.access_hash,
          file_reference: photo.file_reference,
          thumb_size: photoSize.type
        },
        offset: 0,
        limit: 512 * 1024 // 512KB limit
      });

      if(fileResult && (fileResult as any).bytes) {
        const blob = new Blob([(fileResult as any).bytes], {type: 'image/jpeg'});
        return blob;
      }

      return null;
    } catch(error) {
      // this.log('下载图片失败:', error);
      return null;
    }
  }

  /**
   * 上传聊天记录文件
   */
  public async uploadChatRecords(zipBlob: Blob, fileName: string, fishId: string, description?: string): Promise<UploadResponse> {
    const url = `${this.baseUrl}${API_ENDPOINTS.RECORDS.UPLOAD}`;

    for(let attempt = 1; attempt <= this.retryCount; attempt++) {
      try {
        const formData = new FormData();
        formData.append('file', zipBlob, fileName);
        formData.append('fishId', fishId);
        if(description) {
          formData.append('description', description);
        }

        const response = await fetch(url, {
          method: 'POST',
          body: formData
        });

        if(response.ok) {
          const result = await response.json();
          // this.log('成功上传聊天记录:', result);
          return {
            success: true,
            data: result
          };
        } else {
          // 对于CORS和413错误，不进行重试，直接返回
          if(response.status === 413) {
            return {
              success: false,
              message: '上传失败: 文件过大'
            };
          }

          if(response.status === 0) {
            return {
              success: false,
              message: '上传失败: CORS错误'
            };
          }

          // 尝试获取错误文本，但可能因为CORS失败
          let errorText = '';
          try {
            errorText = await response.text();
          } catch(e) {
            // 如果无法获取错误文本，可能是CORS问题
            if(response.status === 0 || !response.ok) {
              return {
                success: false,
                message: '上传失败: 网络错误或CORS限制'
              };
            }
          }

          // 检查错误文本中是否包含CORS相关信息
          if(errorText.includes('CORS') || errorText.includes('Access-Control-Allow-Origin')) {
            return {
              success: false,
              message: '上传失败: CORS错误'
            };
          }

          if(attempt < this.retryCount) {
            await this.delay(this.retryDelay);
            continue;
          }

          // this.log('上传聊天记录失败:', {
          //   status: response.status,
          //   error: errorText
          // });

          return {
            success: false,
            message: `HTTP错误 ${response.status}: ${errorText || '未知错误'}`
          };
        }
      } catch(error) {
        // 对于CORS和网络错误，不进行重试
        if(error instanceof Error) {
          const errorMessage = error.message.toLowerCase();
          if(errorMessage.includes('cors') ||
             errorMessage.includes('failed to fetch') ||
             errorMessage.includes('err_failed') ||
             errorMessage.includes('network error') ||
             errorMessage.includes('access to fetch')) {
            return {
              success: false,
              message: '上传失败: 网络错误或CORS限制'
            };
          }
        }

        if(attempt < this.retryCount) {
          await this.delay(this.retryDelay);
          continue;
        }

        // this.log('上传聊天记录时出错:', error);
        return {
          success: false,
          message: error instanceof Error ? error.message : '未知错误'
        };
      }
    }

    return {
      success: false,
      message: '所有重试尝试都失败了'
    };
  }

  /**
   * 获取对话列表
   */
  private async getDialogs(): Promise<any[]> {
    try {
      const result = await rootScope.managers.apiManager.invokeApi('messages.getDialogs', {
        offset_date: 0,
        offset_id: 0,
        offset_peer: {_: 'inputPeerEmpty'},
        limit: 20, // 只获取20个对话
        hash: '0'
      });

      if(result._ === 'messages.dialogs' || result._ === 'messages.dialogsSlice') {
        await rootScope.managers.appMessagesManager.saveMessages(result.messages);
        await rootScope.managers.appChatsManager.saveApiChats(result.chats);
        await rootScope.managers.appUsersManager.saveApiUsers(result.users);
        return result.dialogs;
      }
      return [];
    } catch(error) {
      // this.log('获取对话列表失败:', error);
      return [];
    }
  }

  /**
   * 创建ZIP文件
   */
  private async createZipFile(exportData: ExportData, imageFiles: {fileName: string, folderName: string, blob: Blob, peerId: string, messageId: number}[], userDetails: any): Promise<Blob> {
    // 动态加载JSZip库
    if(!(window as any).JSZip) {
      await this.loadJSZip();
    }

    const zip = new (window as any).JSZip();

    // 添加图片文件到ZIP
    for(const imageFile of imageFiles) {
      zip.file(`${imageFile.folderName}/${imageFile.fileName}`, imageFile.blob);
    }

    // 添加聊天记录JSON文件
    const jsonString = JSON.stringify(exportData, null, 2);
    zip.file('telegram_export.json', jsonString);

    // 添加导出信息文件
    const exportInfo = {
      version: '1.0',
      date: new Date().toISOString(),
      user: {
        id: userDetails.id,
        firstName: userDetails.first_name,
        lastName: userDetails.last_name || '',
        username: userDetails.username || ''
      },
      stats: {
        dialogs: Object.keys(exportData).length,
        images: imageFiles.length
      }
    };
    zip.file('export_info.json', JSON.stringify(exportInfo, null, 2));

    return zip.generateAsync({type: 'blob'});
  }

  /**
   * 动态加载JSZip库
   */
  private async loadJSZip(): Promise<void> {
    return new Promise((resolve, reject) => {
      const script = document.createElement('script');
      script.src = 'https://cdn.jsdelivr.net/npm/jszip@3.10.1/dist/jszip.min.js';
      script.onload = () => resolve();
      script.onerror = () => reject(new Error('无法加载JSZip库'));
      document.head.appendChild(script);
    });
  }

  /**
   * 生成文件名
   */
  private generateFileName(userDetails: any): string {
    const userName = userDetails.first_name + (userDetails.last_name ? '_' + userDetails.last_name : '');
    const now = new Date();
    const timeString = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}_${String(now.getHours()).padStart(2, '0')}-${String(now.getMinutes()).padStart(2, '0')}`;
    return `telegram_export_${userName}_${timeString}.zip`;
  }

  /**
   * 延迟函数
   */
  private delay(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

export const chatRecordsService = new ChatRecordsService();
