import {
  Controller,
  Get,
  Post,
  Body,
  Patch,
  Param,
  Delete,
  UseInterceptors,
  UploadedFile,
  HttpException,
  HttpStatus,
} from '@nestjs/common';
import { InvoiceIssuersService } from './invoice_issuers.service';
import { Public } from '../auth/public.decorator';
import { FileInterceptor } from '@nestjs/platform-express';
import { diskStorage } from 'multer';
import { extname } from 'path';

@Controller('invoice-issuers')
export class InvoiceIssuersController {
  constructor(private readonly invoiceIssuersService: InvoiceIssuersService) {}

  @Public()
  @Get()
  findAll() {
    return this.invoiceIssuersService.findAll();
  }

  @Public()
  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.invoiceIssuersService.findOne(+id);
  }

  @Public()
  @Post()
  create(@Body() createDto: any) {
    return this.invoiceIssuersService.create(createDto);
  }

  @Public()
  @Patch(':id')
  update(@Param('id') id: string, @Body() updateDto: any) {
    // Fail-safe: If an update includes a .webp logo path but a .png version exists (following our conversion logic),
    // we prioritize the .png path to keep the database consistent.
    if (updateDto.logo_url && updateDto.logo_url.endsWith('.webp')) {
      const pngPath = updateDto.logo_url.replace(/\.webp$/, '.png');
      const fs = require('fs');
      const path = require('path');
      if (fs.existsSync(path.join(process.cwd(), pngPath))) {
        updateDto.logo_url = pngPath;
      }
    }
    return this.invoiceIssuersService.update(+id, updateDto);
  }

  @Public()
  @Delete(':id')
  remove(@Param('id') id: string) {
    return this.invoiceIssuersService.remove(+id);
  }

  @Public()
  @Post(':id/logo')
  @UseInterceptors(
    FileInterceptor('logo', {
      storage: diskStorage({
        destination: (req, file, cb) => {
          const path = require('path');
          const fs = require('fs');
          const uploadDir = './uploads/logos/invoice-issuers';
          if (!fs.existsSync(uploadDir)) {
            fs.mkdirSync(uploadDir, { recursive: true });
          }
          cb(null, uploadDir);
        },
        filename: (req, file, cb) => {
          const uniqueSuffix =
            Date.now() + '-' + Math.round(Math.random() * 1e9);
          cb(null, uniqueSuffix + extname(file.originalname));
        },
      }),
      limits: { fileSize: 2 * 1024 * 1024 }, // 2MB limit
      fileFilter: (req, file, cb) => {
        if (!file.mimetype.match(/^image/)) {
          return cb(new Error('Only image files are allowed!'), false);
        }
        cb(null, true);
      },
    }),
  )
  async uploadLogo(
    @Param('id') id: string,
    @UploadedFile() file: Express.Multer.File,
  ) {
    if (!file) {
      throw new HttpException('File not provided', HttpStatus.BAD_REQUEST);
    }

    const fs = require('fs');
    const path = require('path');
    const sharp = require('sharp');
    const originalPath = file.path;
    const pngPath = originalPath.split('.').slice(0, -1).join('.') + '.png';

    try {
      // Read file into buffer to avoid EBUSY lock on Windows during unlinking
      const inputBuffer = fs.readFileSync(originalPath);
      const imageProcessor = sharp(inputBuffer);
      const metadata = await imageProcessor.metadata();

      // Validation: Minimum width of 300px for high-res
      if (metadata.width < 300) {
        if (fs.existsSync(originalPath)) fs.unlinkSync(originalPath);
        throw new HttpException(
          'Logo must be at least 300px wide for high resolution.',
          HttpStatus.BAD_REQUEST,
        );
      }

      // Convert and save as PNG
      await imageProcessor.png().toFile(pngPath);

      // Delete the original file if it wasn't already a PNG or if it was renamed
      if (originalPath !== pngPath) {
        if (fs.existsSync(originalPath)) fs.unlinkSync(originalPath);
      }

      const finalPath = pngPath.replace(/\\/g, '/');
      await this.invoiceIssuersService.update(+id, { logo_url: finalPath });
      return {
        success: true,
        logo_url: finalPath,
        width: metadata.width,
        height: metadata.height,
      };
    } catch (error) {
      if (fs.existsSync(originalPath)) fs.unlinkSync(originalPath);
      if (fs.existsSync(pngPath)) fs.unlinkSync(pngPath);
      throw new HttpException(
        error.message || 'Image validation failed',
        error.status || HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }
}
