import { Readable } from "stream";
import { ApiValidationError } from "../../Models/Server.Error.model";
import {
    Controller,
    Middlewares,
    Post,
    Get,
    Path,
    Response,
    Route,
    FormField,
    UploadedFile,
    SuccessResponse,
} from "tsoa";
import { authenticateMiddleware } from "../../middleware/authentication";
import { FilesService } from "./Files.Service";
import { UploadFileResponse } from "../../Models/Files/Files.Interface";

function getContentTypeFromExtension(filename: string): string {
    const lower = filename.toLowerCase();

    if (lower.endsWith(".jpg") || lower.endsWith(".jpeg")) {
        return "image/jpeg";
    }
    if (lower.endsWith(".png")) {
        return "image/png";
    }
    if (lower.endsWith(".gif")) {
        return "image/gif";
    }
    if (lower.endsWith(".webp")) {
        return "image/webp";
    }

    // Valor por defecto si no coincide
    return "application/octet-stream";
}

@Route("files/upload-post-file")
@Middlewares([authenticateMiddleware])
export class UploadPostFileController extends Controller {
    @SuccessResponse(200, "El archivo fue cargado correctamente")
    @Post()
    public async uploadImage(
        @FormField() companyId: string,
        @FormField() token: string,
        @FormField() sessionUser: string,
        @UploadedFile() file: Express.Multer.File
    ): Promise<UploadFileResponse | ApiValidationError> {
        try {
            const response = await new FilesService().uploadPostFile({
                companyId,
                token,
                sessionUser,
                file,
            });
            this.setStatus(200);
            return response;
        } catch (e) {
            console.log("ha fallado la subida del archivo...", e);
            const errorOccurred: Error = e as Error;
            this.setStatus(500);
            return new ApiValidationError(500, errorOccurred.message);
        }
    }
}

@Route("files")
export class DownloadFileController extends Controller {
    @Get("download/{objectName}")
    @Response<ApiValidationError>(404, "File not found")
    @Response<ApiValidationError>(500, "Internal Server Error")
    public async downloadImage(
        @Path() objectName: string
    ): Promise<Readable> {
        try {
            const fileBuffer = await new FilesService().downloadFile(objectName);

            if (!fileBuffer || fileBuffer.length === 0) {
                throw new ApiValidationError(404, "File not found");
            }

            const contentType = getContentTypeFromExtension(objectName);
            this.setHeader("Content-Type", contentType);
            this.setHeader("Content-Length", fileBuffer.length.toString());
            this.setHeader("Cache-Control", "public, max-age=3600");
            this.setHeader("Content-Disposition", `inline; filename="${objectName}"`);
            this.setStatus(200);

            const stream = new Readable();
            stream.push(fileBuffer);
            stream.push(null);
            return stream;

        } catch (e) {
            if (e instanceof ApiValidationError) {
                throw e;
            }
            const error = e as Error;
            console.error(`Error al descargar el archivo "${objectName}":`, error);
            throw new ApiValidationError(500, error.message || "Internal Server Error");
        }
    }
}
