import axios from "axios";
import log from "../config/log";
import type CustomRequest from "../types/requestType";
import type { Response } from "express";
import fs from "fs";
import fsPromises from "fs/promises";
import FormData from "form-data";

const cashfree: any = {};

cashfree.addBeneficiary = async (req: CustomRequest, res: Response) => {

    const U = `cashfree`;
    const F = `addBeneficiary`;
    let clientId = req.id;

    try {
        const options = {
            method: "POST",
            url: `${process.env.CASHFREE_PAYOUT_BASE_URL}/beneficiary`,
            headers: {
                "Content-Type": req.headers["content-type"] || "application/json",
                "x-client-id": req.headers["x-client-id"] as string,
                "x-client-secret": req.headers["x-client-secret"] as string,
                "x-api-version": req.headers["x-api-version"] || "2024-01-01",
            },
            data: req.body,
        };
        log.info(`[${U}], [${F}], [DEB], Client Id [${clientId}], Request payload [${JSON.stringify(options)}]`);
        const response = await axios.request(options);
        log.info(`[${U}], [${F}], [DEB], Client Id [${clientId}], Response [${JSON.stringify(response.data)}]`);
        return res.status(response.status).json(response.data);

    } catch (err: any) {
        log.info(`[${U}], [${F}], [ERR], Client Id [${clientId}],  Error [${JSON.stringify(err.response.data || err.message)}]`);
        return res.status(400).json(err.response.data || err.message);
    }

};

cashfree.removeBeneficiary = async (req: CustomRequest, res: Response) => {

    const U = `cashfree`;
    const F = `removeBeneficiary`;
    let { beneficiary_id } = req.query;
    let clientId = req.id;
    try {
        const options = {
            method: "DELETE",
            url: `${process.env.CASHFREE_PAYOUT_BASE_URL}/beneficiary?beneficiary_id=${beneficiary_id}`,
            headers: {
                "Content-Type": req.headers["content-type"] || "application/json",
                "x-client-id": req.headers["x-client-id"] as string,
                "x-client-secret": req.headers["x-client-secret"] as string,
                "x-api-version": req.headers["x-api-version"] || "2024-01-01",
            },
        };
        log.info(`[${U}], [${F}], [DEB], Client Id [${clientId}], Request payload [${JSON.stringify(options)}]`);
        const response = await axios.request(options);
        log.info(`[${U}], [${F}], [DEB], Client Id [${clientId}], Response [${JSON.stringify(response.data)}]`);
        return res.status(response.status).json(response.data);

    } catch (err: any) {
        log.info(`[${U}], [${F}], [ERR], Client Id [${clientId}],  Error [${JSON.stringify(err.response.data || err.message)}]`);

        return res.status(400).json(err.response.data || err.message);
    }

};

cashfree.fetchBeneficiary = async (req: CustomRequest, res: Response) => {

    const U = `cashfree`;
    const F = `fetchBeneficiary`;
    let { bank_ifsc, bank_account_number } = req.query;
    let clientId = req.id;

    try {
        const options = {
            method: "GET",
            url: `${process.env.CASHFREE_PAYOUT_BASE_URL}/beneficiary?bank_account_number=${bank_account_number}&bank_ifsc=${bank_ifsc}`,
            headers: {
                "Content-Type": req.headers["content-type"] || "application/json",
                "x-client-id": req.headers["x-client-id"] as string,
                "x-client-secret": req.headers["x-client-secret"] as string,
                "x-api-version": req.headers["x-api-version"] || "2024-01-01",
            },
        };
        log.info(`[${U}], [${F}], [DEB], Client Id [${clientId}], Request payload [${JSON.stringify(options)}]`);
        const response = await axios.request(options);
        log.info(`[${U}], [${F}], [DEB], Client Id [${clientId}], Response [${JSON.stringify(response.data)}]`);
        return res.status(response.status).json(response.data);
    } catch (err: any) {
        log.info(`[${U}], [${F}], [ERR], Client Id [${clientId}],  Error [${JSON.stringify(err.response.data || err.message)}]`);
        return res.status(400).json(err.response.data || err.message);
    }

};

cashfree.payoutToBeneficiary = async (req: CustomRequest, res: Response) => {

    const U = `cashfree`;
    const F = `payoutToBeneficiary`;
    let clientId = req.id;
    try {
        const options = {
            method: "POST",
            url: `${process.env.CASHFREE_PAYOUT_BASE_URL}/transfers`,
            headers: {
                "Content-Type": req.headers["content-type"] || "application/json",
                "x-client-id": req.headers["x-client-id"] as string,
                "x-client-secret": req.headers["x-client-secret"] as string,
                "x-api-version": req.headers["x-api-version"] || "2024-01-01",
            },
            data: req.body,
        };
        log.info(`[${U}], [${F}], [DEB], Client Id [${clientId}], Request payload [${JSON.stringify(options)}]`);
        const response = await axios.request(options);
        log.info(`[${U}], [${F}], [DEB], Client Id [${clientId}], Response [${JSON.stringify(response.data)}]`);
        return res.status(response.status).json(response.data);
    } catch (err: any) {
        log.info(`[${U}], [${F}], [ERR], Client Id [${clientId}],  Error [${JSON.stringify(err.response?.data || err.message)}]`);
        return res.status(400).json(err.response?.data || err.message);
    }

};

cashfree.quickPayout = async (req: CustomRequest, res: Response) => {

    const U = `cashfree`;
    const F = `quickPayout`;
    let clientId = req.id;
    try {
        const options = {
            method: "POST",
            url: `${process.env.CASHFREE_PAYOUT_BASE_URL}/transfers`,
            headers: {
                "Content-Type": req.headers["content-type"] || "application/json",
                "x-client-id": req.headers["x-client-id"] as string,
                "x-client-secret": req.headers["x-client-secret"] as string,
                "x-api-version": req.headers["x-api-version"] || "2024-01-01",
            },
            data: req.body,
        };

        log.info(`[${U}], [${F}], [DEB], Client Id [${clientId}], Request payload [${JSON.stringify(options)}]`);
        const response = await axios.request(options);
        log.info(`[${U}], [${F}], [DEB], Client Id [${clientId}], Response [${JSON.stringify(response.data)}]`);
        return res.status(response.status).json(response.data);
    } catch (err: any) {
        log.info(`[${U}], [${F}], [ERR], Client Id [${clientId}],  Error [${JSON.stringify(err.response?.data || err.message)}]`);
        return res.status(400).json(err.response?.data || err.message);
    }

};

cashfree.getWalletBalance = async (req: CustomRequest, res: Response) => {

    const U = `cashfree`;
    const F = `getWalletBalance`;
    let clientId = req.id;
    try {
        const options = {
            method: "POST",
            url: process.env.CASHFREE_PAYOUT_AUTH_URL,
            headers: {
                "Content-Type": req.headers["content-type"] || "application/json",
                "x-client-id": req.headers["x-client-id"] as string,
                "x-client-secret": req.headers["x-client-secret"] as string,
                "x-api-version": req.headers["x-api-version"] || "2024-01-01",
            },
        };

        try {
            const response = await axios.request(options);
            let token = response?.data?.data?.token;
            log.info(`[${U}], [${F}], [${F}], [DEB], [Auth], CF Token [${token}]`);

            if (response?.data?.status !== "SUCCESS" || !token) {
                log.info(`[${U}], [${F}], [ERR], [Auth], Client Id [${clientId}], Auth Resp  [${response?.data}], Authentication failed`);
                return res.status(response.status).json(response.data);
            } else {
                const balOptions = {
                    method: "GET",
                    url: process.env.CASHFREE_PAYOUT_GET_BAL_URL,
                    headers: {
                        "Content-Type": "application/json",
                        "Authorization": `Bearer ${token}`
                    },
                };
                try {
                    const balResponse = await axios.request(balOptions);
                    log.info(`[${U}], [${F}], [DEB], [Balance], Client Id [${clientId}], Auth Resp  [${JSON.stringify(balResponse.data)}]`);
                    return res.status(balResponse.status).json(balResponse.data);
                } catch (err: any) {
                    log.info(`[${F}], [${F}], [ERR], [BAL], Client Id [${clientId}], Cashfree Error [${err.response?.data || err.message}]`);
                    return res.status(400).json(err.response?.data || err.message);
                }
            }
        } catch (err: any) {
            log.info(`[${U}], [${F}], [ERR], Client Id [${clientId}], Cashfree Error [${err.response?.data || err.message}]`);
            return res.status(400).json(err.response?.data || err.message);
        }
    } catch (err: any) {
        log.info(`[${U}], [${F}], [ERR], Client Id [${clientId}],  Error [${JSON.stringify(err.response.data || err.message)}]`);
        return res.status(400).json(err.response?.data || err.message);
    }

};



cashfree.callback = async (req: CustomRequest, res: Response) => {

    const U = `cashfree`;
    const F = `callback`;
    try {
        const options = {
            method: "POST",
            url: `${process.env.PAYOUT_CALLBACK}`,
            headers: {
                "Content-Type": req.headers["content-type"] || "application/json",
            },
            data: req.body,
        };

        log.info(`[${U}], [${F}], [DEB], Request payload [${JSON.stringify(options)}]`);
        const response = await axios.request(options);
        log.info(`[${U}], [${F}], [DEB], Response [${JSON.stringify(response.data)}]`);
        res.status(200).json({ msg: "Success" });
    } catch (err: any) {
        log.info(`[${U}], [${F}], Error Payout [${err.stack}]`);
        res.status(200).json({ msg: "Success" });
    }

};

cashfree.verifyAccount = async (req: CustomRequest, res: Response) => {
    const U = `cashfree`;
    const F = `verifyAccount`;
    let clientId = req.id;
    try {
        const options = {
            method: "POST",
            url: `${process.env.CASHFREE_API_BASE_URL}/verification/bank-account/sync`,
            headers: {
                "Content-Type": req.headers["content-type"] || "application/json",
                "x-client-id": req.headers["x-client-id"] as string,
                "x-client-secret": req.headers["x-client-secret"] as string,
            },
            data: req.body,
        };
        log.info(`[${U}], [${F}], [DEB], Client Id [${clientId}], Request payload [${JSON.stringify(options)}]`);
        const response = await axios.request(options);
        log.info(`[${U}], [${F}], [DEB], Client Id [${clientId}], Response [${JSON.stringify(response.data)}]`);
        return res.status(response.status).json(response.data);
    } catch (err: any) {
        log.info(`[${U}], [${F}], [ERR], Client Id [${clientId}],  Error [${JSON.stringify(err.response?.data || err.message)}]`);
        return res.status(400).json(err.response?.data || err.message);
    }
};

cashfree.createDgLockerLink = async (req: CustomRequest, res: Response) => {
    const U = `cashfree`;
    const F = `createDgLockerLink`;
    let clientId = req.id;
    try {
        const options = {
            method: "POST",
            url: `${process.env.CASHFREE_AADHAAR_DIGILOCKER}`,
            headers: {
                "Content-Type": req.headers["content-type"] || "application/json",
                "x-client-id": req.headers["x-client-id"] as string,
                "x-client-secret": req.headers["x-client-secret"] as string,
            },
            data: req.body,
        };
        log.info(`[${U}], [${F}], [DEB], Client Id [${clientId}], Request payload [${JSON.stringify(options)}]`);
        const response = await axios.request(options);
        log.info(`[${U}], [${F}], [DEB], Client Id [${clientId}], Response [${JSON.stringify(response.data)}]`);
        return res.status(response.status).json(response.data);
    } catch (err: any) {
        log.info(`[${U}], [${F}], [ERR], Client Id [${clientId}],  Error [${JSON.stringify(err.response?.data || err.message)}]`);
        return res.status(400).json(err.response?.data || err.message);
    }
};

cashfree.verifyDgLockerLink = async (req: CustomRequest, res: Response) => {
    const U = `cashfree`;
    const F = `verifyDgLockerLink`;
    let clientId = req.id;

    try {
        const options = {
            method: "GET",
            url: `${process.env.CASHFREE_AADHAAR_DIGILOCKER}`,
            headers: {
                "Content-Type": req.headers["content-type"] || "application/json",
                "x-client-id": req.headers["x-client-id"] as string,
                "x-client-secret": req.headers["x-client-secret"] as string,
            },
            params: req.query
        };
        log.info(`[${U}], [${F}], [DEB], Client Id [${clientId}], Request payload [${JSON.stringify(options)}]`);
        const response = await axios.request(options);
        log.info(`[${U}], [${F}], [DEB], Client Id [${clientId}], Response [${JSON.stringify(response.data)}]`);
        return res.status(response.status).json(response.data);
    } catch (err: any) {
        log.info(`[${U}], [${F}], [ERR], Client Id [${clientId}],  Error [${JSON.stringify(err.response?.data || err.message)}]`);
        return res.status(400).json(err.response?.data || err.message);
    }
};

cashfree.getDgLockerDoc = async (req: CustomRequest, res: Response) => {
    const U = `cashfree`;
    const F = `getDgLockerDoc`;
    let clientId = req.id;
    try {
        const options = {
            method: "GET",
            url: `${process.env.CASHFREE_AADHAAR_DIGILOCKER}/document/AADHAAR`,
            headers: {
                "Content-Type": req.headers["content-type"] || "application/json",
                "x-client-id": req.headers["x-client-id"] as string,
                "x-client-secret": req.headers["x-client-secret"] as string,
            },
            params: req.query
        };
        log.info(`[${U}], [${F}], [DEB], Client Id [${clientId}], Request payload [${JSON.stringify(options)}]`);
        const response = await axios.request(options);
        log.info(`[${U}], [${F}], [DEB], Client Id [${clientId}], Response [${JSON.stringify(response.data)}]`);
        return res.status(response.status).json(response.data);
    } catch (err: any) {
        log.info(`[${U}], [${F}], [ERR], Client Id [${clientId}],  Error [${JSON.stringify(err.response?.data || err.message)}]`);
        return res.status(400).json(err.response?.data || err.message);
    }
};

cashfree.uploadAadhar = async (req: CustomRequest, res: Response) => {
    const U = `cashfree`;
    const F = `uploadAadhar`;
    let clientId = req.id;
    try {
        const form = new FormData();

        // Forward multiple files
        const files = req.files as Express.Multer.File[];

        // Forward multiple files
        for (const file of files || []) {
            form.append(file.fieldname, fs.createReadStream(file.path), {
                filename: file.originalname,
                contentType: file.mimetype,
                knownLength: file.size
            });
        }

        // Forward text parameters
        for (const [key, value] of Object.entries(req.body)) {
            if (Array.isArray(value)) {
                value.forEach(item => form.append(key, String(item)));
            } else {
                form.append(key, String(value));
            }
        }

        const response = await axios.post(
            process.env.CASHFREE_AADHAAR_OCR_API!,
            form,
            {
                headers: {
                    ...form.getHeaders(),
                    "x-client-id": req.headers["x-client-id"] as string,
                    "x-client-secret": req.headers["x-client-secret"] as string,
                    "x-api-version": "2024-12-01"
                },
                maxBodyLength: Infinity,
                maxContentLength: Infinity
            }
        );
        log.info(`[${U}], [${F}], [DEB], Client Id [${clientId}], Response [${JSON.stringify(response.data)}]`);
        return res.status(response.status).json(response.data);

    } catch (err: unknown) {
        if (axios.isAxiosError(err)) {
            log.info(`[${U}], [${F}], [ERR], Client Id [${clientId}],  Error [${JSON.stringify(err.response?.data || err.message)}]`);
            return res.status(err.response?.status || 500).json(
                err.response?.data || {
                    message: err.message
                }
            );
        }

        return res.status(500).json({
            message: "Something went wrong"
        });
    }
};



export default cashfree;
