import {
  Controller,
  Get,
  Query,
  Param,
  Headers,
  UnauthorizedException,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import * as jwt from 'jsonwebtoken';
import { ConversationORM } from '../../infrastructure/database/postgres/entities/conversation.orm';
import { MessageORM } from '../../infrastructure/database/postgres/entities/message.orm';
import { TokenUsageORM } from '../../infrastructure/database/postgres/entities/token-usage.orm';
import { AgentExecutionORM } from '../../infrastructure/database/postgres/entities/agent-execution.orm';

interface AdminPayload {
  id: string;
  username: string;
  role: string;
}

interface TokenAggregation {
  totalInputTokens: number;
  totalOutputTokens: number;
  totalCacheCreationTokens: number;
  totalCacheReadTokens: number;
  totalTokens: number;
  totalEstimatedCost: number;
  apiCallCount: number;
}

/**
 * 管理员对话 API - 供 admin-client 使用
 * 需要管理员 JWT 认证
 */
@Controller('conversations/admin')
export class AdminConversationController {
  constructor(
    @InjectRepository(ConversationORM)
    private conversationRepo: Repository<ConversationORM>,
    @InjectRepository(MessageORM)
    private messageRepo: Repository<MessageORM>,
    @InjectRepository(TokenUsageORM)
    private tokenUsageRepo: Repository<TokenUsageORM>,
    @InjectRepository(AgentExecutionORM)
    private agentExecutionRepo: Repository<AgentExecutionORM>,
  ) {}

  /**
   * 验证管理员 Token
   */
  private verifyAdmin(authorization: string): AdminPayload {
    const token = authorization?.replace('Bearer ', '');
    if (!token) {
      throw new UnauthorizedException('Missing token');
    }

    try {
      const secret = process.env.JWT_SECRET || 'your-jwt-secret-key';
      const payload = jwt.verify(token, secret) as AdminPayload;
      return payload;
    } catch {
      throw new UnauthorizedException('Invalid token');
    }
  }

  /**
   * 从 token_usage 表聚合准确的 token 使用数据
   */
  private async aggregateTokenUsage(conversationId: string): Promise<TokenAggregation> {
    const result = await this.tokenUsageRepo
      .createQueryBuilder('t')
      .select([
        'SUM(t.input_tokens) as "totalInputTokens"',
        'SUM(t.output_tokens) as "totalOutputTokens"',
        'SUM(t.cache_creation_tokens) as "totalCacheCreationTokens"',
        'SUM(t.cache_read_tokens) as "totalCacheReadTokens"',
        'SUM(t.total_tokens) as "totalTokens"',
        'SUM(t.estimated_cost) as "totalEstimatedCost"',
        'COUNT(*) as "apiCallCount"',
      ])
      .where('t.conversation_id = :conversationId', { conversationId })
      .getRawOne();

    return {
      totalInputTokens: parseInt(result?.totalInputTokens || '0'),
      totalOutputTokens: parseInt(result?.totalOutputTokens || '0'),
      totalCacheCreationTokens: parseInt(result?.totalCacheCreationTokens || '0'),
      totalCacheReadTokens: parseInt(result?.totalCacheReadTokens || '0'),
      totalTokens: parseInt(result?.totalTokens || '0'),
      totalEstimatedCost: parseFloat(result?.totalEstimatedCost || '0'),
      apiCallCount: parseInt(result?.apiCallCount || '0'),
    };
  }

  /**
   * 获取所有对话列表（分页）
   */
  @Get('list')
  async listConversations(
    @Headers('authorization') auth: string,
    @Query('page') page?: string,
    @Query('pageSize') pageSize?: string,
    @Query('status') status?: string,
    @Query('userId') userId?: string,
    @Query('startDate') startDate?: string,
    @Query('endDate') endDate?: string,
    @Query('hasConverted') hasConverted?: string,
    @Query('sortBy') sortBy?: string,
    @Query('sortOrder') sortOrder?: string,
  ) {
    this.verifyAdmin(auth);

    const pageNum = parseInt(page || '1');
    const pageSizeNum = parseInt(pageSize || '20');

    const queryBuilder = this.conversationRepo.createQueryBuilder('c');

    // 应用筛选条件
    if (status) {
      queryBuilder.andWhere('c.status = :status', { status });
    }

    if (userId) {
      queryBuilder.andWhere('c.user_id = :userId', { userId });
    }

    if (startDate) {
      queryBuilder.andWhere('c.created_at >= :startDate', {
        startDate: new Date(startDate),
      });
    }

    if (endDate) {
      queryBuilder.andWhere('c.created_at <= :endDate', {
        endDate: new Date(endDate),
      });
    }

    if (hasConverted !== undefined) {
      queryBuilder.andWhere('c.has_converted = :hasConverted', {
        hasConverted: hasConverted === 'true',
      });
    }

    // 排序
    const sortColumnMap: Record<string, string> = {
      createdAt: 'c.created_at',
      updatedAt: 'c.updated_at',
      messageCount: 'c.message_count',
    };
    const validSortBy = sortBy && sortColumnMap[sortBy] ? sortBy : 'createdAt';
    const validSortOrder = sortOrder === 'ASC' ? 'ASC' : 'DESC';

    queryBuilder.orderBy(sortColumnMap[validSortBy], validSortOrder);

    // 获取总数
    const total = await queryBuilder.getCount();

    // 分页
    queryBuilder.skip((pageNum - 1) * pageSizeNum).take(pageSizeNum);

    const conversations = await queryBuilder.getMany();

    return {
      success: true,
      data: {
        items: conversations.map((c) => ({
          id: c.id,
          userId: c.userId,
          status: c.status,
          title: c.title,
          summary: c.summary,
          category: c.category,
          messageCount: c.messageCount,
          userMessageCount: c.userMessageCount,
          assistantMessageCount: c.assistantMessageCount,
          totalInputTokens: c.totalInputTokens,
          totalOutputTokens: c.totalOutputTokens,
          rating: c.rating,
          feedback: c.feedback,
          hasConverted: c.hasConverted,
          consultingStage: c.consultingStage,
          deviceInfo: c.deviceInfo,
          createdAt: c.createdAt,
          updatedAt: c.updatedAt,
          endedAt: c.endedAt,
        })),
        total,
        page: pageNum,
        pageSize: pageSizeNum,
        totalPages: Math.ceil(total / pageSizeNum),
      },
    };
  }

  /**
   * 获取用户的对话列表
   */
  @Get('by-user/:userId')
  async getConversationsByUser(
    @Headers('authorization') auth: string,
    @Param('userId') userId: string,
    @Query('limit') limit?: string,
  ) {
    this.verifyAdmin(auth);

    const limitNum = parseInt(limit || '10');

    const conversations = await this.conversationRepo.find({
      where: { userId },
      order: { createdAt: 'DESC' },
      take: limitNum,
    });

    return {
      success: true,
      data: conversations.map((c) => ({
        id: c.id,
        userId: c.userId,
        status: c.status,
        title: c.title,
        messageCount: c.messageCount,
        hasConverted: c.hasConverted,
        consultingStage: c.consultingStage,
        deviceInfo: c.deviceInfo,
        createdAt: c.createdAt,
        updatedAt: c.updatedAt,
        endedAt: c.endedAt,
      })),
    };
  }

  /**
   * Agent 调用统计（按 agentType 分组聚合）
   */
  @Get('statistics/agents')
  async getAgentStatistics(
    @Headers('authorization') auth: string,
    @Query('days') days?: string,
  ) {
    this.verifyAdmin(auth);

    const daysNum = parseInt(days || '30');
    const since = new Date();
    since.setDate(since.getDate() - daysNum);

    const results = await this.agentExecutionRepo
      .createQueryBuilder('a')
      .select([
        'a.agent_type as "agentType"',
        'a.agent_name as "agentName"',
        'COUNT(*) as "totalCalls"',
        'SUM(CASE WHEN a.success THEN 1 ELSE 0 END) as "successCount"',
        'SUM(CASE WHEN NOT a.success THEN 1 ELSE 0 END) as "failureCount"',
        'ROUND(AVG(a.duration_ms)) as "avgDurationMs"',
        'MIN(a.duration_ms) as "minDurationMs"',
        'MAX(a.duration_ms) as "maxDurationMs"',
      ])
      .where('a.created_at >= :since', { since })
      .groupBy('a.agent_type')
      .addGroupBy('a.agent_name')
      .orderBy('"totalCalls"', 'DESC')
      .getRawMany();

    return {
      success: true,
      data: results.map((r) => ({
        agentType: r.agentType,
        agentName: r.agentName,
        totalCalls: parseInt(r.totalCalls || '0'),
        successCount: parseInt(r.successCount || '0'),
        failureCount: parseInt(r.failureCount || '0'),
        successRate:
          parseInt(r.totalCalls || '0') > 0
            ? parseFloat(((parseInt(r.successCount || '0') / parseInt(r.totalCalls || '0')) * 100).toFixed(1))
            : 0,
        avgDurationMs: parseInt(r.avgDurationMs || '0'),
        minDurationMs: parseInt(r.minDurationMs || '0'),
        maxDurationMs: parseInt(r.maxDurationMs || '0'),
      })),
    };
  }

  /**
   * Agent 调用趋势（每日分组）
   */
  @Get('statistics/agents/trend')
  async getAgentTrend(
    @Headers('authorization') auth: string,
    @Query('days') days?: string,
    @Query('agentType') agentType?: string,
  ) {
    this.verifyAdmin(auth);

    const daysNum = parseInt(days || '7');
    const since = new Date();
    since.setDate(since.getDate() - daysNum);

    const qb = this.agentExecutionRepo
      .createQueryBuilder('a')
      .select([
        'DATE(a.created_at) as "date"',
        'a.agent_type as "agentType"',
        'COUNT(*) as "calls"',
        'ROUND(AVG(a.duration_ms)) as "avgDurationMs"',
        'ROUND(SUM(CASE WHEN a.success THEN 1 ELSE 0 END)::numeric / NULLIF(COUNT(*), 0) * 100, 1) as "successRate"',
      ])
      .where('a.created_at >= :since', { since });

    if (agentType) {
      qb.andWhere('a.agent_type = :agentType', { agentType });
    }

    const results = await qb
      .groupBy('DATE(a.created_at)')
      .addGroupBy('a.agent_type')
      .orderBy('"date"', 'ASC')
      .addOrderBy('a.agent_type', 'ASC')
      .getRawMany();

    return {
      success: true,
      data: results.map((r) => ({
        date: r.date,
        agentType: r.agentType,
        calls: parseInt(r.calls || '0'),
        avgDurationMs: parseInt(r.avgDurationMs || '0'),
        successRate: parseFloat(r.successRate || '0'),
      })),
    };
  }

  /**
   * 获取单个对话详情
   * 包含从 token_usage 表聚合的准确 token 数据
   */
  @Get(':id')
  async getConversation(
    @Headers('authorization') auth: string,
    @Param('id') id: string,
  ) {
    this.verifyAdmin(auth);

    const conversation = await this.conversationRepo.findOne({
      where: { id },
    });

    if (!conversation) {
      return {
        success: false,
        error: 'Conversation not found',
      };
    }

    // 从 token_usage 表获取准确的 token 统计（而不是仅依赖 conversation 实体）
    const tokenStats = await this.aggregateTokenUsage(id);

    return {
      success: true,
      data: {
        id: conversation.id,
        userId: conversation.userId,
        status: conversation.status,
        title: conversation.title,
        summary: conversation.summary,
        category: conversation.category,
        messageCount: conversation.messageCount,
        userMessageCount: conversation.userMessageCount,
        assistantMessageCount: conversation.assistantMessageCount,
        // 使用聚合的准确 token 数据
        totalInputTokens: tokenStats.totalInputTokens,
        totalOutputTokens: tokenStats.totalOutputTokens,
        // 额外的 token 详情
        tokenDetails: {
          cacheCreationTokens: tokenStats.totalCacheCreationTokens,
          cacheReadTokens: tokenStats.totalCacheReadTokens,
          totalTokens: tokenStats.totalTokens,
          estimatedCost: tokenStats.totalEstimatedCost,
          apiCallCount: tokenStats.apiCallCount,
        },
        rating: conversation.rating,
        feedback: conversation.feedback,
        hasConverted: conversation.hasConverted,
        consultingStage: conversation.consultingStage,
        consultingState: conversation.consultingState,
        collectedInfo: conversation.collectedInfo,
        recommendedPrograms: conversation.recommendedPrograms,
        conversionPath: conversation.conversionPath,
        deviceInfo: conversation.deviceInfo,
        createdAt: conversation.createdAt,
        updatedAt: conversation.updatedAt,
        endedAt: conversation.endedAt,
      },
    };
  }

  /**
   * 获取对话的消息
   */
  @Get(':id/messages')
  async getConversationMessages(
    @Headers('authorization') auth: string,
    @Param('id') conversationId: string,
  ) {
    this.verifyAdmin(auth);

    const messages = await this.messageRepo.find({
      where: { conversationId },
      order: { createdAt: 'ASC' },
    });

    return {
      success: true,
      data: messages.map((m) => ({
        id: m.id,
        conversationId: m.conversationId,
        role: m.role,
        type: m.type,
        content: m.content,
        metadata: m.metadata,
        createdAt: m.createdAt,
      })),
    };
  }

  /**
   * 获取单个对话的 Agent 执行记录
   */
  @Get(':id/agent-executions')
  async getConversationAgentExecutions(
    @Headers('authorization') auth: string,
    @Param('id') conversationId: string,
  ) {
    this.verifyAdmin(auth);

    const executions = await this.agentExecutionRepo.find({
      where: { conversationId },
      order: { createdAt: 'ASC' },
    });

    return {
      success: true,
      data: executions.map((e) => ({
        id: e.id,
        conversationId: e.conversationId,
        agentType: e.agentType,
        agentName: e.agentName,
        durationMs: e.durationMs,
        success: e.success,
        errorMessage: e.errorMessage,
        toolCallsCount: e.toolCallsCount,
        createdAt: e.createdAt,
      })),
    };
  }

  /**
   * 获取对话统计（包含 Token 汇总）
   */
  @Get('statistics/overview')
  async getStatistics(@Headers('authorization') auth: string) {
    this.verifyAdmin(auth);

    const total = await this.conversationRepo.count();
    const active = await this.conversationRepo.count({ where: { status: 'ACTIVE' } });
    const ended = await this.conversationRepo.count({ where: { status: 'ENDED' } });
    const converted = await this.conversationRepo.count({ where: { hasConverted: true } });

    // 今日对话
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    const todayCount = await this.conversationRepo
      .createQueryBuilder('c')
      .where('c.created_at >= :today', { today })
      .getCount();

    // 全局 Token 统计
    const allTokenStats = await this.tokenUsageRepo
      .createQueryBuilder('t')
      .select([
        'SUM(t.input_tokens) as "totalInputTokens"',
        'SUM(t.output_tokens) as "totalOutputTokens"',
        'SUM(t.cache_creation_tokens) as "totalCacheCreationTokens"',
        'SUM(t.cache_read_tokens) as "totalCacheReadTokens"',
        'SUM(t.total_tokens) as "totalTokens"',
        'SUM(t.estimated_cost) as "totalEstimatedCost"',
        'COUNT(*) as "totalApiCalls"',
      ])
      .getRawOne();

    // 今日 Token 统计
    const todayTokenStats = await this.tokenUsageRepo
      .createQueryBuilder('t')
      .select([
        'SUM(t.input_tokens) as "totalInputTokens"',
        'SUM(t.output_tokens) as "totalOutputTokens"',
        'SUM(t.total_tokens) as "totalTokens"',
        'SUM(t.estimated_cost) as "totalEstimatedCost"',
        'COUNT(*) as "totalApiCalls"',
      ])
      .where('t.created_at >= :today', { today })
      .getRawOne();

    return {
      success: true,
      data: {
        total,
        active,
        ended,
        converted,
        todayCount,
        conversionRate: total > 0 ? ((converted / total) * 100).toFixed(1) : '0',
        // Token 汇总统计
        tokenStats: {
          totalInputTokens: parseInt(allTokenStats?.totalInputTokens || '0'),
          totalOutputTokens: parseInt(allTokenStats?.totalOutputTokens || '0'),
          totalCacheCreationTokens: parseInt(allTokenStats?.totalCacheCreationTokens || '0'),
          totalCacheReadTokens: parseInt(allTokenStats?.totalCacheReadTokens || '0'),
          totalTokens: parseInt(allTokenStats?.totalTokens || '0'),
          totalEstimatedCost: parseFloat(allTokenStats?.totalEstimatedCost || '0'),
          totalApiCalls: parseInt(allTokenStats?.totalApiCalls || '0'),
        },
        todayTokenStats: {
          totalInputTokens: parseInt(todayTokenStats?.totalInputTokens || '0'),
          totalOutputTokens: parseInt(todayTokenStats?.totalOutputTokens || '0'),
          totalTokens: parseInt(todayTokenStats?.totalTokens || '0'),
          totalEstimatedCost: parseFloat(todayTokenStats?.totalEstimatedCost || '0'),
          totalApiCalls: parseInt(todayTokenStats?.totalApiCalls || '0'),
        },
      },
    };
  }
}
