import {
  BadRequestException,
  Controller,
  Post,
  Query,
  Req,
  UseGuards,
  UseInterceptors,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { ApiBearerAuth, ApiOkResponse, ApiTags } from '@nestjs/swagger';
import { UserRole } from '@prisma/client';
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
import { RolesGuard } from '../../common/guards/roles.guard';
import { Roles } from '../../common/decorators/roles.decorator';
import { Permissions } from '../../common/decorators/permissions.decorator';
import { PermissionsGuard } from '../../common/guards/permissions.guard';
import type { Request } from 'express';
import { extname } from 'path';
import { memoryStorage } from 'multer';
import {
  UploadsService,
  type UploadEntityType,
  type UploadPurpose,
} from './uploads.service';

@ApiTags('uploads')
@ApiBearerAuth()
@Controller('uploads')
@UseGuards(JwtAuthGuard, RolesGuard, PermissionsGuard)
@Roles(UserRole.SUPERADMIN, UserRole.ADMIN, UserRole.SUBADMIN)
@Permissions('coupons', 'luckyDraw')
export class UploadsController {
  constructor(private readonly uploads: UploadsService) {}

  @Post('image')
  @ApiOkResponse({ description: 'Upload an image and get public path' })
  @UseInterceptors(
    FileInterceptor('file', {
      limits: { fileSize: 5 * 1024 * 1024 }, // 5MB
      storage: memoryStorage(),
    }),
  )
  async uploadImage(
    @Req() req: Request & { file?: any; user?: any },
    @Query('entityType') entityType?: UploadEntityType,
    @Query('entityId') entityId?: string,
    @Query('purpose') purpose?: UploadPurpose,
  ) {
    const file = req.file;
    if (!file) throw new BadRequestException('file is required');
    if (!file.mimetype?.startsWith('image/'))
      throw new BadRequestException('Only image uploads are allowed');

    // Pick extension from original name, fallback to mimetype.
    const fromName = extname(file.originalname || '').toLowerCase();
    const ext =
      fromName ||
      (file.mimetype === 'image/png'
        ? '.png'
        : file.mimetype === 'image/jpeg'
          ? '.jpg'
          : file.mimetype === 'image/webp'
            ? '.webp'
            : '.png');

    const rawEntityType =
      (entityType as unknown as string | undefined) ?? 'tmp';
    const et: UploadEntityType =
      rawEntityType === 'businesstype'
        ? 'business-type'
        : rawEntityType === 'business-type'
          ? 'business-type'
          : (entityType ?? 'tmp');

    const rawPurpose = (purpose as unknown as string | undefined) ?? 'assets';
    const p: UploadPurpose =
      rawPurpose === 'active' ||
      rawPurpose === 'background' ||
      rawPurpose === 'sticker' ||
      rawPurpose === 'assets'
        ? (rawPurpose as UploadPurpose)
        : 'assets';

    const shopId = req.user?.shopId as string | undefined;
    if (!shopId && et !== 'business-type')
      throw new BadRequestException('No shop selected');

    const path = await this.uploads.saveImage({
      shopId,
      entityType: et,
      entityId: et === 'tmp' ? undefined : entityId,
      purpose: p,
      ext,
      buffer: file.buffer,
    });
    return { path };
  }
}
