import {
  BadRequestException,
  Controller,
  Param,
  Post,
  Req,
  UploadedFile,
  UseGuards,
  UseInterceptors,
} from "@nestjs/common";
import { FileInterceptor } from "@nestjs/platform-express";
import {
  ApiBearerAuth,
  ApiBody,
  ApiConsumes,
  ApiOperation,
  ApiTags,
} from "@nestjs/swagger";
import { Request } from "express";
import { RequirePermission } from "../auth/decorators/require-permission.decorator";
import { JwtAuthGuard } from "../auth/guards/jwt-auth.guard";
import { PermissionGuard } from "../auth/guards/permission.guard";
import {
  UploadType,
  assertUploadedFile,
  getUploadRule,
  isAllowedUploadType,
} from "./upload-validation";
import { UploadsService } from "./uploads.service";

function toAbsoluteUrl(request: Request, url: string): string {
  if (/^https?:\/\//i.test(url)) {
    return url;
  }

  const protocol = request.headers["x-forwarded-proto"] || request.protocol;
  const host = request.get("host");
  return `${protocol}://${host}${url}`;
}

@ApiTags("uploads")
@ApiBearerAuth()
@UseGuards(JwtAuthGuard, PermissionGuard)
@RequirePermission("uploads", "write")
@Controller("uploads")
export class UploadsController {
  constructor(private readonly uploadsService: UploadsService) {}

  @Post(":type")
  @ApiOperation({ summary: "Subir archivo de taller (foto, firma o PDF)" })
  @ApiConsumes("multipart/form-data")
  @ApiBody({
    schema: {
      type: "object",
      properties: {
        file: {
          type: "string",
          format: "binary",
        },
      },
      required: ["file"],
    },
  })
  @UseInterceptors(
    FileInterceptor("file", {
      fileFilter: (req, file, callback) => {
        try {
          const type = req.params.type as UploadType;
          const rule = getUploadRule(type);
          if (!isAllowedUploadType(file, type)) {
            callback(new BadRequestException(rule.invalidTypeMessage), false);
            return;
          }
          callback(null, true);
        } catch (error) {
          callback(error as Error, false);
        }
      },
      limits: {
        fileSize: 15 * 1024 * 1024,
        files: 1,
      },
    }),
  )
  async upload(
    @Param("type") type: UploadType,
    @UploadedFile() file: Express.Multer.File,
    @Req() request: Request,
  ) {
    assertUploadedFile(file, type);

    if (type === "foto") {
      const result = await this.uploadsService.uploadFoto(file);
      return {
        ...result,
        url: toAbsoluteUrl(request, result.url),
        thumbnail: toAbsoluteUrl(request, result.thumbnail),
      };
    }

    if (type === "firma") {
      const result = await this.uploadsService.uploadFirma(file);
      return {
        ...result,
        url: toAbsoluteUrl(request, result.url),
      };
    }

    const result = await this.uploadsService.uploadPdf(file);
    return {
      ...result,
      url: toAbsoluteUrl(request, result.url),
    };
  }
}
