import {
  Controller,
  Get,
  Post,
  Param,
  Req,
  Res,
  UseGuards,
  ParseIntPipe,
  UseInterceptors,
  UploadedFile,
  BadRequestException,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import * as multer from 'multer';
import type { Response } from 'express';

// Same guard the rest of /client-portal uses (company, audits, certificates…).
// Client JWTs carry company_ids[] and pass through this guard exactly like
// in client-portal.controller.ts.
import { JwtAuthGuard } from './../auth/guards/jwt-auth.guard';

import { ChecklistsService } from './services/checklists.service';

/** Mirror of ClientPortalController.getCompanyIds() - the client JWT
 *  payload carries `company_ids: number[]`. */
function getCompanyId(req: any): number {
  const ids: number[] = (req.user as any)?.company_ids ?? [];
  if (!ids || ids.length === 0) {
    throw new BadRequestException('No company access found');
  }
  return ids[0];
}

// Mounted under the same /client-portal prefix as the rest of the portal API.
@Controller('client-portal')
@UseGuards(JwtAuthGuard)
export class ClientChecklistsController {
  constructor(private readonly service: ChecklistsService) {}

  /** Checklists for one of MY audits. :auditRequestId is the id the portal
   *  uses everywhere (audit_requests.id) - the service translates it to the
   *  audit_schedule_row internally. Only checklists the auditor has sent. */
  @Get('audits/:auditRequestId/checklists')
  async getChecklists(@Param('auditRequestId', ParseIntPipe) auditRequestId: number, @Req() req: any) {
    return this.service.getChecklistsForClientByRequest(auditRequestId, getCompanyId(req));
  }

  /** Upload (or re-upload) one document against one checklist item. */
  @Post('checklists/items/:itemId/upload')
  @UseInterceptors(FileInterceptor('file', { storage: multer.memoryStorage(), limits: { fileSize: 10 * 1024 * 1024 } }))
  async upload(
    @Param('itemId', ParseIntPipe) itemId: number,
    @UploadedFile() file: any,
    @Req() req: any,
  ) {
    if (!file) throw new BadRequestException('No file received - send multipart/form-data with a "file" field.');
    const companyId = getCompanyId(req);
    const userId = Number((req.user as any)?.id ?? (req.user as any)?.userId ?? (req.user as any)?.sub ?? 0);
    return this.service.uploadClientDocument(itemId, companyId, userId, {
      originalname: file.originalname,
      mimetype: file.mimetype,
      buffer: file.buffer,
      size: file.size,
    });
  }

  /** Client's own Submit - allowed only when every item is uploaded.
   *  Notifies the lead auditor by email + real-time. */
  @Post('checklists/:checklistId/submit')
  async submit(@Param('checklistId', ParseIntPipe) checklistId: number, @Req() req: any) {
    await this.service.clientSubmitChecklist(checklistId, getCompanyId(req));
    return { success: true };
  }

  /** The checklist itself as a PDF - same file attached to the email. */
  @Get('checklists/:checklistId/pdf')
  async checklistPdf(
    @Param('checklistId', ParseIntPipe) checklistId: number,
    @Req() req: any,
    @Res() res: Response,
  ) {
    const { buffer, filename } = await this.service.getChecklistPdfForCompany(checklistId, getCompanyId(req));
    res.setHeader('Content-Type', 'application/pdf');
    res.setHeader('Content-Length', String(buffer.length));
    res.setHeader('Content-Disposition', `inline; filename="${encodeURIComponent(filename)}"`);
    res.end(buffer);
  }

  /** View / download my own uploaded document. */
  @Get('checklists/items/:itemId/document')
  async download(@Param('itemId', ParseIntPipe) itemId: number, @Req() req: any, @Res() res: Response) {
    const { stream, size, mimeType, filename } = await this.service.openItemDocumentForCompany(itemId, getCompanyId(req));
    res.setHeader('Content-Type', mimeType);
    res.setHeader('Content-Length', String(size));
    res.setHeader('Content-Disposition', `inline; filename="${encodeURIComponent(filename)}"`);
    stream.pipe(res);
  }
}