import { NextFunction, Response } from "express";
import { Request } from "express-jwt";
import { UploadedFile } from "express-fileupload";
import fs from "fs"; // Import fs module to check if directory exists
import Joi from "joi";
import { ILogObj, Logger } from "tslog";
import CommonHelper from "../../helpers/common";
import { ReturnHelper } from "../../helpers/express/return";
import { Language } from "../../langs/lang";
import config from "config";
import Thirdparty from "../../helpers/thirdparty";
import JwtHelper from "../../helpers/jwt";

const log: Logger<ILogObj> = new Logger({
	name: "[FileController]",
	type: "pretty",
});

export class FileController {
	static async upload(req: Request, res: Response, next: NextFunction): Promise<void | Response> {
		/*
            #swagger.tags = ['File']
            #swagger.security = [{
                "bearerAuth": []
            }]    
            #swagger.requestBody = {
                required: true,
                content: {
                    "multipart/form-data": {
                        schema: {
                            type: "object",
                            properties: {
                                file: {
                                    type: "string",
                                    format: "binary"
                                }
                            }
                        }
                    }
                }
            }
        }
        */
		try {
			const uploadedFile: UploadedFile | any = req.files.file;

			const schema = Joi.object({
				file: Joi.object({
					name: Joi.string().label("File Name"),
					mimetype: Joi.string()
						.valid(
							"image/jpeg",
							"image/png",
							"image/webp",
							"application/pdf",
							"application/vnd.ms-excel", // ✅ .xls
							"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", // ✅ .xlsx
							"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
							"text/csv", // csv
						)
						.optional()
						.label("File Type"),
					size: Joi.number()
						.max(10 * 1024 * 1024)
						.optional()
						.label("File Size"),
				})
					.optional()
					.label("File"),
			});

			const fileData = {
				name: uploadedFile.name,
				mimetype: uploadedFile.mimetype,
				size: uploadedFile.size,
			};

			let body = await schema.validateAsync({ file: fileData });

			const field = {
				file: uploadedFile,
				application: "saude",
			};

			let url = config.get("service.file") + "upload";
			let result = await Thirdparty.UploadFile(url, field, JwtHelper.token(req.auth.data));
			console.log("result :", result);

			let data = { file: result.data.file };
			return ReturnHelper.successResponseAny(res, 200, Language.lang.success, data);
		} catch (e: unknown) {
			log.error(e);
			const err = e as Error;

			return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message);
		}
	}

	static async delete(req: Request, res: Response, next: NextFunction): Promise<void | Response> {
		/*
            #swagger.tags = ['File']
            #swagger.security = [{
                "bearerAuth": []
            }]
            #swagger.requestBody = {
                required: true,
                content: {
                    "application/json": {
                        schema: {
                            type: "object",
                            properties: {
                                file: {
                                    type: "string",
                                    description: "File name returned from upload"
                                }
                            },
                            required: ["file"]
                        }
                    }
                }
            }
        }
        */
		try {
			const schema = Joi.object({
				file: Joi.string().required().label("File"),
			});

			const param = await schema.validateAsync(req.body);

			if (param.file.includes("..") || param.file.includes("/") || param.file.includes("\\")) {
				return ReturnHelper.errorResponse(res, 400, 400, Language.lang.failed_delete, "Invalid file name");
			}

			const field = {
				file: param.file,
				application: "saude",
			};

			let url = config.get("service.file") + "delete";
			await Thirdparty.DeleteFile(url, field, JwtHelper.token(req.auth.data));

			return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {});
		} catch (e: unknown) {
			log.error(e);
			const err = e as Error;

			return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_delete, err.message);
		}
	}

	static async download(req: Request, res: Response, next: NextFunction): Promise<void | Response> {
		/*
        #swagger.tags = ['File']
        #swagger.security = [{
            "bearerAuth": []
        }]    
        #swagger.parameters['name'] = {
            in: 'query',
            type: 'string'
        }
        #swagger.parameters['token'] = {
            in: 'query',
            required: true,
            type: 'string'
        }
        */
		try {
			// 1️⃣ Validasi parameter
			const schema = Joi.object({
				name: Joi.string().required().label("File Name"),
				token: Joi.string().required().label("Token"),
			});

			const param = await schema.validateAsync(req.query);

			// 2️⃣ Ambil file dari service-file via SFTP (bukan static URL /file/ yang diarahkan ke frontend)
			const url = config.get("service.file") + "download";
			const buffer = await Thirdparty.DownloadFile(url, { file: param.name, application: "saude" }, param.token);

			// 3️⃣ Deteksi ekstensi & MIME type
			const fileName = param.name;
			const ext = fileName.split(".").pop()?.toLowerCase();

			const mimeMap: Record<string, string> = {
				xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
				xls: "application/vnd.ms-excel",
				csv: "text/csv",
				pdf: "application/pdf",
				jpg: "image/jpeg",
				jpeg: "image/jpeg",
				png: "image/png",
				webp: "image/webp",
				gif: "image/gif",
				doc: "application/msword",
				docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
				zip: "application/zip",
				txt: "text/plain",
			};

			const contentType = mimeMap[ext ?? ""] ?? "application/octet-stream";

			// 4️⃣ Set header tipe file
			res.setHeader("Content-Type", contentType);
			res.setHeader("Content-Length", buffer.length);

			// 5️⃣ Tentukan apakah file perlu auto download
			const isInline = contentType.startsWith("image/") || contentType === "application/pdf";

			// 🟢 Kalau image/pdf → tampil di browser
			// 🔵 Kalau file lain → download otomatis
			if (isInline) {
				res.setHeader("Content-Disposition", `inline; filename="${encodeURIComponent(fileName)}"`);
			} else {
				res.setHeader("Content-Disposition", `attachment; filename="${encodeURIComponent(fileName)}"`);
			}

			// 6️⃣ Kirim file ke browser
			return res.end(buffer);
		} catch (e: unknown) {
			log.error(e);
			const err = e as Error;
			return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message);
		}
	}
}
