import {
  Body,
  Controller,
  Delete,
  Get,
  Header,
  Param,
  Post,
  Put,
  Query,
  Res,
  UploadedFile,
  UseGuards,
  UseInterceptors,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { Response } from 'express';
import { ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger';
import { plainToInstance } from 'class-transformer';
import { AdminJwtAuthGuard } from '../auth/admin/jwt.guard';
import { Roles } from '../auth/admin/roles.decorator';
import { RolesGuard } from '../auth/admin/roles.guard';
import {
  CreateMedicationStandardDto,
  CreateMedicationStandardResponseDto,
  DeleteMedicationStandardDto,
  GetCategoryListResponseDto,
  GetMedicationStandardDetailResponseDto,
  GetMedicationStandardFlatDto,
  GetMedicationStandardFlatResponseDto,
  UpdateMedicationStandardDto,
} from './medication-standard.dto';
import { MedicationStandardService } from './medication-standard.service';

@ApiTags('[관리자] 투약기준관리')
@UseGuards(AdminJwtAuthGuard, RolesGuard)
@Roles('admin')
@Controller('admin/medication-standard')
export class MedicationStandardController {
  constructor(
    private medicationStandardService: MedicationStandardService,
  ) {}

  // ==================== A. 대분류 (Category) API ====================

  @ApiOperation({
    summary: '대분류 목록 조회',
    description: '투약 대분류 전체 목록을 조회합니다.',
  })
  @Get('categories')
  @ApiOkResponse({ type: GetCategoryListResponseDto })
  async getCategoryList() {
    const data = await this.medicationStandardService.getCategoryList();
    return plainToInstance(GetCategoryListResponseDto, data, {
      excludeExtraneousValues: true,
    });
  }

  @ApiOperation({
    summary: '대분류 생성',
    description: '새로운 투약 대분류를 생성합니다.',
  })
  @Post('categories')
  async createCategory(@Body() body: { mcName: string }) {
    return await this.medicationStandardService.createCategory(body.mcName);
  }

  // ==================== B. 중분류 (Standard) API ====================

  @ApiOperation({
    summary: '중분류 목록 조회 (페이지네이션 + 필터)',
    description: `
    투약 중분류 목록을 페이지네이션과 필터로 조회합니다.

    필터 옵션:
    - categoryId: 대분류 ID로 필터링
    - searchKey: 검색 키 (mcName, mscCode, mscName)
    - searchText: 검색어
    - startDate: 시작일 (YYYY-MM-DD)
    - endDate: 종료일 (YYYY-MM-DD)
    - sortBy: 정렬 기준
    - sortOrder: 정렬 방향 (ASC, DESC)
    `,
  })
  @Get('flat')
  @ApiOkResponse({ type: GetMedicationStandardFlatResponseDto })
  async getStandardFlatList(@Query() query: GetMedicationStandardFlatDto) {
    const data = await this.medicationStandardService.getStandardFlatList(query);
    return plainToInstance(GetMedicationStandardFlatResponseDto, data, {
      excludeExtraneousValues: true,
    });
  }

  // ==================== 엑셀 기능 (동적 라우트보다 먼저 선언) ====================
  @Get('excel')
  @ApiOperation({ summary: '투약기준 목록 엑셀 다운로드' })
  @Header(
    'Content-Type',
    'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  )
  @Header(
    'Content-Disposition',
    `attachment;filename*=utf-8''${encodeURIComponent('투약로그관리')}.xlsx`,
  )
  async downloadExcel(
    @Query() query: GetMedicationStandardFlatDto,
    @Res({ passthrough: true }) res: Response,
  ) {
    await this.medicationStandardService.downloadExcel(query, res);
    return;
  }

  @Get('upload-form')
  @ApiOperation({ summary: '엑셀 업로드 양식 다운로드' })
  @Header(
    'Content-Type',
    'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  )
  @Header(
    'Content-Disposition',
    `attachment;filename*=utf-8''${encodeURIComponent('투약로그관리_업로드양식')}.xlsx`,
  )
  async downloadUploadForm(@Res({ passthrough: true }) res: Response) {
    await this.medicationStandardService.downloadUploadForm(res);
    return;
  }

  @ApiOperation({
    summary: '중분류 상세 조회',
    description: 'ID로 중분류 상세 정보를 조회합니다.',
  })
  @Get(':mscId')
  @ApiOkResponse({ type: GetMedicationStandardDetailResponseDto })
  async getStandardDetail(@Param('mscId') mscId: number) {
    const data = await this.medicationStandardService.getStandardDetail(mscId);
    return plainToInstance(GetMedicationStandardDetailResponseDto, data, {
      excludeExtraneousValues: true,
    });
  }

  @ApiOperation({
    summary: '중분류 등록',
    description: '새로운 투약 중분류를 등록합니다.',
  })
  @Post()
  @ApiOkResponse({ type: CreateMedicationStandardResponseDto })
  async createStandard(@Body() body: CreateMedicationStandardDto) {
    const data = await this.medicationStandardService.createStandard(body);
    return plainToInstance(CreateMedicationStandardResponseDto, data, {
      excludeExtraneousValues: true,
    });
  }

  @ApiOperation({
    summary: '중분류 수정',
    description: 'ID로 중분류 정보를 수정합니다.',
  })
  @Put(':mscId')
  async updateStandard(
    @Param('mscId') mscId: number,
    @Body() body: UpdateMedicationStandardDto,
  ) {
    await this.medicationStandardService.updateStandard(mscId, body);
    return { success: true };
  }

  @ApiOperation({
    summary: '중분류 삭제 (일괄)',
    description: '선택한 중분류를 일괄 삭제합니다.',
  })
  @Delete()
  async deleteStandards(@Body() body: DeleteMedicationStandardDto) {
    await this.medicationStandardService.deleteStandards(body);
    return { success: true };
  }

  @Post('upload')
  @ApiOperation({ summary: '엑셀 일괄 업로드' })
  @UseInterceptors(FileInterceptor('file'))
  async uploadExcel(@UploadedFile() file: Express.Multer.File) {
    console.log('Controller - 파일 수신:', file ? file.originalname : 'NO FILE');
    console.log('Controller - 파일 정보:', {
      fieldname: file?.fieldname,
      originalname: file?.originalname,
      mimetype: file?.mimetype,
      size: file?.size
    });
    return await this.medicationStandardService.uploadExcel(file);
  }

  @Post('recovery')
  @ApiOperation({ summary: '이전 데이터 복구' })
  async recovery() {
    return await this.medicationStandardService.recovery();
  }
}
