import {
  Controller,
  Post,
  Get,
  Put,
  Body,
  Param,
  UseGuards,
  Query,
  BadRequestException,
  UploadedFile,
  UseInterceptors,
} from '@nestjs/common';
import { BiometricService } from './biometric.service';
import { JwtAuthGuard } from 'src/auth/jwt-auth.guard';
import { Roles } from 'common/guards/decorators/roles.decorator';
import { RolesGuard } from 'common/guards/roles.guard';
import { RegisterDeviceDto } from 'src/auth/dto/register-device.dto';
import { UserRole } from 'common/enums/user.enum';
import { LinkDeviceDto } from './dto/link-device.dto';
import { SyncLogsDto } from './dto/register-device.dto';
import { FileInterceptor } from '@nestjs/platform-express';
import { BiometricExcelService } from './biometric-excel.service';
import { ApiBearerAuth, ApiParam, ApiTags } from '@nestjs/swagger';
import { ApiConsumes, ApiBody } from '@nestjs/swagger';
import { UploadExcelDto } from './dto/upload-excel.dto';

@ApiTags('Biometric')
@ApiBearerAuth('access-token')
@Controller('biometric')
@UseGuards(JwtAuthGuard)
export class BiometricController {
  constructor(
    private readonly biometricService: BiometricService,
    private readonly excelService: BiometricExcelService,
  ) {}

  @Post('devices')
  @Roles(UserRole.HR_ADMIN)
  @UseGuards(RolesGuard)
  registerDevice(@Body() registerDeviceDto: RegisterDeviceDto) {
    return this.biometricService.registerDevice(
      registerDeviceDto.deviceId,
      registerDeviceDto.name,
      registerDeviceDto.ipAddress,
    );
  }

  @Get('devices')
  @Roles(UserRole.HR_ADMIN)
  @UseGuards(RolesGuard)
  getDevices() {
    return this.biometricService.getDevices();
  }

  @Put('devices/:deviceId/status')
  @Roles(UserRole.HR_ADMIN)
  @UseGuards(RolesGuard)
  @ApiParam({
    name: 'deviceId',
    description: 'The unique ID of the biometric device',
  })
  updateDeviceStatus(
    @Param('deviceId') deviceId: string,
    @Body('isActive') isActive: boolean,
  ) {
    return this.biometricService.updateDeviceStatus(deviceId, isActive);
  }

  @Post('link')
  @Roles(UserRole.HR_ADMIN)
  @UseGuards(RolesGuard)
  linkEmployee(@Body() linkDeviceDto: LinkDeviceDto) {
    return this.biometricService.linkEmployeeToDevice(
      linkDeviceDto.userId,
      linkDeviceDto.biometricDeviceId,
    );
  }

  @Post('sync')
  @Roles(UserRole.HR_ADMIN)
  @UseGuards(RolesGuard)
  syncLogs(@Body() syncLogsDto: SyncLogsDto) {
    return this.biometricService.syncLogs(syncLogsDto);
  }

  @Post('manual')
  @Roles(UserRole.HR_ADMIN)
  @UseGuards(RolesGuard)
  manualAddLog(
    @Body() manualDto: { userId: number; timestamp: Date; type: string },
  ) {
    return this.biometricService.manualAddLog(
      manualDto.userId,
      manualDto.timestamp,
      manualDto.type,
    );
  }

  @Get('logs/:userId')
  @ApiParam({
    name: 'userId',
    description: 'The ID of the user to fetch biometric logs for',
  })
  getUserLogs(
    @Param('userId') userId: number,
    @Query('start') start?: string,
    @Query('end') end?: string,
  ) {
    const startDate = start ? new Date(start) : undefined;
    const endDate = end ? new Date(end) : undefined;
    return this.biometricService.getUserBiometricLogs(
      userId,
      startDate,
      endDate,
    );
  }

  @Post('upload/excel')
  @Roles(UserRole.HR_ADMIN)
  @UseGuards(RolesGuard)
  @UseInterceptors(FileInterceptor('file'))
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    description: 'Excel file containing biometric logs',
    type: UploadExcelDto,
  })
  async uploadExcel(@UploadedFile() file: Express.Multer.File) {
    if (!file) {
      throw new BadRequestException('No file uploaded');
    }

    const logs = await this.excelService.parseExcel(file.buffer);
    if (logs.length === 0) {
      throw new BadRequestException('No valid logs found in Excel file');
    }

    await this.excelService.saveLogs(logs);

    return {
      message: 'Attendance logs saved successfully',
      count: logs.length,
    };
  }
}
