import { AppDataSource, Comment, PlatformAccount, Work } from '../models/index.js';
import { AppError } from '../middleware/error.js';
import { ERROR_CODES, HTTP_STATUS, WS_EVENTS } from '@media-manager/shared';
import type {
  Comment as CommentType,
  CommentStats,
  PaginatedData,
  PlatformType,
} from '@media-manager/shared';
import { wsManager } from '../websocket/index.js';
import { headlessBrowserService, type WorkComments, type CookieData } from './HeadlessBrowserService.js';
import { CookieManager } from '../automation/cookie.js';
import { logger } from '../utils/logger.js';

interface GetCommentsParams {
  page: number;
  pageSize: number;
  accountId?: number;
  workId?: number;
  platform?: string;
  isRead?: boolean;
  keyword?: string;
}

export class CommentService {
  private commentRepository = AppDataSource.getRepository(Comment);

  async getComments(userId: number, params: GetCommentsParams): Promise<PaginatedData<CommentType>> {
    const { page, pageSize, accountId, workId, platform, isRead, keyword } = params;
    const skip = (page - 1) * pageSize;

    const queryBuilder = this.commentRepository
      .createQueryBuilder('comment')
      .where('comment.userId = :userId', { userId });

    if (accountId) {
      queryBuilder.andWhere('comment.accountId = :accountId', { accountId });
    }
    if (workId) {
      // 直接使用 workId 查询
      queryBuilder.andWhere('comment.workId = :workId', { workId });
      logger.info(`Querying comments for workId: ${workId}`);
    }
    if (platform) {
      queryBuilder.andWhere('comment.platform = :platform', { platform });
    }
    if (isRead !== undefined) {
      queryBuilder.andWhere('comment.isRead = :isRead', { isRead });
    }
    if (keyword) {
      queryBuilder.andWhere(
        '(comment.content LIKE :keyword OR comment.authorName LIKE :keyword)',
        { keyword: `%${keyword}%` }
      );
    }

    // 打印查询 SQL 用于调试
    logger.info(`Comment query: userId=${userId}, accountId=${accountId}, workId=${workId}, platform=${platform}`);
    
    const [comments, total] = await queryBuilder
      .orderBy('comment.commentTime', 'DESC')
      .skip(skip)
      .take(pageSize)
      .getManyAndCount();
    
    logger.info(`Found ${total} comments`);

    return {
      items: comments.map(this.formatComment),
      total,
      page,
      pageSize,
      totalPages: Math.ceil(total / pageSize),
    };
  }

  async getStats(userId: number): Promise<CommentStats> {
    const totalCount = await this.commentRepository.count({ where: { userId } });
    const unreadCount = await this.commentRepository.count({ where: { userId, isRead: false } });
    const unrepliedCount = await this.commentRepository
      .createQueryBuilder('comment')
      .where('comment.userId = :userId', { userId })
      .andWhere('comment.replyContent IS NULL')
      .getCount();

    const today = new Date();
    today.setHours(0, 0, 0, 0);
    const todayCount = await this.commentRepository
      .createQueryBuilder('comment')
      .where('comment.userId = :userId', { userId })
      .andWhere('comment.createdAt >= :today', { today })
      .getCount();

    return { totalCount, unreadCount, unrepliedCount, todayCount };
  }

  async markAsRead(userId: number, commentIds: number[]): Promise<void> {
    await this.commentRepository
      .createQueryBuilder()
      .update(Comment)
      .set({ isRead: true })
      .where('userId = :userId AND id IN (:...commentIds)', { userId, commentIds })
      .execute();
  }

  async replyComment(userId: number, commentId: number, content: string): Promise<CommentType> {
    const comment = await this.commentRepository.findOne({
      where: { id: commentId, userId },
    });
    if (!comment) {
      throw new AppError('评论不存在', HTTP_STATUS.NOT_FOUND, ERROR_CODES.COMMENT_NOT_FOUND);
    }

    // TODO: 调用平台适配器发送回复
    // 这里只更新本地记录

    await this.commentRepository.update(commentId, {
      replyContent: content,
      repliedAt: new Date(),
      isRead: true,
    });

    const updated = await this.commentRepository.findOne({ where: { id: commentId } });

    wsManager.sendToUser(userId, WS_EVENTS.COMMENT_REPLIED, {
      comment: this.formatComment(updated!),
    });

    return this.formatComment(updated!);
  }

  async batchReply(
    userId: number,
    commentIds: number[],
    content: string
  ): Promise<{ success: number; failed: number }> {
    let success = 0;
    let failed = 0;

    for (const commentId of commentIds) {
      try {
        await this.replyComment(userId, commentId, content);
        success++;
      } catch {
        failed++;
      }
    }

    return { success, failed };
  }

  /**
   * 异步同步评论（后台执行，通过 WebSocket 通知结果）
   */
  syncCommentsAsync(userId: number, accountId?: number): void {
    // 通知用户同步已开始 - 直接使用字符串，并在 payload 中加入 event 字段
    wsManager.sendToUser(userId, 'comment:sync_started', {
      event: 'sync_started',
      accountId,
      message: '正在同步评论...',
    });

    // 进度回调：在处理每个作品时发送进度更新
    const onProgress = (current: number, total: number, workTitle: string) => {
      const progress = total > 0 ? Math.round((current / total) * 100) : 0;
      wsManager.sendToUser(userId, 'comment:sync_progress', {
        event: 'sync_progress',
        accountId,
        current,
        total,
        progress,
        workTitle,
        message: `正在同步: ${workTitle || `作品 ${current}/${total}`}`,
      });
    };

    // 后台执行同步任务
    this.syncComments(userId, accountId, onProgress)
      .then((result) => {
        logger.info(`Comment sync completed: synced ${result.synced} comments from ${result.accounts} accounts`);
        // 同步完成，通知用户
        wsManager.sendToUser(userId, 'comment:synced', {
          event: 'synced',
          accountId,
          syncedCount: result.synced,
          accountCount: result.accounts,
          message: `同步完成，共同步 ${result.synced} 条评论`,
        });
      })
      .catch((error) => {
        logger.error('Comment sync failed:', error);
        // 同步失败，通知用户
        wsManager.sendToUser(userId, 'comment:sync_failed', {
          event: 'sync_failed',
          accountId,
          message: error instanceof Error ? error.message : '同步失败，请稍后重试',
        });
      });
  }

  /**
   * 同步指定账号的评论
   * @param onProgress 进度回调 (current, total, workTitle)
   */
  async syncComments(
    userId: number, 
    accountId?: number,
    onProgress?: (current: number, total: number, workTitle: string) => void
  ): Promise<{ synced: number; accounts: number }> {
    const accountRepository = AppDataSource.getRepository(PlatformAccount);
    
    // 获取需要同步的账号列表
    const whereCondition: { userId: number; id?: number; platform?: string } = { userId };
    if (accountId) {
      whereCondition.id = accountId;
    }
    
    const accounts = await accountRepository.find({ where: whereCondition });
    
    if (accounts.length === 0) {
      throw new AppError('没有找到可同步的账号', HTTP_STATUS.NOT_FOUND, ERROR_CODES.ACCOUNT_NOT_FOUND);
    }

    let totalSynced = 0;
    let syncedAccounts = 0;

    for (const account of accounts) {
      try {
        // 只处理支持的平台
        if (account.platform !== 'douyin' && account.platform !== 'xiaohongshu') {
          logger.info(`Skipping unsupported platform: ${account.platform}`);
          continue;
        }

        // 解密 Cookie
        if (!account.cookieData) {
          logger.warn(`Account ${account.id} has no cookies`);
          continue;
        }

        let decryptedCookies: string;
        try {
          decryptedCookies = CookieManager.decrypt(account.cookieData);
        } catch {
          decryptedCookies = account.cookieData;
        }

        // 解析 Cookie - 支持两种格式
        let cookies: CookieData[];
        try {
          // 先尝试 JSON 格式
          cookies = JSON.parse(decryptedCookies);
        } catch {
          // 如果 JSON 解析失败，尝试解析 "name=value; name2=value2" 格式
          cookies = this.parseCookieString(decryptedCookies, account.platform);
          if (cookies.length === 0) {
            logger.error(`Invalid cookie format for account ${account.id}`);
            continue;
          }
        }
        
        // 获取评论数据 - 根据平台类型调用不同方法
        logger.info(`Syncing comments for account ${account.id} (${account.platform})...`);
        let workComments: Array<{
          videoId: string;
          videoTitle: string;
          comments: Array<{
            commentId: string;
            authorId: string;
            authorName: string;
            authorAvatar: string;
            content: string;
            likeCount: number;
            commentTime: string;
            replyCount?: number;
            parentCommentId?: string;
          }>;
        }> = [];
        
        if (account.platform === 'douyin') {
          workComments = await headlessBrowserService.fetchDouyinCommentsViaApi(cookies);
        } else if (account.platform === 'xiaohongshu') {
          workComments = await headlessBrowserService.fetchXiaohongshuCommentsViaApi(cookies);
        }
        
        // 获取该账号的所有作品，用于关联
        const workRepository = AppDataSource.getRepository(Work);
        const accountWorks = await workRepository.find({
          where: { userId, accountId: account.id },
        });
        
        logger.info(`Found ${accountWorks.length} works for account ${account.id}`);
        
        // 保存评论到数据库
        let accountSynced = 0;
        const totalWorks = workComments.length;
        
        // 创建 platformVideoId -> workId 的快速映射
        const videoIdToWorkMap = new Map<string, { id: number; title: string }>();
        for (const work of accountWorks) {
          if (work.platformVideoId) {
            videoIdToWorkMap.set(work.platformVideoId, { id: work.id, title: work.title });
            // 同时存储不带前缀的版本（如果 platformVideoId 是 "douyin_xxx" 格式）
            if (work.platformVideoId.includes('_')) {
              const parts = work.platformVideoId.split('_');
              if (parts.length >= 2) {
                videoIdToWorkMap.set(parts.slice(1).join('_'), { id: work.id, title: work.title });
              }
            }
          }
        }
        
        logger.info(`Created videoId mapping with ${videoIdToWorkMap.size} entries`);

        for (let workIndex = 0; workIndex < workComments.length; workIndex++) {
          const workComment = workComments[workIndex];
          
          // 发送进度更新
          if (onProgress) {
            onProgress(workIndex + 1, totalWorks, workComment.videoTitle || `作品 ${workIndex + 1}`);
          }
          
          let workId: number | null = null;
          const commentVideoId = workComment.videoId?.toString() || '';
          const commentVideoTitle = workComment.videoTitle?.trim() || '';
          
          logger.info(`Trying to match work for videoId: "${commentVideoId}", title: "${commentVideoTitle}"`);
          
          // 1. 【首选】通过 platformVideoId (aweme_id) 匹配 - 最可靠的方式
          if (commentVideoId) {
            // 直接匹配
            if (videoIdToWorkMap.has(commentVideoId)) {
              const matched = videoIdToWorkMap.get(commentVideoId)!;
              workId = matched.id;
              logger.info(`Matched work by videoId: ${commentVideoId} -> workId: ${workId}, title: "${matched.title}"`);
            }
            
            // 尝试带平台前缀匹配
            if (!workId) {
              const prefixedId = `douyin_${commentVideoId}`;
              if (videoIdToWorkMap.has(prefixedId)) {
                const matched = videoIdToWorkMap.get(prefixedId)!;
                workId = matched.id;
                logger.info(`Matched work by prefixed videoId: ${prefixedId} -> workId: ${workId}`);
              }
            }
            
            // 遍历匹配（处理各种格式）
            if (!workId) {
              const matchedWork = accountWorks.find(w => {
                if (!w.platformVideoId) return false;
                // 尝试各种匹配方式
                return w.platformVideoId === commentVideoId ||
                       w.platformVideoId === `douyin_${commentVideoId}` ||
                       w.platformVideoId.endsWith(`_${commentVideoId}`) ||
                       w.platformVideoId.includes(commentVideoId);
              });
              if (matchedWork) {
                workId = matchedWork.id;
                logger.info(`Matched work by videoId iteration: ${commentVideoId} -> workId: ${workId}, platformVideoId: ${matchedWork.platformVideoId}`);
              }
            }
          }
          
          // 2. 通过标题精确匹配
          if (!workId && commentVideoTitle) {
            let matchedWork = accountWorks.find(w => {
              if (!w.title) return false;
              return w.title.trim() === commentVideoTitle;
            });
            
            // 去除空白字符后匹配
            if (!matchedWork) {
              const normalizedCommentTitle = commentVideoTitle.replace(/\s+/g, '');
              matchedWork = accountWorks.find(w => {
                if (!w.title) return false;
                return w.title.trim().replace(/\s+/g, '') === normalizedCommentTitle;
              });
            }
            
            // 包含匹配
            if (!matchedWork) {
              matchedWork = accountWorks.find(w => {
                if (!w.title) return false;
                const workTitle = w.title.trim();
                const shortCommentTitle = commentVideoTitle.slice(0, 50);
                const shortWorkTitle = workTitle.slice(0, 50);
                return workTitle.includes(shortCommentTitle) || 
                       commentVideoTitle.includes(shortWorkTitle) ||
                       shortWorkTitle.includes(shortCommentTitle) ||
                       shortCommentTitle.includes(shortWorkTitle);
              });
            }
            
            // 模糊匹配
            if (!matchedWork) {
              const normalizeTitle = (title: string) => {
                return title.replace(/[^\u4e00-\u9fa5a-zA-Z0-9]/g, '').toLowerCase();
              };
              const normalizedCommentTitle = normalizeTitle(commentVideoTitle);
              matchedWork = accountWorks.find(w => {
                if (!w.title) return false;
                const normalizedWorkTitle = normalizeTitle(w.title);
                return normalizedWorkTitle.slice(0, 40) === normalizedCommentTitle.slice(0, 40) ||
                       normalizedWorkTitle.includes(normalizedCommentTitle.slice(0, 30)) ||
                       normalizedCommentTitle.includes(normalizedWorkTitle.slice(0, 30));
              });
            }
            
            if (matchedWork) {
              workId = matchedWork.id;
              logger.info(`Matched work by title: "${matchedWork.title}" -> workId: ${workId}`);
            }
          }
          
          // 3. 如果只有一个作品，直接关联
          if (!workId && accountWorks.length === 1) {
            workId = accountWorks[0].id;
            logger.info(`Only one work, using default: workId: ${workId}`);
          }
          
          logger.info(`Final work mapping: videoId="${commentVideoId}", title="${commentVideoTitle}", workId=${workId}`);
          
          for (const comment of workComment.comments) {
            try {
              // 过滤无效评论内容 - 放宽限制，只过滤纯操作按钮文本
              if (!comment.content || 
                  /^(回复|删除|举报|点赞|分享|收藏)$/.test(comment.content.trim())) {
                logger.debug(`Skipping invalid comment content: ${comment.content}`);
                continue;
              }
              
              // 检查评论是否已存在（基于内容+作者+账号的去重）
              const existing = await this.commentRepository
                .createQueryBuilder('comment')
                .where('comment.accountId = :accountId', { accountId: account.id })
                .andWhere('comment.authorName = :authorName', { authorName: comment.authorName })
                .andWhere('comment.content = :content', { content: comment.content })
                .getOne();

              if (!existing) {
                const newComment = this.commentRepository.create({
                  userId,
                  accountId: account.id,
                  workId, // 关联作品 ID
                  platform: account.platform as PlatformType,
                  videoId: workComment.videoId,
                  commentId: comment.commentId,
                  authorId: comment.authorId,
                  authorName: comment.authorName,
                  authorAvatar: comment.authorAvatar,
                  content: comment.content,
                  likeCount: comment.likeCount,
                  commentTime: comment.commentTime ? new Date(comment.commentTime) : new Date(),
                  isRead: false,
                  isTop: false,
                });

                await this.commentRepository.save(newComment);
                accountSynced++;
                logger.info(`Saved comment: "${comment.content.slice(0, 30)}..." -> workId: ${workId}`);
              } else {
                // 如果评论已存在但没有 workId，更新它
                if (!existing.workId && workId) {
                  await this.commentRepository.update(existing.id, { workId });
                  logger.info(`Updated existing comment workId: ${existing.id} -> ${workId}`);
                }
              }
            } catch (saveError) {
              logger.warn(`Failed to save comment ${comment.commentId}:`, saveError);
            }
          }
        }

        if (accountSynced > 0) {
          totalSynced += accountSynced;
          syncedAccounts++;
          logger.info(`Synced ${accountSynced} comments for account ${account.id}`);
          // 注意：不在这里发送 COMMENT_SYNCED，而是由 syncCommentsAsync 统一发送
        }
      } catch (accountError) {
        logger.error(`Failed to sync comments for account ${account.id}:`, accountError);
      }
    }

    // 尝试修复没有 workId 的现有评论
    await this.fixOrphanedComments(userId);

    return { synced: totalSynced, accounts: syncedAccounts };
  }

  /**
   * 修复没有 workId 的评论
   */
  private async fixOrphanedComments(userId: number): Promise<void> {
    try {
      const workRepository = AppDataSource.getRepository(Work);
      
      // 获取所有没有 workId 的评论
      const orphanedComments = await this.commentRepository.find({
        where: { userId, workId: undefined as unknown as number },
      });
      
      if (orphanedComments.length === 0) return;
      
      logger.info(`Found ${orphanedComments.length} comments without workId, trying to fix...`);
      
      // 获取用户的所有作品
      const works = await workRepository.find({ where: { userId } });
      
      // 创建多种格式的 videoId -> workId 映射
      const videoIdToWork = new Map<string, { id: number; title: string }>();
      for (const work of works) {
        if (work.platformVideoId) {
          // 存储原始 platformVideoId
          videoIdToWork.set(work.platformVideoId, { id: work.id, title: work.title });
          
          // 如果是 "douyin_xxx" 格式，也存储纯 ID
          if (work.platformVideoId.startsWith('douyin_')) {
            const pureId = work.platformVideoId.replace('douyin_', '');
            videoIdToWork.set(pureId, { id: work.id, title: work.title });
          }
          
          // 如果是纯数字 ID，也存储带前缀的版本
          if (/^\d+$/.test(work.platformVideoId)) {
            videoIdToWork.set(`douyin_${work.platformVideoId}`, { id: work.id, title: work.title });
          }
        }
      }
      
      let fixedCount = 0;
      
      for (const comment of orphanedComments) {
        let matchedWorkId: number | null = null;
        
        // 1. 尝试通过 videoId 精确匹配
        if (comment.videoId) {
          if (videoIdToWork.has(comment.videoId)) {
            matchedWorkId = videoIdToWork.get(comment.videoId)!.id;
          }
          // 尝试带前缀匹配
          if (!matchedWorkId) {
            const prefixedId = `douyin_${comment.videoId}`;
            if (videoIdToWork.has(prefixedId)) {
              matchedWorkId = videoIdToWork.get(prefixedId)!.id;
            }
          }
          // 尝试去掉前缀匹配
          if (!matchedWorkId && comment.videoId.includes('_')) {
            const pureId = comment.videoId.split('_').pop()!;
            if (videoIdToWork.has(pureId)) {
              matchedWorkId = videoIdToWork.get(pureId)!.id;
            }
          }
          // 遍历查找包含关系
          if (!matchedWorkId) {
            const matchedWork = works.find(w => 
              w.platformVideoId?.includes(comment.videoId!) || 
              comment.videoId!.includes(w.platformVideoId || '')
            );
            if (matchedWork) {
              matchedWorkId = matchedWork.id;
            }
          }
        }
        
        // 2. 尝试通过账号匹配（如果该账号只有一个作品）
        if (!matchedWorkId) {
          const accountWorks = works.filter(w => w.accountId === comment.accountId);
          if (accountWorks.length === 1) {
            matchedWorkId = accountWorks[0].id;
          }
        }
        
        if (matchedWorkId) {
          await this.commentRepository.update(comment.id, { workId: matchedWorkId });
          fixedCount++;
          logger.info(`Fixed comment ${comment.id} (videoId: ${comment.videoId}) -> workId: ${matchedWorkId}`);
        }
      }
      
      logger.info(`Fixed ${fixedCount}/${orphanedComments.length} orphaned comments`);
    } catch (error) {
      logger.warn('Failed to fix orphaned comments:', error);
    }
  }

  /**
   * 将 cookie 字符串解析为 cookie 列表
   */
  private parseCookieString(cookieString: string, platform: string): CookieData[] {
    // 获取平台对应的域名
    const domainMap: Record<string, string> = {
      douyin: '.douyin.com',
      kuaishou: '.kuaishou.com',
      xiaohongshu: '.xiaohongshu.com',
      weixin_video: '.qq.com',
      bilibili: '.bilibili.com',
      toutiao: '.toutiao.com',
      baijiahao: '.baidu.com',
      qie: '.qq.com',
      dayuhao: '.alibaba.com',
    };
    
    const domain = domainMap[platform] || `.${platform}.com`;
    
    // 解析 "name=value; name2=value2" 格式的 cookie 字符串
    const cookies: CookieData[] = [];
    
    const pairs = cookieString.split(';');
    for (const pair of pairs) {
      const trimmed = pair.trim();
      if (!trimmed) continue;
      
      const eqIndex = trimmed.indexOf('=');
      if (eqIndex === -1) continue;
      
      const name = trimmed.substring(0, eqIndex).trim();
      const value = trimmed.substring(eqIndex + 1).trim();
      
      if (name && value) {
        cookies.push({
          name,
          value,
          domain,
          path: '/',
        });
      }
    }
    
    return cookies;
  }

  private formatComment(comment: Comment): CommentType {
    return {
      id: comment.id,
      userId: comment.userId,
      accountId: comment.accountId,
      workId: comment.workId || undefined,
      platform: comment.platform!,
      videoId: comment.videoId || '',
      platformVideoUrl: comment.platformVideoUrl,
      commentId: comment.commentId,
      parentCommentId: comment.parentCommentId,
      authorId: comment.authorId || '',
      authorName: comment.authorName || '',
      authorAvatar: comment.authorAvatar,
      content: comment.content || '',
      likeCount: comment.likeCount,
      replyContent: comment.replyContent,
      repliedAt: comment.repliedAt?.toISOString() || null,
      isRead: comment.isRead,
      isTop: comment.isTop,
      commentTime: comment.commentTime?.toISOString() || '',
      createdAt: comment.createdAt.toISOString(),
    };
  }
}
