import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Body,
  Param,
  Query,
  HttpCode,
  HttpStatus,
  Inject,
  NotFoundException,
  BadRequestException,
} from '@nestjs/common';
import { v4 as uuidv4 } from 'uuid';
import {
  CLASSIFICATION_RULE_REPOSITORY,
  ClassificationRuleRepository,
} from '../../domain/repositories/classification-rule.repository';
import {
  USER_TAG_REPOSITORY,
  UserTagRepository,
} from '../../domain/repositories/user-tag.repository';
import { ClassificationRuleEntity } from '../../domain/entities/classification-rule.entity';
import { RuleEngineService } from '../../application/services/rule-engine.service';
import {
  CreateRuleDto,
  UpdateRuleDto,
  ListRulesDto,
  TestRuleDto,
  EstimateRuleDto,
} from '../dto/request/classification-rule.dto';
import {
  RuleResponseDto,
  RuleListResponseDto,
  RuleTestResultDto,
  RuleEstimateResultDto,
} from '../dto/response/classification-rule.dto';

/**
 * 分类规则管理控制器
 */
@Controller('admin/rules')
export class ClassificationRuleController {
  constructor(
    @Inject(CLASSIFICATION_RULE_REPOSITORY)
    private readonly ruleRepository: ClassificationRuleRepository,
    @Inject(USER_TAG_REPOSITORY)
    private readonly tagRepository: UserTagRepository,
    private readonly ruleEngine: RuleEngineService,
  ) {}

  /**
   * 创建规则
   */
  @Post()
  async createRule(@Body() dto: CreateRuleDto): Promise<RuleResponseDto> {
    // 验证条件格式
    if (!ClassificationRuleEntity.validateConditions(dto.conditions)) {
      throw new BadRequestException('Invalid rule conditions format');
    }

    const rule = ClassificationRuleEntity.create({
      id: uuidv4(),
      name: dto.name,
      description: dto.description,
      conditions: dto.conditions,
    });

    const saved = await this.ruleRepository.save(rule);
    return RuleResponseDto.fromEntity(saved);
  }

  /**
   * 获取规则列表
   */
  @Get()
  async listRules(@Query() dto: ListRulesDto): Promise<RuleListResponseDto> {
    const [rules, total] = await Promise.all([
      this.ruleRepository.findAll({
        isEnabled: dto.isEnabled,
        limit: dto.limit,
        offset: dto.offset,
      }),
      this.ruleRepository.count({ isEnabled: dto.isEnabled }),
    ]);

    // 获取关联的标签信息
    const linkedRules = await this.ruleRepository.findLinkedRules();
    const linkedMap = new Map(
      linkedRules.map((r) => [r.rule.id, { tagId: r.tagId, tagCode: r.tagCode }]),
    );

    return {
      items: rules.map((rule) =>
        RuleResponseDto.fromEntity(rule, linkedMap.get(rule.id)),
      ),
      total,
    };
  }

  /**
   * 获取规则详情
   */
  @Get(':id')
  async getRule(@Param('id') id: string): Promise<RuleResponseDto> {
    const rule = await this.ruleRepository.findById(id);
    if (!rule) {
      throw new NotFoundException(`Rule not found: ${id}`);
    }

    // 查找关联的标签
    const tags = await this.tagRepository.findAllTags();
    const linkedTag = tags.find((t) => t.ruleId === id);

    return RuleResponseDto.fromEntity(
      rule,
      linkedTag ? { tagId: linkedTag.id, tagCode: linkedTag.code } : null,
    );
  }

  /**
   * 更新规则
   */
  @Put(':id')
  async updateRule(
    @Param('id') id: string,
    @Body() dto: UpdateRuleDto,
  ): Promise<RuleResponseDto> {
    const existing = await this.ruleRepository.findById(id);
    if (!existing) {
      throw new NotFoundException(`Rule not found: ${id}`);
    }

    if (dto.conditions) {
      if (!ClassificationRuleEntity.validateConditions(dto.conditions)) {
        throw new BadRequestException('Invalid rule conditions format');
      }
    }

    const updated = existing.update(dto);
    const saved = await this.ruleRepository.save(updated);

    // 查找关联的标签
    const tags = await this.tagRepository.findAllTags();
    const linkedTag = tags.find((t) => t.ruleId === id);

    return RuleResponseDto.fromEntity(
      saved,
      linkedTag ? { tagId: linkedTag.id, tagCode: linkedTag.code } : null,
    );
  }

  /**
   * 删除规则
   */
  @Delete(':id')
  @HttpCode(HttpStatus.NO_CONTENT)
  async deleteRule(@Param('id') id: string): Promise<void> {
    const rule = await this.ruleRepository.findById(id);
    if (!rule) {
      throw new NotFoundException(`Rule not found: ${id}`);
    }
    await this.ruleRepository.delete(id);
  }

  /**
   * 启用规则
   */
  @Post(':id/enable')
  async enableRule(@Param('id') id: string): Promise<RuleResponseDto> {
    const rule = await this.ruleRepository.findById(id);
    if (!rule) {
      throw new NotFoundException(`Rule not found: ${id}`);
    }

    const enabled = rule.enable();
    const saved = await this.ruleRepository.save(enabled);
    return RuleResponseDto.fromEntity(saved);
  }

  /**
   * 禁用规则
   */
  @Post(':id/disable')
  async disableRule(@Param('id') id: string): Promise<RuleResponseDto> {
    const rule = await this.ruleRepository.findById(id);
    if (!rule) {
      throw new NotFoundException(`Rule not found: ${id}`);
    }

    const disabled = rule.disable();
    const saved = await this.ruleRepository.save(disabled);
    return RuleResponseDto.fromEntity(saved);
  }

  /**
   * 测试规则匹配
   */
  @Post(':id/test')
  async testRule(
    @Param('id') id: string,
    @Body() dto: TestRuleDto,
  ): Promise<RuleTestResultDto> {
    const rule = await this.ruleRepository.findById(id);
    if (!rule) {
      throw new NotFoundException(`Rule not found: ${id}`);
    }

    const result = await this.ruleEngine.evaluateUserRules(dto.accountSequence);
    const ruleResult = result.matchedRules.find((r) => r.ruleId === id);

    return {
      ruleId: id,
      ruleName: rule.name,
      accountSequence: dto.accountSequence,
      matched: ruleResult?.matched ?? false,
      evaluatedConditions: [], // TODO: 详细的条件评估结果
    };
  }

  /**
   * 预估规则匹配用户数
   */
  @Post(':id/estimate')
  async estimateRule(
    @Param('id') id: string,
  ): Promise<RuleEstimateResultDto> {
    const rule = await this.ruleRepository.findById(id);
    if (!rule) {
      throw new NotFoundException(`Rule not found: ${id}`);
    }

    const { accountSequences, total } = await this.ruleEngine.findMatchingUsers(
      rule,
      { limit: 10 },
    );

    return {
      estimatedUsers: total,
      sampleUsers: accountSequences,
    };
  }

  /**
   * 预估条件匹配用户数（不保存规则）
   */
  @Post('estimate')
  async estimateConditions(
    @Body() dto: EstimateRuleDto,
  ): Promise<RuleEstimateResultDto> {
    if (!ClassificationRuleEntity.validateConditions(dto.conditions)) {
      throw new BadRequestException('Invalid rule conditions format');
    }

    const tempRule = ClassificationRuleEntity.create({
      id: 'temp',
      name: 'temp',
      conditions: dto.conditions,
    });

    const { accountSequences, total } = await this.ruleEngine.findMatchingUsers(
      tempRule,
      { limit: 10 },
    );

    return {
      estimatedUsers: total,
      sampleUsers: accountSequences,
    };
  }
}
