import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Body,
  Param,
  Query,
  HttpCode,
  HttpStatus,
  NotFoundException,
  BadRequestException,
} from '@nestjs/common';
import { AudienceSegmentService } from '../../application/services/audience-segment.service';
import { AudienceSegmentEntity } from '../../domain/entities/audience-segment.entity';
import {
  CreateSegmentDto,
  UpdateSegmentDto,
  ListSegmentsDto,
  TestSegmentDto,
  EstimateSegmentDto,
  GetSegmentUsersDto,
} from '../dto/request/audience-segment.dto';
import {
  SegmentResponseDto,
  SegmentListResponseDto,
  SegmentTestResultDto,
  SegmentEstimateResultDto,
  SegmentUsersResponseDto,
  UserSegmentsResponseDto,
} from '../dto/response/audience-segment.dto';

/**
 * 人群包管理控制器
 */
@Controller('admin/segments')
export class AudienceSegmentController {
  constructor(private readonly segmentService: AudienceSegmentService) {}

  /**
   * 创建人群包
   */
  @Post()
  async createSegment(
    @Body() dto: CreateSegmentDto,
  ): Promise<SegmentResponseDto> {
    const segment = await this.segmentService.createSegment({
      name: dto.name,
      description: dto.description,
      conditions: dto.conditions,
      usageType: dto.usageType,
      createdBy: 'admin', // TODO: 从认证信息获取
    });

    return SegmentResponseDto.fromEntity(segment);
  }

  /**
   * 获取人群包列表
   */
  @Get()
  async listSegments(
    @Query() dto: ListSegmentsDto,
  ): Promise<SegmentListResponseDto> {
    const { items, total } = await this.segmentService.listSegments({
      usageType: dto.usageType,
      isEnabled: dto.isEnabled,
      limit: dto.limit,
      offset: dto.offset,
    });

    return {
      items: items.map(SegmentResponseDto.fromEntity),
      total,
    };
  }

  /**
   * 获取人群包详情
   */
  @Get(':id')
  async getSegment(@Param('id') id: string): Promise<SegmentResponseDto> {
    const segment = await this.segmentService.getSegment(id);
    if (!segment) {
      throw new NotFoundException(`Segment not found: ${id}`);
    }
    return SegmentResponseDto.fromEntity(segment);
  }

  /**
   * 更新人群包
   */
  @Put(':id')
  async updateSegment(
    @Param('id') id: string,
    @Body() dto: UpdateSegmentDto,
  ): Promise<SegmentResponseDto> {
    try {
      const updated = await this.segmentService.updateSegment(id, dto);
      return SegmentResponseDto.fromEntity(updated);
    } catch (error) {
      if (error instanceof Error && error.message.includes('not found')) {
        throw new NotFoundException(error.message);
      }
      throw error;
    }
  }

  /**
   * 删除人群包
   */
  @Delete(':id')
  @HttpCode(HttpStatus.NO_CONTENT)
  async deleteSegment(@Param('id') id: string): Promise<void> {
    await this.segmentService.deleteSegment(id);
  }

  /**
   * 测试用户是否匹配人群包
   */
  @Post(':id/test')
  async testSegment(
    @Param('id') id: string,
    @Body() dto: TestSegmentDto,
  ): Promise<SegmentTestResultDto> {
    const segment = await this.segmentService.getSegment(id);
    if (!segment) {
      throw new NotFoundException(`Segment not found: ${id}`);
    }

    const matched = await this.segmentService.evaluateUser(
      dto.accountSequence,
      id,
    );

    return {
      segmentId: id,
      segmentName: segment.name,
      accountSequence: dto.accountSequence,
      matched,
    };
  }

  /**
   * 预估人群包用户数
   */
  @Post(':id/estimate')
  async estimateSegment(
    @Param('id') id: string,
  ): Promise<SegmentEstimateResultDto> {
    const segment = await this.segmentService.getSegment(id);
    if (!segment) {
      throw new NotFoundException(`Segment not found: ${id}`);
    }

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

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

  /**
   * 预估条件匹配用户数（不保存人群包）
   */
  @Post('estimate')
  async estimateConditions(
    @Body() dto: EstimateSegmentDto,
  ): Promise<SegmentEstimateResultDto> {
    if (!AudienceSegmentEntity.validateConditions(dto.conditions)) {
      throw new BadRequestException('Invalid segment conditions format');
    }

    // 创建临时人群包进行评估
    const tempSegment = await this.segmentService.createSegment({
      name: '__temp_estimate__',
      conditions: dto.conditions,
      createdBy: 'system',
    });

    try {
      const { accountSequences, total } =
        await this.segmentService.findMatchingUsers(tempSegment.id, {
          limit: 10,
        });

      return {
        estimatedUsers: total,
        sampleUsers: accountSequences,
      };
    } finally {
      // 删除临时人群包
      await this.segmentService.deleteSegment(tempSegment.id);
    }
  }

  /**
   * 获取人群包内的用户列表
   */
  @Get(':id/users')
  async getSegmentUsers(
    @Param('id') id: string,
    @Query() dto: GetSegmentUsersDto,
  ): Promise<SegmentUsersResponseDto> {
    const segment = await this.segmentService.getSegment(id);
    if (!segment) {
      throw new NotFoundException(`Segment not found: ${id}`);
    }

    const { accountSequences, total } =
      await this.segmentService.findMatchingUsers(id, {
        limit: dto.limit ?? 50,
        offset: dto.offset ?? 0,
      });

    return {
      segmentId: id,
      users: accountSequences,
      total,
    };
  }

  /**
   * 刷新人群包预估用户数
   */
  @Post(':id/refresh')
  async refreshEstimate(
    @Param('id') id: string,
  ): Promise<{ estimatedUsers: number }> {
    const segment = await this.segmentService.getSegment(id);
    if (!segment) {
      throw new NotFoundException(`Segment not found: ${id}`);
    }

    const count = await this.segmentService.calculateEstimatedUsers(id);
    return { estimatedUsers: count };
  }

  /**
   * 刷新所有人群包的预估用户数
   */
  @Post('refresh-all')
  async refreshAllEstimates(): Promise<{ success: boolean }> {
    await this.segmentService.recalculateAllEstimatedUsers();
    return { success: true };
  }

  /**
   * 获取用户匹配的所有人群包
   */
  @Get('user/:accountSequence')
  async getUserSegments(
    @Param('accountSequence') accountSequence: string,
    @Query('usageType') usageType?: string,
  ): Promise<UserSegmentsResponseDto> {
    const results = await this.segmentService.evaluateUserSegments(
      accountSequence,
      usageType as any,
    );

    return {
      accountSequence,
      segments: results.map((r) => ({
        segmentId: r.segmentId,
        segmentName: r.segmentName,
        matched: r.matched,
      })),
    };
  }
}
