import {
    Controller,
    Post,
    Route,
    Tags,
    UploadedFile,
    UploadedFiles,
    Get,
    Delete,
    Path,
    Query,
    FormField,
} from "tsoa";

import fs from "fs";
import path from "path";
import { Express } from "express";
import { AppDataSource } from "../data-source";
import { ImageUploads } from "../entity/ImageUploads";

function randomName(original: string) {
    const chars = "abcdefghijklmnopqrstuvwxyz";
    const rand = Array(10).fill(null).map(() => chars[Math.floor(Math.random() * chars.length)]).join("");
    const ext = original.substring(original.lastIndexOf("."));
    return rand + "_" + Date.now() + ext;
}

@Route("image-upload")
@Tags("Image Upload")
export class ImageUploadController extends Controller {

    /**
     * Upload SINGLE image
     */
    @Post("/single")
    public async uploadSingleImage(
        @UploadedFile() file?: Express.Multer.File,
        @FormField() title?: string
    ): Promise<{ message: string; file?: any }> {

        if (!file) {
            this.setStatus(400);
            return { message: "No file uploaded" };
        }

        const uploadDir = path.join(process.cwd(), "public/uploads/");
        if (!fs.existsSync(uploadDir)) fs.mkdirSync(uploadDir, { recursive: true });

        const newFileName = randomName(file.originalname);
        const finalPath = path.join(uploadDir, newFileName);

        fs.writeFileSync(finalPath, file.buffer, { flag: "w" });

        const imageRepo = AppDataSource.getRepository(ImageUploads);

        const saved = await imageRepo.save({
            filename: newFileName,
            path: `/public/uploads/${newFileName}`,
            title: title ? title : undefined
        });


        return {
            message: "Image uploaded successfully",
            file: saved
        };
    }



    /**
     * Upload MULTIPLE images
     */
    @Post("/multiple")
    public async uploadMultipleImages(
        @UploadedFiles() files?: Express.Multer.File[],
        @FormField() title?: string
    ): Promise<{ message: string; uploaded?: any[] }> {

        if (!files || files.length === 0) {
            this.setStatus(400);
            return { message: "No images uploaded" };
        }

        const uploadDir = path.join(process.cwd(), "public/uploads/");
        if (!fs.existsSync(uploadDir)) fs.mkdirSync(uploadDir, { recursive: true });

        const results: any[] = [];
        const imageRepo = AppDataSource.getRepository(ImageUploads);

        for (const file of files) {
            const newFileName = randomName(file.originalname);
            const finalPath = path.join(uploadDir, newFileName);

            fs.writeFileSync(finalPath, file.buffer, { flag: "w" });

            const saved = await imageRepo.save({
                filename: newFileName,
                path: `/public/uploads/${newFileName}`,
                title: title ? title : undefined
            });

            results.push(saved);
        }

        return {
            message: "Images uploaded successfully",
            uploaded: results
        };
    }



    /**
     * List all uploaded images
     */
    @Get("/")
    public async listImages(
        @Query() title?: string
    ): Promise<{ count: number; images: ImageUploads[] }> {

        const imageRepo = AppDataSource.getRepository(ImageUploads);

        let images;

        if (title) {
            images = await imageRepo.find({
                where: { title: title }
            });
        } else {
            images = await imageRepo.find();
        }

        return {
            count: images.length,
            images
        };
    }


    /**
     * Delete an image
     */
    @Delete("/{filename}")
    public async deleteImage(
        @Path() filename: string
    ): Promise<{ message: string }> {

        const filePath = path.join(process.cwd(), "public/uploads", filename);

        if (!fs.existsSync(filePath)) {
            this.setStatus(404);
            return { message: "Image not found" };
        }

        fs.unlinkSync(filePath);

        return { message: "Image deleted successfully" };
    }
}
