import log from "../config/log";
import CONSTANTS from "../config/constants";
import fs from "fs";
import fsPromises from "fs/promises";
import occupanciesTypes from "../schemas/occupancy.schema";
// @ts-ignore
import pdf from "pdf-creator-node";
import transactionDB from "../models/transaction.model";
import getRentReciptPoints from "./getRentReciptPoints";
import moment from "moment";
import { string } from "zod";
import settingsDB from "../models/settings.model";
import axios from "axios";
import clientDB from "../models/client.model";
import propertyDB from "../models/property.model";
import tenantDB from "../models/tenant.model";

const createGstReceipt = async (details: any) => {
  try {
    log.info(`[createGstReceipt], Details [${JSON.stringify(details)}]`);

    const { tenantId, clientId, propId, roomId, bedId } = details.occupancy;
    const { dueStats, paidDate, propName, flatName } = details;

    const client = await clientDB.getById({ id: clientId });
    if (!client) {
      log.info(`[createGstReceipt], Client Id [${clientId}], No Client Found`);
      return false;
    }

    const property = await propertyDB.getById({ id: propId });
    if (!property) {
      log.info(`[createGstReceipt], Property Id [${propId}], No Property Found`);
      return false;
    }

    const tenant = await tenantDB.getById({ id: tenantId });
    if (!tenant) {
      log.info(`[createGstReceipt], Tenant Id [${tenantId}], No Tenant Found`);
      return false;
    }

    let businessName = property?.businessName ? property?.businessName : client?.businessName ? client?.businessName : client?.name;
    let businessGstNo = property?.gstNo ? property?.gstNo : "";
    let businessSacCode = property?.sacCode ? property?.sacCode : "";
    let businessAddress = client?.businessAddress ? client?.businessAddress : property?.address;
    let businessMobile = property?.ownerMobile ? property?.ownerMobile : client?.mobile;
    let businessEmail = client?.businessEmail ? client?.businessEmail : "";
    let gstNo = details.gstNo;
    let businessState = property?.state ? property?.state : client?.state ? client?.state : "";
    let sacCode = property?.sacCode ? property?.sacCode : "";
    let tenantName = tenant?.name;
    let tenantBusinessAddress = tenant?.businessAddress || "";
    let tenantGstNo = tenant?.gstNo || "";
    let invoiceNo = details.transactionInvoiceNo;
    let gstCharges = details.gstCharges;
    let tenantPaid = details.amount;
    let totalAmount = tenantPaid - gstCharges;
    let totalAmountInWords = getIndianCurrency(totalAmount);
    let gstChargesInWords = getIndianCurrency(gstCharges);
    let propertyGst = property?.gstCharges ? (Number(property?.gstCharges) / 100).toFixed(2) : 0;
    let propertyName = propName + "," + flatName;

    let templatePath = `${process.env.UPLOAD_PATH}/documents/defaults/gst_receipt.html`;
    let { data: receiptHtml } = await axios.get(templatePath);

    receiptHtml = receiptHtml.replace(/{{businessName}}/g, businessName);
    receiptHtml = receiptHtml.replace(/{{businessGstNo}}/g, businessGstNo);
    receiptHtml = receiptHtml.replace(/{{businessSacCode}}/g, businessSacCode);
    receiptHtml = receiptHtml.replace(/{{businessAddress}}/g, businessAddress);
    receiptHtml = receiptHtml.replace(/{{businessMobile}}/g, businessMobile);
    receiptHtml = receiptHtml.replace(/{{businessEmail}}/g, businessEmail);
    receiptHtml = receiptHtml.replace(/{{gstNo}}/g, gstNo);
    receiptHtml = receiptHtml.replace(/{{businessState}}/g, businessState);
    receiptHtml = receiptHtml.replace(/{{sacCode}}/g, sacCode);
    receiptHtml = receiptHtml.replace(/{{tenantName}}/g, tenantName);
    receiptHtml = receiptHtml.replace(/{{tenantBusinessAddress}}/g, tenantBusinessAddress);
    receiptHtml = receiptHtml.replace(/{{tenantGstNo}}/g, tenantGstNo);
    receiptHtml = receiptHtml.replace(/{{collectionDate}}/g, moment(paidDate).format("DD-MM-YYYY"));
    receiptHtml = receiptHtml.replace(/{{invoiceNo}}/g, invoiceNo);
    receiptHtml = receiptHtml.replace(/{{propertyName}}/g, propertyName);

    let rows = "";
    let srNo = 1;
    dueStats.forEach((row: any, index: any) => {
      rows += `
            <tr style="height:220px; vertical-align:top;">
            <td style="border-bottom:1px solid #000;border-top:1px solid #000; border-right:1px solid #000;text-align:center;">${srNo}</td>

            <td style="border:1px solid #000; padding:5px;">
                <table>
                <tr><td style="padding:5px;">${row.title}</td></tr>
                </table>
            </td>

            <td style="border:1px solid #000; text-align:center;">${sacCode}</td>
            <td style="border:1px solid #000; text-align:center;">${property?.gstCharges}</td>
            <td style="border:1px solid #000; text-align:center;">1</td>
            <td style="border:1px solid #000;"></td>

            <td style="border:1px solid #000; text-align:right; padding:5px;">
                ${row.amount}
            </td>

            <td style="border:1px solid #000; text-align:right; padding:5px;">
                ${(Number(row.amount) * Number(propertyGst)).toFixed(2)}
            </td>

            <td style="border-bottom:1px solid #000;border-top:1px solid #000; border-left:1px solid #000; text-align:right; padding:5px;">
                ${Number(row.amount) + Number((Number(row.amount) * Number(propertyGst)).toFixed(2))}
            </td>
            </tr>
        `;
      srNo++;
    });

    receiptHtml = receiptHtml.replace(/{{tableRows}}/g, rows);

    receiptHtml = receiptHtml.replace(/{{taxInWords}}/g, gstChargesInWords);
    receiptHtml = receiptHtml.replace(/{{amountInWords}}/g, totalAmountInWords);
    receiptHtml = receiptHtml.replace(/{{totalAmount}}/g, totalAmount);
    receiptHtml = receiptHtml.replace(/{{cgst}}/g, (gstCharges/2).toFixed(2));
    receiptHtml = receiptHtml.replace(/{{sgst}}/g, (gstCharges/2).toFixed(2));
    receiptHtml = receiptHtml.replace(/{{tenantPaid}}/g, tenantPaid);

    const template = await propertyDB.getRentAgreementTemplate({
      clientId: clientId,
      propId: propId,
    });

    if (template) {
      receiptHtml = receiptHtml.replace(/{{signaturePath}}/g, template?.signaturePath ? template?.signaturePath : "");
    }

    const folderName = `tenant_${tenantId}`;
    const currentYear = moment().year();
    const folderPath = `uploads/documents/${currentYear}/receipt/client_${clientId}/prop_${propId}/room_${roomId}_bed_${bedId}/${folderName}`;

    if (!fs.existsSync(folderPath)) {
      await fsPromises.mkdir(folderPath, { recursive: true });
    }

    const urlBasePath = `${process.env.UPLOAD_PATH}/documents/${currentYear}/receipt/client_${clientId}/prop_${propId}/room_${roomId}_bed_${bedId}/${folderName}`;

    const filename = `GstReceipt_${moment(details.paidDate).format("YYYYMMDD")}_${bedId}_${new Date().getTime().toString().slice(5)}.pdf`;
    const url = `${urlBasePath}/${filename}`;

    var document = {
      html: receiptHtml,
      path: `${folderPath}/${filename}`,
      data: {},
      type: "",
    };

    const options = {
      format: "A4",
      orientation: "portrait",
      border: "10mm",
      childProcessOptions: {
        env: {
          OPENSSL_CONF: "/dev/null",
        },
      },
    };

    await pdf.create(document, options);

    return url;
  } catch (error: any) {
    log.info(
      `[createGstReceipt], Tenant Name [${details.tenantName}], Start Date [${details.paidDate}], Error: ${JSON.stringify(error?.response?.data) || error?.message || error}`,
    );
    return false;
  }
};

function getIndianCurrency(number: number) {
  let decimal = Math.round((number - Math.floor(number)) * 100);
  let no = Math.floor(number);
  let digits_length = no.toString().length;
  let i = 0;
  let str: (string | null)[] = [];
  let words: { [key: number]: string } = {
    0: "",
    1: "One",
    2: "Two",
    3: "Three",
    4: "Four",
    5: "Five",
    6: "Six",
    7: "Seven",
    8: "Eight",
    9: "Nine",
    10: "Ten",
    11: "Eleven",
    12: "Twelve",
    13: "Thirteen",
    14: "Fourteen",
    15: "Fifteen",
    16: "Sixteen",
    17: "Seventeen",
    18: "Eighteen",
    19: "Nineteen",
    20: "Twenty",
    30: "Thirty",
    40: "Forty",
    50: "Fifty",
    60: "Sixty",
    70: "Seventy",
    80: "Eighty",
    90: "Ninety",
  };
  let digits = ["", "Hundred", "Thousand", "Lakh", "Crore"];

  while (i < digits_length) {
    let divider = i == 2 ? 10 : 100;
    let numberPart: number = Math.floor(no % divider);
    no = Math.floor(no / divider);
    i += divider == 10 ? 1 : 2;

    if (numberPart) {
      let plural: string = str.length && numberPart > 9 ? "" : "";
      let hundred: string = str.length == 1 && str[0] ? " and " : "";
      str.push(
        numberPart < 21
          ? (words[numberPart] || "") +
              " " +
              digits[str.length] +
              " " +
              plural +
              hundred
          : (words[Math.floor(numberPart / 10) * 10] || "") +
              " " +
              (words[numberPart % 10] || "") +
              " " +
              digits[str.length] +
              " " +
              plural +
              hundred
      );
    } else {
      str.push(null);
    }
  }

  let Rupees = str.reverse().filter(Boolean).join("");
  let Paise =
    decimal > 0
      ? "." +
        ((words[Math.floor(decimal / 10)] || "") +
          " " +
          (words[decimal % 10] || "")) +
        " Paise"
      : "";
  return (Rupees ? Rupees + "Rupees " : "") + Paise;
}

export default createGstReceipt;
