import {
  Controller,
  Get,
  Post,
  Put,
  Patch,
  Body,
  Param,
  Query,
  ParseUUIDPipe,
  HttpCode,
} from '@nestjs/common';
import { ResultService } from '../services/result.service';
import {
  QueryResultDto,
  QueryMyResultsDto,
  CalculateResultsDto,
  ExportResultsDto,
  UpdateResultRemarksDto,
  AppealResultDto,
  ResolveAppealDto,
  SaveOverallCommentDto,
} from '../dto/result.dto';
import { CurrentUser } from '@common/decorators/current-user.decorator';
import { RequirePermissions } from '@common/decorators/permissions.decorator';
import { PERFORMANCE_PERMISSIONS } from '../constants/permissions';
import { BusinessException } from '@common/exceptions/business.exception';
import { PERFORMANCE_ERROR_CODES } from '../constants/error-codes';
import { toPaginatedResponse } from '@common/utils/pagination';

/**
 * 绩效结果控制器
 * 路由前缀: /api/v1/performance/results
 */
@Controller('performance/results')
export class ResultController {
  constructor(private readonly resultService: ResultService) {}

  @Get()
  @RequirePermissions(PERFORMANCE_PERMISSIONS.RESULT_VIEW)
  async findByCycle(@Query() query: QueryResultDto) {
    const { cycleId, ...rest } = query;
    const result = await this.resultService.findByCycle(cycleId, rest);
    return {
      items: result.items,
      pagination: result.pagination,
      summary: result.summary,
    };
  }

  @Get('my')
  @RequirePermissions(PERFORMANCE_PERMISSIONS.RESULT_VIEW_OWN)
  async findMyResults(
    @CurrentUser('userId') userId: string,
    @Query() query: QueryMyResultsDto,
  ) {
    const result = await this.resultService.findMyResults(userId, query);
    return toPaginatedResponse(result);
  }

  @Get('my/:cycleId')
  @RequirePermissions(PERFORMANCE_PERMISSIONS.RESULT_VIEW_OWN)
  async findMyResultByCycle(
    @CurrentUser('userId') userId: string,
    @Param('cycleId', ParseUUIDPipe) cycleId: string,
  ) {
    return this.resultService.findMyResultByCycle(userId, cycleId);
  }

  /**
   * 获取整体评语
   */
  @Get('overall-comment')
  @RequirePermissions(PERFORMANCE_PERMISSIONS.KPI_SELF_EVALUATE)
  @HttpCode(200)
  async getOverallComment(
    @Query('cycleId', ParseUUIDPipe) cycleId: string,
    @Query('employeeId', ParseUUIDPipe) employeeId: string,
    @CurrentUser('userId') userId: string,
  ) {
    return this.resultService.getOverallComment(cycleId, employeeId, userId);
  }

  /**
   * 保存整体评语（upsert）
   */
  @Patch('overall-comment')
  @RequirePermissions(PERFORMANCE_PERMISSIONS.KPI_SELF_EVALUATE)
  @HttpCode(200)
  async saveOverallComment(
    @Body() dto: SaveOverallCommentDto,
    @CurrentUser('userId') userId: string,
  ) {
    return this.resultService.saveOverallComment(dto, userId);
  }

  @Get(':id')
  @RequirePermissions(PERFORMANCE_PERMISSIONS.RESULT_VIEW)
  async findById(@Param('id', ParseUUIDPipe) id: string) {
    return this.resultService.findById(id);
  }

  @Post('calculate')
  @RequirePermissions(PERFORMANCE_PERMISSIONS.RESULT_CALCULATE)
  @HttpCode(200)
  async calculateResults(@Body() dto: CalculateResultsDto) {
    const result = await this.resultService.calculateResults(dto.cycleId, {
      weights: dto.weights,
      employeeIds: dto.employeeIds,
    });
    return { calculated: result.calculated, failed: result.failed };
  }

  @Post('export')
  @RequirePermissions(PERFORMANCE_PERMISSIONS.REPORT_EXPORT)
  @HttpCode(200)
  async exportResults(@Body() dto: ExportResultsDto) {
    return this.resultService.exportResults({
      cycleId: dto.cycleId,
      format: dto.format || 'xlsx',
      fields: dto.fields,
    });
  }

  @Post('my/:id/viewed')
  @RequirePermissions(PERFORMANCE_PERMISSIONS.RESULT_VIEW_OWN)
  @HttpCode(200)
  async markAsViewed(
    @Param('id', ParseUUIDPipe) id: string,
    @CurrentUser('userId') currentUserId: string,
  ) {
    const result = await this.resultService.markAsViewed(id, currentUserId);
    return {
      id: result.id,
      viewedByEmployee: result.viewedByEmployee,
      viewedAt: result.viewedAt,
    };
  }

  /**
   * 员工确认结果
   */
  @Post('my/:id/confirm')
  @RequirePermissions(PERFORMANCE_PERMISSIONS.RESULT_VIEW_OWN)
  @HttpCode(200)
  async confirmResult(
    @Param('id', ParseUUIDPipe) id: string,
    @CurrentUser('userId') userId: string,
  ) {
    const result = await this.resultService.confirmResult(id, userId);
    return {
      id: result.id,
      confirmStatus: result.confirmStatus,
      confirmedAt: result.updatedAt,
    };
  }

  /**
   * 员工申诉
   */
  @Post('my/:id/appeal')
  @RequirePermissions(PERFORMANCE_PERMISSIONS.RESULT_VIEW_OWN)
  @HttpCode(200)
  async appealResult(
    @Param('id', ParseUUIDPipe) id: string,
    @Body() dto: AppealResultDto,
    @CurrentUser('userId') userId: string,
  ) {
    const result = await this.resultService.appealResult(id, userId, dto.reason);
    return {
      id: result.id,
      confirmStatus: result.confirmStatus,
      appealedAt: result.updatedAt,
    };
  }

  /**
   * HR 处理申诉
   */
  @Post(':id/resolve-appeal')
  @RequirePermissions(PERFORMANCE_PERMISSIONS.RESULT_PUBLISH)
  @HttpCode(200)
  async resolveAppeal(
    @Param('id', ParseUUIDPipe) id: string,
    @Body() dto: ResolveAppealDto,
  ) {
    const result = await this.resultService.resolveAppeal(id, dto);
    return {
      id: result.id,
      confirmStatus: result.confirmStatus,
      appealResponse: result.appealResponse,
      appealResolvedAt: result.appealResolvedAt,
      gradeCode: result.gradeCode,
      totalScore: result.totalScore,
    };
  }

  @Put(':id')
  @RequirePermissions(PERFORMANCE_PERMISSIONS.RESULT_PUBLISH)
  async updateRemarks(
    @Param('id', ParseUUIDPipe) id: string,
    @Body() dto: UpdateResultRemarksDto,
  ) {
    if (dto.remarks === undefined) {
      throw new BusinessException(
        PERFORMANCE_ERROR_CODES.COMMON_VALIDATION_FAILED.message,
        PERFORMANCE_ERROR_CODES.COMMON_VALIDATION_FAILED.code,
        PERFORMANCE_ERROR_CODES.COMMON_VALIDATION_FAILED.httpStatus,
        { field: 'remarks' },
      );
    }
    await this.resultService.addRemarks(id, dto.remarks);
    return this.resultService.findById(id);
  }
}
