/**
 * Admin Evaluation Rule Controller
 * 评估规则管理 API — 供 admin-client 使用
 *
 * 管理员可以：
 * 1. 为不同咨询阶段配置评估规则
 * 2. 开关规则
 * 3. 测试规则（dry-run）
 * 4. 清除规则缓存
 *
 * ⚠️ 路由顺序重要：静态路由（test, cache）必须在动态路由（:id）之前声明，
 *    否则 NestJS 会把 "test"/"cache" 当作 :id 参数匹配。
 */

import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Param,
  Body,
  Query,
  Headers,
  HttpCode,
  HttpStatus,
  UnauthorizedException,
  BadRequestException,
} from '@nestjs/common';
import * as jwt from 'jsonwebtoken';
import { v4 as uuidv4 } from 'uuid';
import { EvaluationGateService } from '../../infrastructure/agents/coordinator/evaluation-gate.service';
import {
  IEvaluationRuleRepository,
  EVALUATION_RULE_REPOSITORY,
} from '../../domain/repositories/evaluation-rule.repository.interface';
import {
  EvaluationRuleEntity,
  EvaluationRuleType,
  EvaluationFailureAction,
} from '../../domain/entities/evaluation-rule.entity';
import {
  CreateEvaluationRuleDto,
  UpdateEvaluationRuleDto,
  TestEvaluationDto,
} from '../../application/dtos/evaluation-rule.dto';
import { Inject } from '@nestjs/common';

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

@Controller('conversations/admin/evaluation-rules')
export class AdminEvaluationRuleController {
  constructor(
    @Inject(EVALUATION_RULE_REPOSITORY)
    private readonly repo: IEvaluationRuleRepository,
    private readonly evaluationGate: EvaluationGateService,
  ) {}

  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';
      return jwt.verify(token, secret) as AdminPayload;
    } catch {
      throw new UnauthorizedException('Invalid token');
    }
  }

  // ─── 静态路由（必须在 :id 之前） ─────────────────────────

  // POST /conversations/admin/evaluation-rules/test
  @Post('test')
  async testEvaluation(
    @Headers('authorization') auth: string,
    @Body() dto: TestEvaluationDto,
  ) {
    const admin = this.verifyAdmin(auth);
    const tenantId = admin.tenantId || null;

    if (!dto.stage || !dto.responseText) {
      throw new BadRequestException('stage and responseText are required');
    }

    const result = await this.evaluationGate.evaluate(tenantId, {
      stage: dto.stage,
      collectedInfo: dto.collectedInfo || null,
      assessmentResult: dto.assessmentResult || null,
      responseText: dto.responseText,
      turnCount: dto.turnCount || 1,
      messageCount: dto.messageCount || 1,
      hasConverted: false,
      agentsUsed: [],
    });

    return { success: true, data: result };
  }

  // DELETE /conversations/admin/evaluation-rules/cache
  @Delete('cache')
  async clearCache(@Headers('authorization') auth: string) {
    this.verifyAdmin(auth);
    this.evaluationGate.clearCache();
    return { success: true, message: 'Cache cleared' };
  }

  // ─── 集合路由 ──────────────────────────────────────────

  // GET /conversations/admin/evaluation-rules
  @Get()
  async listRules(
    @Headers('authorization') auth: string,
    @Query('stage') stage?: string,
  ) {
    const admin = this.verifyAdmin(auth);
    const tenantId = admin.tenantId || null;

    const allRules = await this.repo.findAllByTenant(tenantId);
    const filtered = stage
      ? allRules.filter(r => r.stage === stage || r.stage === '*')
      : allRules;

    return {
      success: true,
      data: {
        items: filtered.map(r => this.toResponse(r)),
        total: filtered.length,
        ruleTypes: Object.values(EvaluationRuleType),
        failureActions: Object.values(EvaluationFailureAction),
        stages: ['*', 'greeting', 'needs_discovery', 'info_collection', 'assessment', 'recommendation', 'objection_handling', 'conversion', 'handoff'],
      },
    };
  }

  // POST /conversations/admin/evaluation-rules
  @Post()
  @HttpCode(HttpStatus.CREATED)
  async createRule(
    @Headers('authorization') auth: string,
    @Body() dto: CreateEvaluationRuleDto,
  ) {
    const admin = this.verifyAdmin(auth);
    const tenantId = admin.tenantId || null;

    if (!dto.name || !dto.stage || !dto.ruleType || !dto.config) {
      throw new BadRequestException('name, stage, ruleType, and config are required');
    }

    if (!Object.values(EvaluationRuleType).includes(dto.ruleType)) {
      throw new BadRequestException(`Invalid ruleType. Valid types: ${Object.values(EvaluationRuleType).join(', ')}`);
    }

    if (dto.failureAction && !Object.values(EvaluationFailureAction).includes(dto.failureAction)) {
      throw new BadRequestException(`Invalid failureAction. Valid actions: ${Object.values(EvaluationFailureAction).join(', ')}`);
    }

    const rule = EvaluationRuleEntity.create({
      id: uuidv4(),
      tenantId,
      stage: dto.stage,
      ruleType: dto.ruleType,
      name: dto.name,
      description: dto.description,
      config: dto.config,
      priority: dto.priority,
      failureAction: dto.failureAction,
      createdBy: admin.id,
    });

    const saved = await this.repo.save(rule);

    // Invalidate cache
    this.evaluationGate.clearCache(tenantId || undefined);

    return { success: true, data: this.toResponse(saved) };
  }

  // ─── 动态路由（:id 在静态路由之后） ───────────────────────

  // GET /conversations/admin/evaluation-rules/:id
  @Get(':id')
  async getRule(
    @Headers('authorization') auth: string,
    @Param('id') id: string,
  ) {
    this.verifyAdmin(auth);

    const rule = await this.repo.findById(id);
    if (!rule) {
      return { success: false, error: 'Rule not found' };
    }

    return { success: true, data: this.toResponse(rule) };
  }

  // PUT /conversations/admin/evaluation-rules/:id
  @Put(':id')
  async updateRule(
    @Headers('authorization') auth: string,
    @Param('id') id: string,
    @Body() dto: UpdateEvaluationRuleDto,
  ) {
    const admin = this.verifyAdmin(auth);

    const rule = await this.repo.findById(id);
    if (!rule) {
      return { success: false, error: 'Rule not found' };
    }

    if (dto.stage !== undefined) rule.stage = dto.stage;
    if (dto.ruleType !== undefined) rule.ruleType = dto.ruleType;
    if (dto.name !== undefined) rule.name = dto.name;
    if (dto.description !== undefined) rule.description = dto.description;
    if (dto.config !== undefined) rule.config = dto.config;
    if (dto.priority !== undefined) rule.priority = dto.priority;
    if (dto.failureAction !== undefined) rule.failureAction = dto.failureAction;
    if (dto.enabled !== undefined) rule.enabled = dto.enabled;
    rule.updatedBy = admin.id;
    rule.updatedAt = new Date();

    const updated = await this.repo.update(rule);

    // Invalidate cache
    this.evaluationGate.clearCache(rule.tenantId || undefined);

    return { success: true, data: this.toResponse(updated) };
  }

  // DELETE /conversations/admin/evaluation-rules/:id
  @Delete(':id')
  async deleteRule(
    @Headers('authorization') auth: string,
    @Param('id') id: string,
  ) {
    this.verifyAdmin(auth);

    const rule = await this.repo.findById(id);
    if (!rule) {
      return { success: false, error: 'Rule not found' };
    }

    await this.repo.delete(id);

    // Invalidate cache
    this.evaluationGate.clearCache(rule.tenantId || undefined);

    return { success: true };
  }

  // POST /conversations/admin/evaluation-rules/:id/toggle
  @Post(':id/toggle')
  async toggleRule(
    @Headers('authorization') auth: string,
    @Param('id') id: string,
  ) {
    const admin = this.verifyAdmin(auth);

    const rule = await this.repo.findById(id);
    if (!rule) {
      return { success: false, error: 'Rule not found' };
    }

    rule.toggle();
    rule.updatedBy = admin.id;
    const updated = await this.repo.update(rule);

    // Invalidate cache
    this.evaluationGate.clearCache(rule.tenantId || undefined);

    return { success: true, data: this.toResponse(updated) };
  }

  // ─── 私有方法 ─────────────────────────────────────────

  private toResponse(rule: EvaluationRuleEntity) {
    return {
      id: rule.id,
      tenantId: rule.tenantId,
      stage: rule.stage,
      ruleType: rule.ruleType,
      name: rule.name,
      description: rule.description,
      config: rule.config,
      enabled: rule.enabled,
      priority: rule.priority,
      failureAction: rule.failureAction,
      createdBy: rule.createdBy,
      updatedBy: rule.updatedBy,
      createdAt: rule.createdAt,
      updatedAt: rule.updatedAt,
    };
  }
}
