import { AppDataSource, PlatformAccount, AccountGroup } from '../models/index.js';
import { AppError } from '../middleware/error.js';
import { ERROR_CODES, HTTP_STATUS } from '@media-manager/shared';
import type {
  PlatformType,
  PlatformAccount as PlatformAccountType,
  AccountGroup as AccountGroupType,
  AddPlatformAccountRequest,
  UpdatePlatformAccountRequest,
  CreateAccountGroupRequest,
  QRCodeInfo,
  LoginStatusResult,
} from '@media-manager/shared';
import { wsManager } from '../websocket/index.js';
import { WS_EVENTS } from '@media-manager/shared';
import { CookieManager } from '../automation/cookie.js';
import { logger } from '../utils/logger.js';
import { headlessBrowserService } from './HeadlessBrowserService.js';
import { aiService } from '../ai/index.js';
import { UserDayStatisticsService } from './UserDayStatisticsService.js';
import { XiaohongshuAccountOverviewImportService } from './XiaohongshuAccountOverviewImportService.js';
import { DouyinAccountOverviewImportService } from './DouyinAccountOverviewImportService.js';
import { BaijiahaoContentOverviewImportService } from './BaijiahaoContentOverviewImportService.js';
import { WeixinVideoDataCenterImportService } from './WeixinVideoDataCenterImportService.js';

interface GetAccountsParams {
  platform?: string;
  groupId?: number;
  status?: string;
}

export class AccountService {
  private accountRepository = AppDataSource.getRepository(PlatformAccount);
  private groupRepository = AppDataSource.getRepository(AccountGroup);

  // ============ 账号分组 ============

  async getGroups(userId: number): Promise<AccountGroupType[]> {
    const groups = await this.groupRepository.find({
      where: { userId },
      order: { createdAt: 'ASC' },
    });
    return groups.map(this.formatGroup);
  }

  async createGroup(userId: number, data: CreateAccountGroupRequest): Promise<AccountGroupType> {
    const group = this.groupRepository.create({
      userId,
      name: data.name,
      description: data.description || null,
    });
    await this.groupRepository.save(group);
    return this.formatGroup(group);
  }

  async updateGroup(
    userId: number,
    groupId: number,
    data: Partial<CreateAccountGroupRequest>
  ): Promise<AccountGroupType> {
    const group = await this.groupRepository.findOne({
      where: { id: groupId, userId },
    });
    if (!group) {
      throw new AppError('分组不存在', HTTP_STATUS.NOT_FOUND, ERROR_CODES.NOT_FOUND);
    }

    await this.groupRepository.update(groupId, {
      name: data.name ?? group.name,
      description: data.description ?? group.description,
    });

    const updated = await this.groupRepository.findOne({ where: { id: groupId } });
    return this.formatGroup(updated!);
  }

  async deleteGroup(userId: number, groupId: number): Promise<void> {
    const group = await this.groupRepository.findOne({
      where: { id: groupId, userId },
    });
    if (!group) {
      throw new AppError('分组不存在', HTTP_STATUS.NOT_FOUND, ERROR_CODES.NOT_FOUND);
    }
    await this.groupRepository.delete(groupId);
  }

  // ============ 平台账号 ============

  async getAccounts(userId: number, params: GetAccountsParams): Promise<PlatformAccountType[]> {
    const queryBuilder = this.accountRepository
      .createQueryBuilder('account')
      .where('account.userId = :userId', { userId });

    if (params.platform) {
      queryBuilder.andWhere('account.platform = :platform', { platform: params.platform });
    }
    if (params.groupId) {
      queryBuilder.andWhere('account.groupId = :groupId', { groupId: params.groupId });
    }
    if (params.status) {
      queryBuilder.andWhere('account.status = :status', { status: params.status });
    }

    const accounts = await queryBuilder
      .orderBy('account.createdAt', 'DESC')
      .getMany();

    return accounts.map(this.formatAccount);
  }

  async getAccountById(userId: number, accountId: number): Promise<PlatformAccountType> {
    const account = await this.accountRepository.findOne({
      where: { id: accountId, userId },
    });
    if (!account) {
      throw new AppError('账号不存在', HTTP_STATUS.NOT_FOUND, ERROR_CODES.ACCOUNT_NOT_FOUND);
    }
    return this.formatAccount(account);
  }

  /**
   * 获取账号的 Cookie 数据（用于客户端打开后台）
   */
  async getAccountCookie(userId: number, accountId: number): Promise<string> {
    const account = await this.accountRepository.findOne({
      where: { id: accountId, userId },
    });
    if (!account) {
      throw new AppError('账号不存在', HTTP_STATUS.NOT_FOUND, ERROR_CODES.ACCOUNT_NOT_FOUND);
    }

    if (!account.cookieData) {
      throw new AppError('账号没有 Cookie 数据', HTTP_STATUS.BAD_REQUEST, ERROR_CODES.VALIDATION_ERROR);
    }

    // 尝试解密 Cookie
    let decryptedCookies: string;
    try {
      decryptedCookies = CookieManager.decrypt(account.cookieData);
      logger.info(`[AccountService] Cookie 解密成功，账号: ${account.accountName}`);
    } catch (error) {
      // 如果解密失败，返回原始数据
      logger.warn(`[AccountService] Cookie 解密失败，使用原始数据，账号: ${account.accountName}`);
      decryptedCookies = account.cookieData;
    }

    // 验证 Cookie 格式
    try {
      const parsed = JSON.parse(decryptedCookies);
      if (Array.isArray(parsed) && parsed.length > 0) {
        logger.info(`[AccountService] Cookie 格式验证通过，共 ${parsed.length} 个 Cookie`);
        const cookieNames = parsed.map((c: any) => c?.name).filter(Boolean);
        // 记录关键 Cookie（用于调试）
        const keyNames = cookieNames.slice(0, 5).join(', ');
        logger.info(`[AccountService] 关键 Cookie: ${keyNames}`);

        if (account.platform === 'baijiahao') {
          const required = ['BDUSS', 'STOKEN', 'bjhStoken', 'devStoken', 'BAIDUID'];
          const present = required.filter(name => cookieNames.includes(name));
          logger.info(
            `[AccountService] 百家号关键 Cookie 命中: ${present.length}/${required.length} -> ${present.join(', ') || '无'}`
          );
        }
      }
    } catch {
      logger.warn(`[AccountService] Cookie 不是 JSON 格式，可能是字符串格式`);
    }

    return decryptedCookies;
  }

  async addAccount(userId: number, data: AddPlatformAccountRequest & {
    accountInfo?: {
      accountId?: string;
      accountName?: string;
      avatarUrl?: string;
      fansCount?: number;
      worksCount?: number;
    };
  }): Promise<PlatformAccountType> {
    const platform = data.platform as PlatformType;

    // 解密 Cookie（如果是加密的）
    let cookieData = data.cookieData;
    let decryptedCookies: string;

    try {
      // 尝试解密（如果是通过浏览器登录获取的加密Cookie）
      decryptedCookies = CookieManager.decrypt(cookieData);
    } catch {
      // 如果解密失败，可能是直接粘贴的Cookie字符串
      decryptedCookies = cookieData;
    }

    // 检查客户端传入的 accountId 是否有效（不是纯时间戳）
    const clientAccountId = data.accountInfo?.accountId;
    const isValidClientAccountId = clientAccountId && !this.isTimestampBasedId(clientAccountId);

    // 从 Cookie 中提取账号 ID（部分平台的 Cookie 包含真实用户 ID）
    const accountIdFromCookie = this.extractAccountIdFromCookie(platform, decryptedCookies);

    // 某些平台应优先使用 API 返回的真实 ID，而不是 Cookie 中的值
    // - 抖音：使用抖音号（unique_id，如 Ethanfly9392），而不是 Cookie 中的 passport_uid
    // - 小红书：使用小红书号（red_num），而不是 Cookie 中的 userid
    // - 百家号：使用 new_uc_id，而不是 Cookie 中的 BDUSS
    // - 视频号/头条：使用 API 返回的真实账号 ID
    const platformsPreferApiId: PlatformType[] = ['douyin', 'xiaohongshu', 'baijiahao', 'weixin_video', 'toutiao'];
    const preferApiId = platformsPreferApiId.includes(platform);

    // 确定最终的 accountId
    let finalAccountId: string;

    if (preferApiId && isValidClientAccountId) {
      // 对于优先使用 API ID 的平台，先用客户端传入的有效 ID
      finalAccountId = this.normalizeAccountId(platform, clientAccountId);
      logger.info(`[addAccount] Using API-based accountId for ${platform}: ${finalAccountId}`);
    } else if (accountIdFromCookie) {
      // 其他平台优先使用 Cookie 中提取的 ID
      finalAccountId = accountIdFromCookie;
      logger.info(`[addAccount] Using accountId from cookie: ${finalAccountId}`);
    } else if (isValidClientAccountId) {
      // 再次尝试客户端 ID
      finalAccountId = this.normalizeAccountId(platform, clientAccountId);
      logger.info(`[addAccount] Using valid client accountId: ${finalAccountId}`);
    } else {
      finalAccountId = `${platform}_${Date.now()}`;
      logger.warn(`[addAccount] Using timestamp-based accountId as fallback: ${finalAccountId}`);
    }

    // 使用传入的账号信息（来自浏览器登录会话），或使用默认值
    const accountInfo = {
      accountId: finalAccountId,
      accountName: data.accountInfo?.accountName || `${platform}账号`,
      avatarUrl: data.accountInfo?.avatarUrl || null,
      fansCount: data.accountInfo?.fansCount || 0,
      worksCount: data.accountInfo?.worksCount || 0,
    };

    logger.info(`Adding account for ${platform}: ${accountInfo.accountId}, name: ${accountInfo.accountName}`);

    // 检查是否已存在相同账号
    const existing = await this.accountRepository.findOne({
      where: { userId, platform, accountId: accountInfo.accountId },
    });

    if (existing) {
      // 更新已存在的账号
      const wasExpired = existing.status === 'expired';

      await this.accountRepository.update(existing.id, {
        cookieData: cookieData, // 存储原始数据（可能是加密的）
        accountName: accountInfo.accountName,
        avatarUrl: accountInfo.avatarUrl,
        fansCount: accountInfo.fansCount,
        worksCount: accountInfo.worksCount,
        status: 'active',
        groupId: data.groupId || existing.groupId,
        proxyConfig: data.proxyConfig || existing.proxyConfig,
      });

      const updated = await this.accountRepository.findOne({ where: { id: existing.id } });
      wsManager.sendToUser(userId, WS_EVENTS.ACCOUNT_UPDATED, { account: this.formatAccount(updated!) });

      // Bug #6070: 通知前端账号数据已变更，触发其他模块（如首页数据看板）刷新
      wsManager.sendToUser(userId, WS_EVENTS.ACCOUNT_DATA_CHANGED, { accountId: existing.id });

      // 异步刷新账号信息（获取准确的粉丝数、作品数等）
      this.refreshAccountAsync(userId, existing.id, platform).catch(err => {
        logger.warn(`[addAccount] Background refresh failed for existing account ${existing.id}:`, err);
      });

      // 账号从 expired 恢复为 active：异步补齐最近 30 天用户每日数据
      if (wasExpired && updated && updated.status === 'active') {
        this.backfillDailyStatisticsForReactivatedAccountAsync(updated).catch(err => {
          logger.warn(
            `[addAccount] Daily statistics backfill failed for reactivated account ${updated.id}:`,
            err
          );
        });
      }

      return this.formatAccount(updated!);
    }

    // 创建新账号
    const account = this.accountRepository.create({
      userId,
      platform,
      cookieData: cookieData,
      groupId: data.groupId || null,
      proxyConfig: data.proxyConfig || null,
      status: 'active',
      accountId: accountInfo.accountId,
      accountName: accountInfo.accountName,
      avatarUrl: accountInfo.avatarUrl,
      fansCount: accountInfo.fansCount,
      worksCount: accountInfo.worksCount,
    });

    await this.accountRepository.save(account);

    // 通知其他客户端
    wsManager.sendToUser(userId, WS_EVENTS.ACCOUNT_ADDED, { account: this.formatAccount(account) });

    // Bug #6070: 通知前端账号数据已变更，触发其他模块（如首页数据看板）刷新
    wsManager.sendToUser(userId, WS_EVENTS.ACCOUNT_DATA_CHANGED, { accountId: account.id });

    // 异步刷新账号信息（获取准确的粉丝数、作品数等）
    // 不阻塞返回，后台执行
    this.refreshAccountAsync(userId, account.id, platform).catch(err => {
      logger.warn(`[addAccount] Background refresh failed for account ${account.id}:`, err);
    });

    // 新增账号后，按平台触发一次“近30天数据同步”，用于初始化 user_day_statistics
    this.initStatisticsForNewAccountAsync(account).catch(err => {
      logger.warn(
        `[addAccount] Initial statistics sync failed for account ${account.id} (${platform}):`,
        err
      );
    });

    return this.formatAccount(account);
  }

  /**
   * 异步刷新账号信息（用于添加账号后获取准确数据）
   */
  private async refreshAccountAsync(userId: number, accountId: number, platform: PlatformType): Promise<void> {
    // 延迟 2 秒执行，等待前端处理完成
    await new Promise(resolve => setTimeout(resolve, 2000));

    logger.info(`[addAccount] Starting background refresh for account ${accountId} (${platform})`);

    try {
      await this.refreshAccount(userId, accountId);
      logger.info(`[addAccount] Background refresh completed for account ${accountId}`);
    } catch (error) {
      logger.warn(`[addAccount] Background refresh failed for account ${accountId}:`, error);
    }
  }

  /**
   * 新增账号后，按平台触发一次“近30天数据同步”，用于初始化 user_day_statistics
   * 仿照定时任务里跑的导入服务，但只针对当前账号
   */
  private async initStatisticsForNewAccountAsync(account: PlatformAccount): Promise<void> {
    const platform = account.platform as PlatformType;

    // 延迟几秒，避免和前端后续操作/账号刷新抢占浏览器资源
    await new Promise((resolve) => setTimeout(resolve, 3000));

    logger.info(
      `[addAccount] Starting initial statistics import for account ${account.id} (${platform})`
    );

    try {
      if (platform === 'xiaohongshu') {
        await XiaohongshuAccountOverviewImportService.runDailyImport();
      } else if (platform === 'douyin') {
        await DouyinAccountOverviewImportService.runDailyImport();
      } else if (platform === 'baijiahao') {
        await BaijiahaoContentOverviewImportService.runDailyImport();
      } else if (platform === 'weixin_video') {
        await WeixinVideoDataCenterImportService.runDailyImport();
      } else {
        logger.info(
          `[addAccount] Initial statistics import skipped for unsupported platform ${platform}`
        );
        return;
      }

      logger.info(
        `[addAccount] Initial statistics import completed for account ${account.id} (${platform})`
      );
    } catch (error) {
      logger.warn(
        `[addAccount] Initial statistics import encountered error for account ${account.id} (${platform}):`,
        error
      );
      // 出错时不抛出，让前端添加账号流程不受影响
    }
  }

  /**
   * 账号从失效（expired）恢复为 active 时，为该账号补齐最近 30 天的用户每日数据（user_day_statistics）
   * 注意：仅在状态从 expired → active 的切换时触发，且按平台调用对应的单账号导入入口
   */
  private async backfillDailyStatisticsForReactivatedAccountAsync(
    account: PlatformAccount
  ): Promise<void> {
    const platform = account.platform as PlatformType;

    // 延迟几秒，避免与前端后续操作/其他浏览器任务抢占资源
    await new Promise((resolve) => setTimeout(resolve, 3000));

    try {
      if (platform === 'xiaohongshu') {
        await XiaohongshuAccountOverviewImportService.runDailyImportForAccount(account.id);
      } else if (platform === 'douyin') {
        await DouyinAccountOverviewImportService.runDailyImportForAccount(account.id);
      } else if (platform === 'baijiahao') {
        await BaijiahaoContentOverviewImportService.runDailyImportForAccount(account.id);
      } else if (platform === 'weixin_video') {
        await WeixinVideoDataCenterImportService.runDailyImportForAccount(account.id);
      } else {
        logger.info(
          `[AccountService] Skip daily statistics backfill for unsupported platform ${platform} (accountId=${account.id})`
        );
        return;
      }

      logger.info(
        `[AccountService] Completed daily statistics backfill for reactivated account ${account.id} (${platform})`
      );
    } catch (error) {
      logger.warn(
        `[AccountService] Daily statistics backfill failed for reactivated account ${account.id} (${platform}):`,
        error
      );
      // 出错不影响账号激活本身
    }
  }

  async updateAccount(
    userId: number,
    accountId: number,
    data: UpdatePlatformAccountRequest
  ): Promise<PlatformAccountType> {
    const account = await this.accountRepository.findOne({
      where: { id: accountId, userId },
    });
    if (!account) {
      throw new AppError('账号不存在', HTTP_STATUS.NOT_FOUND, ERROR_CODES.ACCOUNT_NOT_FOUND);
    }

    await this.accountRepository.update(accountId, {
      groupId: data.groupId !== undefined ? data.groupId : account.groupId,
      proxyConfig: data.proxyConfig !== undefined ? data.proxyConfig : account.proxyConfig,
      status: data.status ?? account.status,
    });

    const updated = await this.accountRepository.findOne({ where: { id: accountId } });

    // 通知其他客户端
    wsManager.sendToUser(userId, WS_EVENTS.ACCOUNT_UPDATED, { account: this.formatAccount(updated!) });

    return this.formatAccount(updated!);
  }

  async deleteAccount(userId: number, accountId: number): Promise<void> {
    const account = await this.accountRepository.findOne({
      where: { id: accountId, userId },
    });
    if (!account) {
      throw new AppError('账号不存在', HTTP_STATUS.NOT_FOUND, ERROR_CODES.ACCOUNT_NOT_FOUND);
    }
    await this.accountRepository.delete(accountId);

    // 通知其他客户端
    wsManager.sendToUser(userId, WS_EVENTS.ACCOUNT_DELETED, { accountId });
  }

  async refreshAccount(userId: number, accountId: number): Promise<PlatformAccountType & { needReLogin?: boolean }> {
    const account = await this.accountRepository.findOne({
      where: { id: accountId, userId },
    });
    if (!account) {
      throw new AppError('账号不存在', HTTP_STATUS.NOT_FOUND, ERROR_CODES.ACCOUNT_NOT_FOUND);
    }

    const platform = account.platform as PlatformType;
    const wasExpired = account.status === 'expired';
    const updateData: Partial<PlatformAccount> = {
      updatedAt: new Date(),
    };

    let needReLogin = false;
    let aiRefreshSuccess = false;

    // Bug #6084: cookie 为空的账号直接标记为 expired
    if (!account.cookieData) {
      updateData.status = 'expired';
      needReLogin = true;
      logger.warn(`[refreshAccount] Account ${accountId} has empty cookieData, marking as expired`);
      await this.accountRepository.update(accountId, updateData);
      const updated = await this.accountRepository.findOne({ where: { id: accountId } });
      wsManager.sendToUser(userId, WS_EVENTS.ACCOUNT_UPDATED, { account: this.formatAccount(updated!) });
      return { ...this.formatAccount(updated!), needReLogin };
    }

    // 尝试通过无头浏览器刷新账号信息
    if (account.cookieData) {
      try {
        // 解密 Cookie
        let decryptedCookies: string;
        try {
          decryptedCookies = CookieManager.decrypt(account.cookieData);
        } catch {
          decryptedCookies = account.cookieData;
        }

        // 解析 Cookie - 支持两种格式
        let cookieList: { name: string; value: string; domain: string; path: string }[];
        let cookieParseError = false;
        try {
          // 先尝试 JSON 格式
          cookieList = JSON.parse(decryptedCookies);
        } catch {
          // 如果 JSON 解析失败，尝试解析 "name=value; name2=value2" 格式
          cookieList = this.parseCookieString(decryptedCookies, platform);
          if (cookieList.length === 0) {
            logger.error(`Invalid cookie format for account ${accountId}`);
            cookieParseError = true;
          }
        }

        if (cookieList.length > 0 && !cookieParseError) {
          // 抖音、小红书、百家号直接使用 API 获取准确数据，不使用 AI（因为 AI 可能识别错误）
          // 但是如果 API 调用失败，作为备用方案仍会尝试 AI
          const platformsSkipAI: PlatformType[] = ['douyin', 'xiaohongshu', 'baijiahao'];
          const shouldUseAI = aiService.isAvailable() && !platformsSkipAI.includes(platform);

          logger.info(`[refreshAccount] Platform: ${platform}, shouldUseAI: ${shouldUseAI}, aiAvailable: ${aiService.isAvailable()}`);

          // ========== AI 辅助刷新（部分平台使用） ==========
          if (shouldUseAI) {
            try {
              logger.info(`[AI Refresh] Starting AI-assisted refresh for account ${accountId} (${platform})`);

              // 使用无头浏览器截图，然后 AI 分析
              const aiResult = await this.refreshAccountWithAI(platform, cookieList, accountId);

              if (aiResult.needReLogin) {
                // AI 检测到需要重新登录
                updateData.status = 'expired';
                needReLogin = true;
                aiRefreshSuccess = true;
                logger.warn(`[AI Refresh] Account ${accountId} needs re-login (detected by AI)`);
              } else if (aiResult.accountInfo) {
                // AI 成功获取到账号信息
                updateData.status = 'active';
                updateData.accountName = aiResult.accountInfo.accountName;
                if (aiResult.accountInfo.avatarUrl) {
                  updateData.avatarUrl = aiResult.accountInfo.avatarUrl;
                }
                if (aiResult.accountInfo.fansCount !== undefined) {
                  updateData.fansCount = aiResult.accountInfo.fansCount;
                }
                if (aiResult.accountInfo.worksCount !== undefined) {
                  updateData.worksCount = aiResult.accountInfo.worksCount;
                }
                aiRefreshSuccess = true;
                logger.info(`[AI Refresh] Successfully refreshed account ${accountId}: ${aiResult.accountInfo.accountName}`);
              }
            } catch (aiError) {
              logger.warn(`[AI Refresh] AI-assisted refresh failed for account ${accountId}:`, aiError);
              // AI 刷新失败，继续使用原有逻辑
            }
          }

          // ========== 原有逻辑（AI 失败时的备用方案） ==========
          if (!aiRefreshSuccess) {
            const cookieStatus = await headlessBrowserService.checkCookieStatus(platform, cookieList);

            if (cookieStatus.needReLogin) {
              updateData.status = 'expired';
              needReLogin = true;
              logger.warn(
                `Account ${accountId} (${account.accountName}) needs re-login: reason=${cookieStatus.reason}, source=${cookieStatus.source}, msg=${cookieStatus.message || ''}`
              );
            } else if (cookieStatus.uncertain) {
              logger.warn(
                `Account ${accountId} (${account.accountName}) cookie status uncertain: source=${cookieStatus.source}, msg=${cookieStatus.message || ''}`
              );
            } else if (cookieStatus.isValid) {
              updateData.status = 'active';

              try {
                const profile = await headlessBrowserService.fetchAccountInfo(platform, cookieList);

                // 检查是否获取到有效信息（排除默认名称）
                const defaultNames = [
                  `${platform}账号`, '未知账号', '抖音账号', '小红书账号',
                  '快手账号', '视频号账号', 'B站账号', '头条账号', '百家号账号'
                ];
                const isValidProfile = profile.accountName && !defaultNames.includes(profile.accountName);

                if (isValidProfile) {
                  updateData.accountName = profile.accountName;
                  updateData.avatarUrl = profile.avatarUrl;

                  // 仅在粉丝数有效时更新（避免因获取失败导致的归零）
                  if (profile.fansCount !== undefined) {
                    // 如果新粉丝数为 0，但原粉丝数 > 0，可能是获取失败，记录警告并跳过更新
                    if (profile.fansCount === 0 && (account.fansCount || 0) > 0) {
                      logger.warn(`[refreshAccount] Fans count dropped to 0 for ${accountId} (was ${account.fansCount}). Ignoring potential fetch error.`);
                    } else {
                      updateData.fansCount = profile.fansCount;
                    }
                  }

                  if (profile.worksCount === 0 && (account.worksCount || 0) > 0) {
                    logger.warn(`[refreshAccount] Works count dropped to 0 for ${accountId} (was ${account.worksCount}). Ignoring potential fetch error.`);
                  } else {
                    updateData.worksCount = profile.worksCount;
                  }

                  // 如果获取到了有效的 accountId（如抖音号），也更新它
                  // 这样可以修正之前使用错误 ID（如 Cookie 值）保存的账号
                  if (profile.accountId && !this.isTimestampBasedId(profile.accountId)) {
                    const newAccountId = this.normalizeAccountId(platform, profile.accountId);
                    // 只有当新 ID 与旧 ID 不同时才更新
                    if (newAccountId !== account.accountId) {
                      updateData.accountId = newAccountId;
                      logger.info(`[refreshAccount] Updating accountId from ${account.accountId} to ${newAccountId}`);
                    }
                  }

                  logger.info(`Refreshed account info for ${platform}: ${profile.accountName}, fans: ${profile.fansCount}, works: ${profile.worksCount}`);
                } else {
                  // 获取的信息无效，但 Cookie 有效，保持 active 状态
                  logger.warn(`Could not fetch valid account info for ${accountId}, but cookie is valid`);

                  // Bug #6075: 即使 profile 名称无效，仍然强制更新 avatarUrl（用户可能只改了头像没改昵称）
                  if (profile.avatarUrl) {
                    updateData.avatarUrl = profile.avatarUrl;
                    logger.info(`[refreshAccount] Force updating avatarUrl for ${accountId} (profile name invalid but avatar changed)`);
                  }
                }

                // 无论 profile 是否有效，都尝试更新粉丝数和作品数（来自 Python API 的数据是可靠的）
                // 仅在粉丝数有效时更新（避免因获取失败导致的归零）
                if (profile.fansCount !== undefined) {
                  if (profile.fansCount === 0 && (account.fansCount || 0) > 0) {
                    logger.warn(`[refreshAccount] Fans count dropped to 0 for ${accountId} (was ${account.fansCount}). Ignoring potential fetch error.`);
                  } else {
                    updateData.fansCount = profile.fansCount;
                  }
                }

                // 作品数更新：Python API 返回的数据是可靠的
                if (profile.worksCount !== undefined && profile.worksCount > 0) {
                  updateData.worksCount = profile.worksCount;
                  logger.info(`[refreshAccount] Updated works count for ${accountId}: ${profile.worksCount}`);
                } else if (profile.worksCount === 0 && (account.worksCount || 0) > 0) {
                  logger.warn(`[refreshAccount] Works count dropped to 0 for ${accountId} (was ${account.worksCount}). Ignoring potential fetch error.`);
                }
              } catch (infoError) {
                // 获取账号信息失败，但 Cookie 检查已通过，保持 active 状态
                logger.warn(`Failed to fetch account info for ${accountId}, but cookie is valid:`, infoError);

                // 对于百家号，如果是获取信息失败，可能是分散认证问题，不需要立即标记为失败
                if (platform === 'baijiahao') {
                  logger.info(`[baijiahao] Account info fetch failed for ${accountId}, but this might be due to distributed auth. Keeping status active.`);
                }
              }
            } else {
              logger.warn(
                `Account ${accountId} (${account.accountName}) cookie invalid without explicit re-login: source=${cookieStatus.source}, reason=${cookieStatus.reason}`
              );
            }
          }
        }
        // Cookie 解析失败时，不改变状态
      } catch (error) {
        logger.error(`Failed to refresh account ${accountId}:`, error);
        // 不抛出错误，不改变状态，只更新时间戳
      }
    }
    // 没有 Cookie 数据时，不改变状态

    await this.accountRepository.update(accountId, updateData);

    const updated = await this.accountRepository.findOne({ where: { id: accountId } });

    // 账号从 expired 恢复为 active：异步补齐最近 30 天用户每日数据
    const newStatus = updated?.status ?? account.status;
    if (wasExpired && newStatus === 'active' && updated) {
      this.backfillDailyStatisticsForReactivatedAccountAsync(updated).catch((error) => {
        logger.warn(
          `[AccountService] Daily statistics backfill failed after refresh for reactivated account ${updated.id}:`,
          error
        );
      });
    }

    // 刷新账号时不再写入 user_day_statistics，仅保留：每天定时任务 + 添加账号时的 initStatisticsForNewAccountAsync
    // if (updated) {
    //   try {
    //     const userDayStatisticsService = new UserDayStatisticsService();
    //     await userDayStatisticsService.saveStatistics({
    //       accountId,
    //       fansCount: updated.fansCount || 0,
    //       worksCount: updated.worksCount || 0,
    //     });
    //     logger.debug(`[AccountService] Saved account day statistics for account ${accountId} (fans: ${updated.fansCount || 0}, works: ${updated.worksCount || 0})`);
    //   } catch (error) {
    //     logger.error(`[AccountService] Failed to save account day statistics for account ${accountId}:`, error);
    //   }
    // }

    // 通知其他客户端
    wsManager.sendToUser(userId, WS_EVENTS.ACCOUNT_UPDATED, { account: this.formatAccount(updated!) });

    // Bug #6075: 检测 avatarUrl 或 accountName 是否发生变化，通知前端刷新数据
    if (updated) {
      const avatarChanged = updateData.avatarUrl !== undefined && updateData.avatarUrl !== account.avatarUrl;
      const nameChanged = updateData.accountName !== undefined && updateData.accountName !== account.accountName;
      if (avatarChanged || nameChanged) {
        logger.info(`[refreshAccount] Account ${accountId} data changed: avatarChanged=${avatarChanged}, nameChanged=${nameChanged}`);
        wsManager.sendToUser(userId, WS_EVENTS.ACCOUNT_DATA_CHANGED, {
          accountId,
          accountName: updated.accountName,
          avatarUrl: updated.avatarUrl,
        });
      }
    }

    return { ...this.formatAccount(updated!), needReLogin };
  }

  /**
   * 使用 AI 辅助刷新账号信息
   */
  private async refreshAccountWithAI(
    platform: PlatformType,
    cookieList: { name: string; value: string; domain: string; path: string }[],
    accountId: number
  ): Promise<{
    needReLogin: boolean;
    accountInfo?: {
      accountName: string;
      avatarUrl?: string;
      fansCount?: number;
      worksCount?: number;
    };
  }> {
    // 使用无头浏览器访问平台后台并截图
    const screenshot = await headlessBrowserService.capturePageScreenshot(platform, cookieList);

    if (!screenshot) {
      throw new Error('Failed to capture screenshot');
    }

    // 第一步：使用 AI 分析登录状态
    const loginStatus = await aiService.analyzeLoginStatus(screenshot, platform);

    logger.info(`[AI Refresh] Login status for account ${accountId}:`, {
      isLoggedIn: loginStatus.isLoggedIn,
      hasVerification: loginStatus.hasVerification,
    });

    // 如果 AI 检测到未登录或有验证码，说明需要重新登录
    if (!loginStatus.isLoggedIn || loginStatus.hasVerification) {
      return { needReLogin: true };
    }

    // 第二步：使用 AI 提取账号信息
    const accountInfo = await aiService.extractAccountInfo(screenshot, platform);

    logger.info(`[AI Refresh] Account info extraction for ${accountId}:`, {
      found: accountInfo.found,
      accountName: accountInfo.accountName,
    });

    if (accountInfo.found && accountInfo.accountName) {
      return {
        needReLogin: false,
        accountInfo: {
          accountName: accountInfo.accountName,
          fansCount: accountInfo.fansCount ? parseInt(String(accountInfo.fansCount)) : undefined,
          worksCount: accountInfo.worksCount ? parseInt(String(accountInfo.worksCount)) : undefined,
        },
      };
    }

    // AI 未能提取到账号信息，但登录状态正常
    // 返回空结果，让原有逻辑处理
    return { needReLogin: false };
  }

  /**
   * 检查账号 Cookie 是否有效
   */
  async checkAccountStatus(
    userId: number,
    accountId: number
  ): Promise<{ isValid: boolean; needReLogin: boolean; uncertain: boolean }> {
    const account = await this.accountRepository.findOne({
      where: { id: accountId, userId },
    });
    if (!account) {
      throw new AppError('账号不存在', HTTP_STATUS.NOT_FOUND, ERROR_CODES.ACCOUNT_NOT_FOUND);
    }

    if (!account.cookieData) {
      // 更新状态为过期
      await this.accountRepository.update(accountId, { status: 'expired' });
      return { isValid: false, needReLogin: true, uncertain: false };
    }

    const platform = account.platform as PlatformType;

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

      // 解析 Cookie - 支持两种格式
      let cookieList: { name: string; value: string; domain: string; path: string }[];
      try {
        // 先尝试 JSON 格式
        cookieList = JSON.parse(decryptedCookies);
      } catch {
        // 如果 JSON 解析失败，尝试解析 "name=value; name2=value2" 格式
        cookieList = this.parseCookieString(decryptedCookies, platform);
        if (cookieList.length === 0) {
          await this.accountRepository.update(accountId, { status: 'expired' });
          return { isValid: false, needReLogin: true, uncertain: false };
        }
      }

      const cookieStatus = await headlessBrowserService.checkCookieStatus(platform, cookieList);

      // 更新账号状态
      if (cookieStatus.needReLogin) {
        await this.accountRepository.update(accountId, { status: 'expired' });
        wsManager.sendToUser(userId, WS_EVENTS.ACCOUNT_UPDATED, {
          account: { ...this.formatAccount(account), status: 'expired' }
        });
        return { isValid: false, needReLogin: true, uncertain: false };
      }

      if (cookieStatus.uncertain) {
        return { isValid: true, needReLogin: false, uncertain: true };
      }

      if (cookieStatus.isValid && account.status === 'expired') {
        // 如果之前是过期状态但现在有效了，更新为正常
        await this.accountRepository.update(accountId, { status: 'active' });
      }

      return { isValid: cookieStatus.isValid, needReLogin: false, uncertain: false };
    } catch (error) {
      logger.error(`Failed to check account status ${accountId}:`, error);
      return { isValid: true, needReLogin: false, uncertain: true };
    }
  }

  /**
   * 批量刷新所有账号状态
   */
  async refreshAllAccounts(userId: number): Promise<{ refreshed: number; failed: number }> {
    const accounts = await this.accountRepository.find({
      where: { userId },
    });

    let refreshed = 0;
    let failed = 0;

    for (const account of accounts) {
      try {
        await this.refreshAccount(userId, account.id);
        refreshed++;
      } catch (error) {
        logger.error(`Failed to refresh account ${account.id}:`, error);
        failed++;
      }
    }

    logger.info(`Refreshed ${refreshed} accounts for user ${userId}, ${failed} failed`);
    return { refreshed, failed };
  }

  async getQRCode(platform: string): Promise<QRCodeInfo> {
    // TODO: 调用对应平台适配器获取二维码
    // 这里返回模拟数据
    return {
      qrcodeUrl: `https://example.com/qrcode/${platform}/${Date.now()}`,
      qrcodeKey: `qr_${platform}_${Date.now()}`,
      expireTime: Date.now() + 300000, // 5分钟后过期
    };
  }

  async checkQRCodeStatus(platform: string, qrcodeKey: string): Promise<LoginStatusResult> {
    // TODO: 调用对应平台适配器检查扫码状态
    // 这里返回模拟数据
    return {
      status: 'waiting',
      message: '等待扫码',
    };
  }

  /**
   * 验证 Cookie 并获取账号信息（用于 Electron 内嵌浏览器登录）
   */
  async verifyCookieAndGetInfo(platform: PlatformType, cookieData: string): Promise<{
    success: boolean;
    message?: string;
    accountInfo?: {
      accountId: string;
      accountName: string;
      avatarUrl: string;
      fansCount: number;
      worksCount: number;
    };
  }> {
    try {
      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',
      };

      let cookieList: { name: string; value: string; domain: string; path: string }[] = [];
      try {
        const parsed = JSON.parse(cookieData) as Array<{
          name?: string;
          value?: string;
          domain?: string;
          path?: string;
        }>;
        if (Array.isArray(parsed) && parsed.length > 0) {
          const domain = domainMap[platform] || `.${platform}.com`;
          cookieList = parsed
            .filter(c => c?.name && c?.value)
            .map(c => ({
              name: String(c.name),
              value: String(c.value),
              domain: c.domain ? String(c.domain) : domain,
              path: c.path ? String(c.path) : '/',
            }));
        }
      } catch {
        cookieList = this.parseCookieString(cookieData, platform);
      }

      if (cookieList.length === 0) {
        return { success: false, message: 'Cookie 格式无效' };
      }

      // 先尝试获取账号信息（可以同时验证登录状态）
      // 如果能成功获取到有效信息，说明登录是有效的
      try {
        const profile = await headlessBrowserService.fetchAccountInfo(platform, cookieList);

        // 检查是否获取到有效信息（排除默认名称）
        const defaultNames = [
          `${platform}账号`, '未知账号', '抖音账号', '小红书账号',
          '快手账号', '视频号账号', 'B站账号', '头条账号', '百家号账号'
        ];
        const isValidProfile = profile.accountName && !defaultNames.includes(profile.accountName);

        if (isValidProfile) {
          return {
            success: true,
            accountInfo: {
              // 确保 accountId 带有平台前缀
              accountId: this.normalizeAccountId(platform, profile.accountId || ''),
              accountName: profile.accountName,
              avatarUrl: profile.avatarUrl || '',
              fansCount: profile.fansCount || 0,
              worksCount: profile.worksCount || 0,
            },
          };
        }

        // 未能获取有效信息，再验证 Cookie 是否有效
        logger.info(`[verifyCookieAndGetInfo] Could not get valid profile for ${platform}, checking cookie validity...`);
      } catch (infoError) {
        logger.warn(`Failed to fetch account info for ${platform}:`, infoError);
      }

      // 账号信息获取失败或无效，检查 Cookie 是否有效
      const cookieStatus = await headlessBrowserService.checkCookieStatus(platform, cookieList);

      if (cookieStatus.isValid) {
        // Cookie 有效但未能获取账号信息，返回基本成功
        return {
          success: true,
          message: '登录成功，但无法获取详细信息',
          accountInfo: {
            accountId: `${platform}_${Date.now()}`,
            accountName: `${platform}账号`,
            avatarUrl: '',
            fansCount: 0,
            worksCount: 0,
          },
        };
      }

      if (cookieStatus.needReLogin) {
        // Cookie 无效
        return { success: false, message: '登录状态无效或已过期' };
      }

      return { success: false, message: '无法验证登录状态，请稍后重试' };
    } catch (error) {
      logger.error(`Failed to verify cookie for ${platform}:`, error);
      return {
        success: false,
        message: error instanceof Error ? error.message : '验证失败'
      };
    }
  }

  /**
   * 将 cookie 字符串解析为 cookie 列表
   */
  private parseCookieString(cookieString: string, platform: PlatformType): {
    name: string;
    value: string;
    domain: string;
    path: string;
  }[] {
    // 获取平台对应的域名
    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: { name: string; value: string; domain: string; path: string }[] = [];

    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 formatGroup(group: AccountGroup): AccountGroupType {
    return {
      id: group.id,
      userId: group.userId,
      name: group.name,
      description: group.description,
      createdAt: group.createdAt.toISOString(),
    };
  }

  private formatAccount(account: PlatformAccount): PlatformAccountType {
    return {
      id: account.id,
      userId: account.userId,
      platform: account.platform,
      accountName: account.accountName || '',
      accountId: account.accountId || '',
      avatarUrl: account.avatarUrl,
      fansCount: account.fansCount,
      worksCount: account.worksCount,
      status: account.status,
      proxyConfig: account.proxyConfig,
      groupId: account.groupId,
      cookieExpireAt: account.cookieExpireAt?.toISOString() || null,
      createdAt: account.createdAt.toISOString(),
      updatedAt: account.updatedAt.toISOString(),
    };
  }

  /**
   * 从 Cookie 中提取账号 ID（最可靠的方式）
   * 不同平台使用不同的 Cookie 字段来标识用户
   */
  private extractAccountIdFromCookie(platform: PlatformType, cookieString: string): string | null {
    // 各平台用于标识用户的 Cookie 名称（按优先级排序）
    const platformCookieNames: Record<string, string[]> = {
      douyin: ['passport_uid', 'uid_tt', 'ttwid', 'sessionid_ss'],
      kuaishou: ['userId', 'passToken', 'did'],
      xiaohongshu: ['customerClientId', 'web_session', 'xsecappid'],
      weixin_video: ['wxuin', 'pass_ticket', 'uin'],
      bilibili: ['DedeUserID', 'SESSDATA', 'bili_jct'],
      toutiao: ['sso_uid', 'sessionid', 'passport_uid'],
      baijiahao: ['BDUSS', 'STOKEN', 'BAIDUID'],
      qie: ['uin', 'skey', 'p_uin'],
      dayuhao: ['login_aliyunid', 'cna', 'munb'],
    };

    const targetCookieNames = platformCookieNames[platform] || [];
    if (targetCookieNames.length === 0) {
      return null;
    }

    try {
      // 尝试解析 JSON 格式的 Cookie
      let cookieList: { name: string; value: string }[];
      try {
        cookieList = JSON.parse(cookieString);
      } catch {
        // 如果不是 JSON，尝试解析 "name=value; name2=value2" 格式
        cookieList = this.parseCookieString(cookieString, platform).map(c => ({
          name: c.name,
          value: c.value,
        }));
      }

      if (!Array.isArray(cookieList) || cookieList.length === 0) {
        return null;
      }

      // 按优先级查找 Cookie
      for (const cookieName of targetCookieNames) {
        const cookie = cookieList.find(c => c.name === cookieName);
        if (cookie?.value) {
          // 获取 Cookie 值，处理可能的编码
          let cookieValue = cookie.value;

          // 处理特殊格式的 Cookie（如 ttwid 可能包含分隔符）
          if (cookieValue.includes('|')) {
            cookieValue = cookieValue.split('|')[1] || cookieValue;
          }
          if (cookieValue.includes('%')) {
            try {
              cookieValue = decodeURIComponent(cookieValue);
            } catch {
              // 解码失败，使用原值
            }
          }

          // 截取合理长度（避免过长的 ID）
          if (cookieValue.length > 64) {
            cookieValue = cookieValue.slice(0, 64);
          }

          const accountId = `${platform}_${cookieValue}`;
          logger.info(`[extractAccountIdFromCookie] Found ${cookieName} for ${platform}: ${accountId}`);
          return accountId;
        }
      }

      return null;
    } catch (error) {
      logger.warn(`[extractAccountIdFromCookie] Failed to extract accountId from cookie for ${platform}:`, error);
      return null;
    }
  }

  /**
   * 平台短前缀映射（统一使用短前缀）
   */
  private static readonly SHORT_PREFIX_MAP: Record<PlatformType, string> = {
    'douyin': 'dy_',
    'xiaohongshu': 'xhs_',
    'weixin_video': 'sph_',
    'baijiahao': 'bjh_',
    'kuaishou': 'ks_',
    'bilibili': 'bili_',
    'toutiao': 'tt_',
    'qie': 'qie_',
    'dayuhao': 'dyh_',
  };

  /**
   * 标准化 accountId 格式，统一使用短前缀
   * 例如：Ethanfly9392 -> dy_Ethanfly9392
   */
  private normalizeAccountId(platform: PlatformType, accountId: string): string {
    const shortPrefix = AccountService.SHORT_PREFIX_MAP[platform] || `${platform}_`;

    if (!accountId) {
      return `${shortPrefix}${Date.now()}`;
    }

    // 如果已经有正确的短前缀，直接返回
    if (accountId.startsWith(shortPrefix)) {
      return accountId;
    }

    // 移除任何已有的前缀（短前缀或完整前缀）
    const allShortPrefixes = Object.values(AccountService.SHORT_PREFIX_MAP);
    const allFullPrefixes = Object.keys(AccountService.SHORT_PREFIX_MAP).map(p => `${p}_`);
    const allPrefixes = [...allShortPrefixes, ...allFullPrefixes];

    let cleanId = accountId;
    for (const prefix of allPrefixes) {
      if (cleanId.startsWith(prefix)) {
        cleanId = cleanId.slice(prefix.length);
        break;
      }
    }

    // 添加正确的短前缀
    return `${shortPrefix}${cleanId}`;
  }

  /**
   * 检查 accountId 是否是基于时间戳生成的（不可靠的 ID）
   * 时间戳 ID 格式通常是：dy_1737619200000 或 douyin_1737619200000
   */
  private isTimestampBasedId(accountId: string): boolean {
    if (!accountId) return true;

    // 检查是否匹配 前缀_时间戳 格式（支持短前缀和完整前缀）
    const timestampPattern = /^[a-z_]+_(\d{13,})$/;
    const match = accountId.match(timestampPattern);
    if (!match) {
      return false;
    }

    // 提取数字部分，检查是否是合理的时间戳（2020年到2030年之间）
    if (match[1]) {
      const timestamp = parseInt(match[1]);
      const minTimestamp = new Date('2020-01-01').getTime(); // 1577836800000
      const maxTimestamp = new Date('2030-01-01').getTime(); // 1893456000000

      if (timestamp >= minTimestamp && timestamp <= maxTimestamp) {
        logger.info(`[isTimestampBasedId] Detected timestamp-based ID: ${accountId}`);
        return true;
      }
    }

    return false;
  }
}
