import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Body,
  Param,
  Query,
  UseInterceptors,
  UploadedFile,
  HttpCode,
  HttpStatus,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import {
  ApiTags,
  ApiOperation,
  ApiResponse,
  ApiBearerAuth,
  ApiParam,
  ApiConsumes,
  ApiBody,
} from '@nestjs/swagger';
import { diskStorage } from 'multer';
import { extname } from 'path';
import { v4 as uuidv4 } from 'uuid';
import { S3PlanningService } from './s3-planning.service';
import {
  CreateS3PlanDto,
  AddS3CategoryDto,
  UpdateS3StatusDto,
  UpdateS3CategoryDto,
  UpdateS3PlanDto,
  QueryS3PlansDto,
  QueryS3DashboardDto,
  QueryS3StatisticsDto,
} from './dto';
import { RequirePermissions } from '../../../auth/permissions/permissions.decorator';
import { Permission } from '../../../auth/permissions/permissions.enum';
import { AuditLog } from '../../audit/audit.interceptor';
import { CurrentUser } from '../../../auth/decorators/current-user.decorator';

/**
 * Multer storage configuration for S3 photo uploads
 */
const s3Storage = diskStorage({
  destination: './uploads/s3',
  filename: (req, file, callback) => {
    const uniqueSuffix = uuidv4();
    callback(null, `${uniqueSuffix}${extname(file.originalname)}`);
  },
});

/**
 * File filter for image uploads
 */
const imageFileFilter = (
  req: Express.Request,
  file: Express.Multer.File,
  callback: (error: Error | null, acceptFile: boolean) => void,
) => {
  if (!file.originalname.match(/\.(jpg|jpeg|png|gif|webp)$/i)) {
    return callback(new Error('Only image files are allowed!'), false);
  }
  callback(null, true);
};

@ApiTags('lean/s3-planning')
@ApiBearerAuth('JWT-auth')
@Controller('lean/s3')
export class S3PlanningController {
  constructor(private readonly s3PlanningService: S3PlanningService) {}

  // ==================== PLANS ====================

  @Post('plans')
  @RequirePermissions(Permission.S3_CREATE)
  @AuditLog('S3Plan', 'CREATE')
  @ApiOperation({ summary: 'Create a new 3S plan' })
  @ApiResponse({ status: 201, description: 'Plan created successfully' })
  @ApiResponse({ status: 400, description: 'Bad request' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  @ApiResponse({ status: 403, description: 'Forbidden' })
  @ApiResponse({ status: 409, description: 'Plan already exists' })
  create(@Body() createDto: CreateS3PlanDto, @CurrentUser('sub') userId: string) {
    return this.s3PlanningService.createPlan(createDto, userId);
  }

  @Get('plans')
  @RequirePermissions(Permission.S3_VIEW)
  @ApiOperation({ summary: 'Get all 3S plans with filtering and pagination' })
  @ApiResponse({ status: 200, description: 'List of plans' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  findAll(@Query() query: QueryS3PlansDto) {
    return this.s3PlanningService.findAll(query);
  }

  @Get('plans/:id')
  @RequirePermissions(Permission.S3_VIEW)
  @ApiOperation({ summary: 'Get a single 3S plan by ID' })
  @ApiParam({ name: 'id', description: 'Plan ID' })
  @ApiResponse({ status: 200, description: 'Plan found' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  @ApiResponse({ status: 404, description: 'Plan not found' })
  findOne(@Param('id') id: string) {
    return this.s3PlanningService.findOne(id);
  }

  @Put('plans/:id')
  @RequirePermissions(Permission.S3_UPDATE)
  @AuditLog('S3Plan', 'UPDATE')
  @ApiOperation({ summary: 'Update a 3S plan' })
  @ApiParam({ name: 'id', description: 'Plan ID' })
  @ApiResponse({ status: 200, description: 'Plan updated successfully' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  @ApiResponse({ status: 403, description: 'Forbidden' })
  @ApiResponse({ status: 404, description: 'Plan not found' })
  update(@Param('id') id: string, @Body() updateDto: UpdateS3PlanDto) {
    return this.s3PlanningService.updatePlan(id, updateDto);
  }

  @Delete('plans/:id')
  @RequirePermissions(Permission.S3_DELETE)
  @AuditLog('S3Plan', 'DELETE')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Delete a 3S plan' })
  @ApiParam({ name: 'id', description: 'Plan ID' })
  @ApiResponse({ status: 200, description: 'Plan deleted successfully' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  @ApiResponse({ status: 403, description: 'Forbidden' })
  @ApiResponse({ status: 404, description: 'Plan not found' })
  remove(@Param('id') id: string) {
    return this.s3PlanningService.deletePlan(id);
  }

  // ==================== CATEGORIES ====================

  @Get('plans/:planId/categories')
  @RequirePermissions(Permission.S3_VIEW)
  @ApiOperation({ summary: 'Get categories for a plan' })
  @ApiParam({ name: 'planId', description: 'Plan ID' })
  @ApiResponse({ status: 200, description: 'List of categories' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  @ApiResponse({ status: 404, description: 'Plan not found' })
  getCategories(@Param('planId') planId: string) {
    return this.s3PlanningService.getCategories(planId);
  }

  @Post('plans/:planId/categories')
  @RequirePermissions(Permission.S3_UPDATE)
  @AuditLog('S3Category', 'CREATE')
  @ApiOperation({ summary: 'Add a category to a plan' })
  @ApiParam({ name: 'planId', description: 'Plan ID' })
  @ApiResponse({ status: 201, description: 'Category created successfully' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  @ApiResponse({ status: 403, description: 'Forbidden' })
  @ApiResponse({ status: 404, description: 'Plan not found' })
  addCategory(
    @Param('planId') planId: string,
    @Body() addDto: AddS3CategoryDto,
  ) {
    return this.s3PlanningService.addCategory(planId, addDto);
  }

  @Put('categories/:id')
  @RequirePermissions(Permission.S3_UPDATE)
  @AuditLog('S3Category', 'UPDATE')
  @ApiOperation({ summary: 'Update a category' })
  @ApiParam({ name: 'id', description: 'Category ID' })
  @ApiResponse({ status: 200, description: 'Category updated successfully' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  @ApiResponse({ status: 403, description: 'Forbidden' })
  @ApiResponse({ status: 404, description: 'Category not found' })
  updateCategory(
    @Param('id') id: string,
    @Body() updateDto: UpdateS3CategoryDto,
  ) {
    return this.s3PlanningService.updateCategory(id, updateDto);
  }

  @Delete('categories/:id')
  @RequirePermissions(Permission.S3_DELETE)
  @AuditLog('S3Category', 'DELETE')
  @HttpCode(HttpStatus.OK)
  @ApiOperation({ summary: 'Delete a category' })
  @ApiParam({ name: 'id', description: 'Category ID' })
  @ApiResponse({ status: 200, description: 'Category deleted successfully' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  @ApiResponse({ status: 403, description: 'Forbidden' })
  @ApiResponse({ status: 404, description: 'Category not found' })
  deleteCategory(@Param('id') id: string) {
    return this.s3PlanningService.deleteCategory(id);
  }

  // ==================== STATUS ====================

  @Put('status/:id')
  @RequirePermissions(Permission.S3_UPDATE)
  @AuditLog('S3Status', 'UPDATE')
  @ApiOperation({ summary: 'Update a status entry' })
  @ApiParam({ name: 'id', description: 'Status ID' })
  @ApiResponse({ status: 200, description: 'Status updated successfully' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  @ApiResponse({ status: 403, description: 'Forbidden' })
  @ApiResponse({ status: 404, description: 'Status not found' })
  updateStatus(
    @Param('id') id: string,
    @Body() updateDto: UpdateS3StatusDto,
    @CurrentUser('sub') userId: string,
  ) {
    return this.s3PlanningService.updateStatus(id, updateDto, userId);
  }

  @Post('status/:id/photo')
  @RequirePermissions(Permission.S3_UPDATE)
  @UseInterceptors(
    FileInterceptor('photo', {
      storage: s3Storage,
      fileFilter: imageFileFilter,
      limits: { fileSize: 5 * 1024 * 1024 }, // 5MB max
    }),
  )
  @ApiOperation({ summary: 'Upload a photo for a status entry' })
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      properties: {
        photo: {
          type: 'string',
          format: 'binary',
          description: 'Image file (jpg, png, gif, webp)',
        },
      },
    },
  })
  @ApiParam({ name: 'id', description: 'Status ID' })
  @ApiResponse({ status: 200, description: 'Photo uploaded successfully' })
  @ApiResponse({ status: 400, description: 'Invalid file' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  @ApiResponse({ status: 404, description: 'Status not found' })
  uploadPhoto(
    @Param('id') id: string,
    @UploadedFile() file: Express.Multer.File,
    @CurrentUser('sub') userId: string,
  ) {
    const photoPath = `/uploads/s3/${file.filename}`;
    return this.s3PlanningService.uploadStatusPhoto(id, photoPath, userId);
  }

  // ==================== DASHBOARD & STATISTICS ====================

  @Get('dashboard/:departmentId')
  @RequirePermissions(Permission.S3_VIEW)
  @ApiOperation({ summary: 'Get dashboard data for a department' })
  @ApiParam({ name: 'departmentId', description: 'Department ID' })
  @ApiResponse({ status: 200, description: 'Dashboard data' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  @ApiResponse({ status: 404, description: 'Department not found' })
  getDashboard(
    @Param('departmentId') departmentId: string,
    @Query() query: QueryS3DashboardDto,
  ) {
    return this.s3PlanningService.getDashboard(departmentId, query);
  }

  @Get('statistics')
  @RequirePermissions(Permission.S3_VIEW)
  @ApiOperation({ summary: 'Get overall 3S statistics' })
  @ApiResponse({ status: 200, description: 'Statistics data' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  getStatistics(@Query() query: QueryS3StatisticsDto) {
    return this.s3PlanningService.getStatistics(query);
  }
}
