import {
  Controller, Get, Post, Patch, Delete, Body, Param, Query,
  ParseIntPipe, Req, Logger,
  UploadedFiles, UseInterceptors,
} from '@nestjs/common';
import { FileFieldsInterceptor, FilesInterceptor } from '@nestjs/platform-express';
import { diskStorage } from 'multer';
import * as fs from 'fs';
import * as nodePath from 'path';

import { AuditRequestsService } from './services/audit-requests.service';
import { CreateAuditRequestDto } from './dto/create-audit-request.dto';
import { UpdateAuditRequestDto } from './dto/update-audit-request.dto';
import { ScheduleAuditRequestDto } from './dto/schedule-audit-request.dto';
import { RejectAuditRequestDto } from './dto/reject-audit-request.dto';
import { CancelAuditRequestDto } from './dto/cancel-audit-request.dto';
import { ListAuditRequestsQueryDto } from './dto/list-audit-requests.dto';
import { CreateBatchAuditRequestDto } from './dto/create-batch-audit-request.dto';
@Controller('audit-requests')
export class AuditRequestsController {
  private readonly logger = new Logger('AuditRequestsController');

  constructor(private readonly service: AuditRequestsService) { }

  // ── Helper: extract current user id from JWT — same as audit-schedules ─
  private getCurrentUserId(req: Request): number {
    const user = (req as any).user;
    const id = user?.id ?? user?.userId ?? user?.sub;
    if (id === undefined || id === null) {
      throw new Error(
        'User id not found on request.user (JwtAuthGuard / strategy issue?)',
      );
    }
    return Number(id);
  }
  // POST /audit-requests/:id/upload-documents
  @Post(':id/upload-documents')
  @UseInterceptors(
    FileFieldsInterceptor(
      [
        { name: 'trade_license', maxCount: 5 },
        { name: 'previous_certificate', maxCount: 5 },
        { name: 'files', maxCount: 10 },
      ],
      {
        storage: diskStorage({
          destination: (req, _file, cb) => {
            const reqId = req.params.id;
            const dir = nodePath.join(process.cwd(), 'uploads', 'audit-requests', String(reqId));
            if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
            cb(null, dir);
          },
          filename: (_req, file, cb) => {
            const ts = Date.now();
            const safe = file.originalname.replace(/[^a-zA-Z0-9._-]/g, '_');
            cb(null, `${ts}_${safe}`);
          },
        }),
        limits: {
          fileSize: 500 * 1024 * 1024,
        },
      },
    ),
  )
  async uploadDocuments(
    @Param('id', ParseIntPipe) id: number,
    @UploadedFiles() files: { trade_license?: Express.Multer.File[]; previous_certificate?: Express.Multer.File[]; files?: Express.Multer.File[] },
    @Req() req: Request,
  ) {
    const userId = this.getCurrentUserId(req);
    const totalFiles = (files.trade_license?.length || 0) + (files.previous_certificate?.length || 0) + (files.files?.length || 0);
    this.logger.log(`POST /audit-requests/${id}/upload-documents — user=${userId}, files=${totalFiles}`);
    return this.service.uploadDocuments(id, files, userId);
  }
  // ═══════════════════ LIST + ANALYTICS ═══════════════════

  // GET /audit-requests
  @Get()
  list(@Query() q: ListAuditRequestsQueryDto, @Req() req: Request) {
    const userId = this.getCurrentUserId(req);
    return this.service.findAll(q, userId);
  }

  // GET /audit-requests/analytics
  @Get('analytics')
  analytics(@Req() req: Request) {
    const userId = this.getCurrentUserId(req);
    return this.service.getAnalytics(userId);
  }

  // GET /audit-requests/available-slots
  @Get('available-slots')
  availableSlots() {
    return this.service.getAvailableSlots();
  }

  // GET /audit-requests/:id
  @Get(':id')
  findOne(@Param('id', ParseIntPipe) id: number) {
    return this.service.findOne(id);
  }

  // ═══════════════════ MARKETING ACTIONS ═══════════════════

  // POST /audit-requests
  @Post()
  async create(@Body() dto: CreateAuditRequestDto, @Req() req: Request) {
    const userId = this.getCurrentUserId(req);
    this.logger.log(
      `POST /audit-requests — user=${userId}, company=${dto.company_id}, date=${dto.proposed_date}`,
    );
    try {
      return await this.service.create(dto, userId);
    } catch (err: any) {
      this.logger.error(`POST /audit-requests failed: ${err.message}`);
      throw err;
    }
  }
  // POST /audit-requests/batch — create one request per client
  @Post('batch')
  async createBatch(
    @Body() dto: CreateBatchAuditRequestDto,
    @Req() req: Request,
  ) {
    const userId = this.getCurrentUserId(req);
    this.logger.log(
      `POST /audit-requests/batch — user=${userId}, clients=${dto.clients?.length ?? 0}`,
    );
    try {
      return await this.service.createBatch(dto, userId);
    } catch (err: any) {
      this.logger.error(`POST /audit-requests/batch failed: ${err.message}`);
      throw err;
    }
  }
  // PATCH /audit-requests/:id
  @Patch(':id')
  update(
    @Param('id', ParseIntPipe) id: number,
    @Body() dto: UpdateAuditRequestDto,
    @Req() req: Request,
  ) {
    const userId = this.getCurrentUserId(req);
    this.logger.log(`PATCH /audit-requests/${id} — user=${userId}`);
    return this.service.update(id, dto, userId);
  }

   // POST /audit-requests/proceed-to-inquiry/batch
  @Post('proceed-to-inquiry/batch')
  proceedBatchToInquiry(@Body() dto: any, @Req() req: Request) {
    const userId = this.getCurrentUserId(req);
    return this.service.proceedBatchToInquiry(dto, userId);
  }

  // POST /audit-requests/:id/proceed-to-inquiry
  @Post(':id/proceed-to-inquiry')
  proceedToInquiry(
    @Param('id', ParseIntPipe) id: number,
    @Body() dto: any,
    @Req() req: Request,
  ) {
    const userId = this.getCurrentUserId(req);
    return this.service.proceedToInquiry(id, dto, userId);
  }

  // PATCH /audit-requests/:id/cancel
  @Patch(':id/cancel')
  cancel(
    @Param('id', ParseIntPipe) id: number,
    @Body() dto: CancelAuditRequestDto,
    @Req() req: Request,
  ) {
    const userId = this.getCurrentUserId(req);
    this.logger.log(
      `PATCH /audit-requests/${id}/cancel — user=${userId}, reason=${dto.cancellation_reason}`,
    );
    return this.service.cancel(id, dto, userId);
  }

  // ═══════════════════ COORDINATOR ACTIONS ═══════════════════

  // PATCH /audit-requests/:id/review
  // Coordinator opens the detail — auto-transitions to UNDER_REVIEW
  @Patch(':id/review')
  markUnderReview(
    @Param('id', ParseIntPipe) id: number,
    @Req() req: Request,
  ) {
    const userId = this.getCurrentUserId(req);
    this.logger.log(`PATCH /audit-requests/${id}/review — user=${userId}`);
    return this.service.markUnderReview(id, userId);
  }

  // POST /audit-requests/:id/schedule ★ KEY ENDPOINT
  // Coordinator assigns auditor + confirms date → creates audit_schedule_row
  @Post(':id/schedule')
  schedule(
    @Param('id', ParseIntPipe) id: number,
    @Body() dto: ScheduleAuditRequestDto,
    @Req() req: Request,
  ) {
    const userId = this.getCurrentUserId(req);
    this.logger.log(
      `POST /audit-requests/${id}/schedule — user=${userId}, auditor=${dto.lead_auditor_id}, date=${dto.audit_date}`,
    );
    return this.service.schedule(id, dto, userId);
  }

  // PATCH /audit-requests/:id/reject
  @Patch(':id/reject')
  reject(
    @Param('id', ParseIntPipe) id: number,
    @Body() dto: RejectAuditRequestDto,
    @Req() req: Request,
  ) {
    const userId = this.getCurrentUserId(req);
    this.logger.log(
      `PATCH /audit-requests/${id}/reject — user=${userId}, reason=${dto.rejection_reason}`,
    );
    return this.service.reject(id, dto, userId);
  }
  @Delete(':id')
  remove(@Param('id', ParseIntPipe) id: number, @Req() req: Request) {
    const userId = this.getCurrentUserId(req);
    this.logger.log(`DELETE /audit-requests/${id} — user=${userId}`);
    return this.service.remove(id, userId);
  }
}