import {
  Controller,
  Get,
  Post,
  Patch,
  Param,
  Body,
  UseInterceptors,
  UploadedFile,
  Res,
  HttpStatus,
  BadRequestException,
  ParseUUIDPipe,
  StreamableFile,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import type { Response } from 'express';
import { DocumentsLegauxService } from './documents-legaux.service';
import { UploadDocumentDto } from './dto/upload-document.dto';
import { DocumentsActifsResponseDto } from './dto/documents-actifs.dto';
import { DocumentVersionDto } from './dto/document-version.dto';

@Controller('documents-legaux')
export class DocumentsLegauxController {
  constructor(private readonly documentsService: DocumentsLegauxService) {}

  /**
   * GET /api/v1/documents-legaux/actifs
   * Récupérer les documents actifs (CGU + Privacy)
   * PUBLIC
   */
  @Get('actifs')
  async getDocumentsActifs(): Promise<DocumentsActifsResponseDto> {
    const { cgu, privacy } = await this.documentsService.getDocumentsActifs();

    return {
      cgu: {
        id: cgu.id,
        type: cgu.type,
        version: cgu.version,
        url: `/api/v1/documents-legaux/${cgu.id}/download`,
        activeLe: cgu.activeLe,
      },
      privacy: {
        id: privacy.id,
        type: privacy.type,
        version: privacy.version,
        url: `/api/v1/documents-legaux/${privacy.id}/download`,
        activeLe: privacy.activeLe,
      },
    };
  }

  /**
   * GET /api/v1/documents-legaux/:type/versions
   * Lister toutes les versions d'un type de document
   * ADMIN ONLY
   */
  @Get(':type/versions')
  // @UseGuards(JwtAuthGuard, RolesGuard)
  // @Roles('super_admin', 'administrateur')
  async listerVersions(@Param('type') type: string): Promise<DocumentVersionDto[]> {
    if (type !== 'cgu' && type !== 'privacy') {
      throw new BadRequestException('Le type doit être "cgu" ou "privacy"');
    }

    const documents = await this.documentsService.listerVersions(type as 'cgu' | 'privacy');

    return documents.map((doc) => ({
      id: doc.id,
      version: doc.version,
      fichier_nom: doc.fichier_nom,
      actif: doc.actif,
      televersePar: doc.televersePar
        ? {
            id: doc.televersePar.id,
            prenom: doc.televersePar.prenom,
            nom: doc.televersePar.nom,
          }
        : null,
      televerseLe: doc.televerseLe,
      activeLe: doc.activeLe,
    }));
  }

  /**
   * POST /api/v1/documents-legaux
   * Upload une nouvelle version d'un document
   * ADMIN ONLY
   */
  @Post()
  @UseInterceptors(FileInterceptor('file'))
  // @UseGuards(JwtAuthGuard, RolesGuard)
  // @Roles('super_admin', 'administrateur')
  async uploadDocument(
    @Body() uploadDto: UploadDocumentDto,
    @UploadedFile() file: Express.Multer.File,
    // @CurrentUser() user: any, // TODO: Décommenter quand le guard sera implémenté
  ) {
    if (!file) {
      throw new BadRequestException('Aucun fichier fourni');
    }

    // TODO: Récupérer l'ID utilisateur depuis le guard quand l'auth sera branchée.
    // En attendant, on n'associe pas d'utilisateur plutôt que d'envoyer un UUID fictif invalide.
    const userId: string | null = null;

    const document = await this.documentsService.uploadNouvelleVersion(
      uploadDto.type,
      file,
      userId,
    );

    return {
      id: document.id,
      type: document.type,
      version: document.version,
      fichier_nom: document.fichier_nom,
      actif: document.actif,
      televerseLe: document.televerseLe,
    };
  }

  /**
   * PATCH /api/v1/documents-legaux/:id/activer
   * Activer une version d'un document
   * ADMIN ONLY
   */
  @Patch(':id/activer')
  // @UseGuards(JwtAuthGuard, RolesGuard)
  // @Roles('super_admin', 'administrateur')
  async activerVersion(@Param('id', ParseUUIDPipe) documentId: string) {
    await this.documentsService.activerVersion(documentId);

    // Récupérer le document pour retourner les infos
    const documents = await this.documentsService.listerVersions('cgu');
    const document = documents.find((d) => d.id === documentId);

    if (!document) {
      const documentsPrivacy = await this.documentsService.listerVersions('privacy');
      const docPrivacy = documentsPrivacy.find((d) => d.id === documentId);

      if (!docPrivacy) {
        throw new BadRequestException('Document non trouvé');
      }

      return {
        message: 'Document activé avec succès',
        documentId: docPrivacy.id,
        type: docPrivacy.type,
        version: docPrivacy.version,
      };
    }

    return {
      message: 'Document activé avec succès',
      documentId: document.id,
      type: document.type,
      version: document.version,
    };
  }

  /**
   * GET /api/v1/documents-legaux/:id/download
   * Télécharger un document
   * PUBLIC
   */
  @Get(':id/download')
  async telechargerDocument(
    @Param('id', ParseUUIDPipe) documentId: string,
    @Res() res: Response,
  ) {
    const { stream, filename } = await this.documentsService.telechargerDocument(documentId);

    res.set({
      'Content-Type': 'application/pdf',
      'Content-Disposition': `attachment; filename="${filename}"`,
    });

    res.status(HttpStatus.OK).send(stream);
  }

  /**
   * GET /api/v1/documents-legaux/:id/verifier-integrite
   * Vérifier l'intégrité d'un document (hash SHA-256)
   * ADMIN ONLY
   */
  @Get(':id/verifier-integrite')
  // @UseGuards(JwtAuthGuard, RolesGuard)
  // @Roles('super_admin', 'administrateur')
  async verifierIntegrite(@Param('id', ParseUUIDPipe) documentId: string) {
    const integre = await this.documentsService.verifierIntegrite(documentId);

    return {
      documentId,
      integre,
      message: integre
        ? 'Le document est intègre (hash valide)'
        : 'ALERTE : Le document a été modifié (hash invalide)',
    };
  }
}

