import { HospitalInformation } from "entity";
import { NextFunction, Response } from "express";
import { Request } from "express-jwt";
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 { OrmHelper } from "../helpers/orm";
import moment from "moment";
import dayjs from 'dayjs';
import fileUpload from "express-fileupload";
import { v4 as uuidv4 } from 'uuid';
import fs from "fs";
import path from "path";
import config from '../../config/stag.json';

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

const hospitalCreateUpdateSchema = {
    name: Joi.string().required().label("Hospital Name"),
    address: Joi.string().required().label("Hospital Address"),
    phone: Joi.string().required().label("Hospital Phone"),
    logo: Joi.string().allow(null, "").label("Hospital Logo"),
    // province: Joi.string().allow("").optional().label("Province Code"),
    // city: Joi.string().allow("").optional().label("City Code"),
    // subdistrict: Joi.string().allow("").optional().label("Subdistrict Code"),
    // ward: Joi.string().allow("").optional().label("Ward Code"),
    munisipo: Joi.string().allow(null, "").label("Munisipo ID"),
    administrativu: Joi.string().allow(null, "").label("Administrativu ID"),
    aldeia: Joi.string().allow(null, "").label("Aldeia ID"),
    suco: Joi.string().allow(null, "").label("Suco ID"),
};

interface FileUploadRequest extends Request {
    files?: fileUpload.FileArray | null;
    body: any;
}

export class HospitalInformationController {

    static async view(req: Request, res: Response, next: NextFunction): Promise<void | Response> {
        /*
            #swagger.tags = ['Hospital Information']
            #swagger.security = [{ "bearerAuth": [] }]
        */
        try {
            const hospital = await OrmHelper.DB.getRepository(HospitalInformation)
                .createQueryBuilder("HospitalInformation")
                .leftJoinAndSelect("HospitalInformation.munisipo", "munisipo")
                .leftJoinAndSelect("HospitalInformation.administrativu", "administrativu")
                .leftJoinAndSelect("HospitalInformation.aldeia", "aldeia")
                .leftJoinAndSelect("HospitalInformation.suco", "suco")
                // .leftJoinAndSelect("HospitalInformation.province", "province")
                // .leftJoinAndSelect("HospitalInformation.city", "city")
                // .leftJoinAndSelect("HospitalInformation.subdistrict", "subdistrict")
                // .leftJoinAndSelect("HospitalInformation.ward", "ward")
                .getOne();

            if (!hospital) return ReturnHelper.errorResponse(res, 404, 404, Language.lang.failed_view, "Hospital not found");

            let hospitallogo = '';
            if (hospital.logo != null && hospital.logo != undefined && hospital.logo != '') {
                hospitallogo = `${config.server.host_swagger}uploads/hospital-logo/${hospital.logo}`;
            }

            const result = {
                id: hospital.id,
                name: hospital.name,
                address: hospital.address,
                phone: hospital.phone,
                logo: hospitallogo,
                file: hospital.logo,
                munisipo: hospital.munisipo,
                administrativu: hospital.administrativu,
                aldeia: hospital.aldeia,
                suco: hospital.suco
            };

            return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, result);

        } 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 create(req: Request, res: Response, next: NextFunction): Promise<void | Response> {
        /*
         #swagger.tags = ['Hospital Information']
         #swagger.security = [{ "bearerAuth": [] }]
         #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/hospitalinformation" } } } }
         */
        const queryRunner = OrmHelper.DB.createQueryRunner();
        await queryRunner.connect();
        await queryRunner.startTransaction();
        try {
            const schema = Joi.object().keys({ ...hospitalCreateUpdateSchema });
            let param: any = await schema.validateAsync(req.body);

            const existing = await OrmHelper.DB.getRepository(HospitalInformation).findOne({ where: {} });

            let hospitalinformation: HospitalInformation;

            if (existing) {
                // ── UPDATE ─────────────────────────────────────────────
                hospitalinformation = existing;
                hospitalinformation.name = param.name;
                hospitalinformation.address = param.address;
                hospitalinformation.phone = param.phone;
                hospitalinformation.logo = param.logo || existing.logo; // ✅ pertahankan logo lama kalau kosong
                // hospitalinformation.province = param.province;
                // hospitalinformation.city = param.city;
                // hospitalinformation.subdistrict = param.subdistrict;
                // hospitalinformation.ward = param.ward;
                hospitalinformation.suco = param.suco;
                hospitalinformation.administrativu = param.administrativu;
                hospitalinformation.aldeia = param.aldeia;
                hospitalinformation.munisipo = param.munisipo;
                hospitalinformation.updated_at = dayjs().toDate();
                hospitalinformation.updated_by = req.auth?.data.name;
            } else {
                // ── INSERT ─────────────────────────────────────────────
                hospitalinformation = new HospitalInformation();
                hospitalinformation.name = param.name;
                hospitalinformation.address = param.address;
                hospitalinformation.phone = param.phone;
                hospitalinformation.logo = param.logo;
                // hospitalinformation.province = param.province;
                // hospitalinformation.city = param.city;
                // hospitalinformation.subdistrict = param.subdistrict;
                // hospitalinformation.ward = param.ward;
                hospitalinformation.suco = param.suco;
                hospitalinformation.administrativu = param.administrativu;
                hospitalinformation.aldeia = param.aldeia;
                hospitalinformation.munisipo = param.munisipo;
                hospitalinformation.created_at = dayjs().toDate();
                hospitalinformation.updated_at = dayjs().toDate();
                hospitalinformation.created_by = req.auth?.data.name;
                hospitalinformation.updated_by = req.auth?.data.name;
            }

            await queryRunner.manager.save(hospitalinformation);
            await queryRunner.commitTransaction();

            return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, hospitalinformation);

        } catch (e: unknown) {
            await queryRunner.rollbackTransaction();
            log.error(e);
            const err = e as Error;
            return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message);
        } finally {
            await queryRunner.release();
        }
    }

    static async uploadlogo(req: FileUploadRequest, res: Response, next: NextFunction): Promise<Response> {
        /* #swagger.tags = ['Hospital Information'] 
           #swagger.security = [{ "bearerAuth": [] }] 
           #swagger.consumes = ['multipart/form-data'] 
           #swagger.requestBody = { 
               required: true, 
               content: { 
                   "multipart/form-data": { 
                       schema: { 
                           type: "object", 
                           properties: { 
                               file: { 
                                   type: "string", 
                                   format: "binary", 
                                   description: "Image file (max 1MB, jpg/png/webp)" 
                               },
                           }, 
                           required: ["file"] 
                       } 
                   } 
               } 
           } 
        */
        try {
            // Validation schema
            // const schema = Joi.object().keys({
            //     path: Joi.string().label('File Path'),
            //     application: Joi.string().label('Application'),
            // });

            log.info("body", req.body);

            // const param: { path: string, application: string } = await schema.validateAsync(req.body);

            // Check if file exists
            if (!req.files || !req.files.file) {
                return ReturnHelper.errorResponse(res, 400, 404, Language.lang.failed_insert, "File not found");
            }

            const file = req.files.file as fileUpload.UploadedFile;

            // Validate file size (max 1MB)
            const maxSize = 10 * 1024 * 1024; // 10MB
            if (file.size > maxSize) {
                return ReturnHelper.errorResponse(
                    res,
                    400,
                    400,
                    Language.lang.failed_insert,
                    "File size exceeds 10MB limit"
                );
            }

            // Validate file type
            const allowedMimes = ['image/jpeg', 'image/jpg', 'image/png', 'image/webp'];
            if (!allowedMimes.includes(file.mimetype)) {
                return ReturnHelper.errorResponse(res, 400, 400, Language.lang.failed_insert, "Invalid file type. Only JPG, PNG, and WEBP are allowed");
            }

            // Normalize path
            // param.path = param.path[param.path.length - 1] !== '/' ? param.path + '/' : param.path;

            // if (param.path == undefined || param.path == null) param.path = 'uploads/hospital-logo/';

            // Generate unique filename
            const ext = file.name.split('.');
            const name = uuidv4() + '.' + ext[ext.length - 1];

            const result: { file: string } = {
                // url: "",
                // path: "",
                file: "",
                // mime: file.mimetype,
                // size: file.size,
                // md5: file.md5
            };

            const folder_path = 'uploads/hospital-logo/';
            const file_path = path.join(folder_path, name);

            // Create directory if it doesn't exist
            if (!fs.existsSync(folder_path)) {
                fs.mkdirSync(folder_path, { recursive: true });
            }

            // Move file to destination
            await file.mv(file_path);

            // result.path = param.path[param.path.length - 1] === '/' ? param.path.substring(0, param.path.length - 1) : param.path;
            result.file = name;
            // result.url = `${result.path}/${name}`; // Generate URL

            log.info(`File uploaded successfully: ${file_path}`);

            return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, result);

        } catch (e: unknown) {
            // Proper error logging to avoid tslog serialization issues
            if (e instanceof Error) {
                log.error("File upload failed:", {
                    message: e.message,
                    stack: e.stack,
                    name: e.name
                });
                return ReturnHelper.errorResponse(res, 500, 500, Language.lang.failed_insert, e.message);
            } else {
                log.error("File upload failed with unknown error:", String(e));
                return ReturnHelper.errorResponse(res, 500, 500, Language.lang.failed_insert, "Unknown error occurred");
            }
        }
    }

    static async deletelogo(req: Request, res: Response, next: NextFunction): Promise<Response> {
        /*
         #swagger.tags = ['Hospital Information']
         #swagger.security = [{ "bearerAuth": [] }]
         #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/files" } } } }
         */

        try {
            const schema = Joi.object().keys({
                file_name: Joi.string().required().label('File Name'),
            });

            const param: { file_name: string } = await schema.validateAsync(req.body);

            // const env = process.env.NODE_ENV + '/'
            const fixedPath = 'uploads/hospital-logo/';
            const file_path = fixedPath + param.file_name;

            // Check if file exists
            if (!fs.existsSync(file_path)) {
                return ReturnHelper.errorResponse(res, 404, 404, Language.lang.failed_not_found, "File not found");
            }

            // Delete file
            fs.unlinkSync(file_path);

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

            return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message);
        }
    }

}
