import axios from "axios";
import CONSTANTS from "../config/constants";
import log from "../config/log";
import clientConfigDB from "../models/clientConfig.model";
import duesDB from "../models/dues.model";
import moveOutDB from "../models/moveOut.model";
import moveOutDuesDB from "../models/moveOutDues.model";
import occupancyDB from "../models/occupancy.model";
import transactionDB from "../models/transaction.model";
import occupanciesTypes from "../schemas/occupancy.schema";
import tallyDB from "../services/tally/tally.model";
import expenseDB from "../models/expense.model";
import propertyDB from "../models/property.model";

export const checkTallyOnlineStatus = async (
    clientId: number,
) => {
    const U = "Set Tally Status";
    const F = "setOccupancyTallyStatus";
  try {
    const isTallyEnabled = await clientConfigDB.getClientConfig({
      clientId,
      provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.INTERNAL,
      type: CONSTANTS.CLIENT_CONFIG_TYPE.INTERNAL.TALLY,
    });

    if (isTallyEnabled && Number(isTallyEnabled.value) === 1) {

      let tallyConfig = await tallyDB.getTallyConfigByClientId({
        clientId: Number(clientId),
      });

      if (!tallyConfig) {
        log.info(
          `[${F}], Client Id [${clientId}], Tally Config Not Found`
        );
        return false;
      }

      const xml = `
      <ENVELOPE>
        <HEADER>
          <TALLYREQUEST>Export Data</TALLYREQUEST>
        </HEADER>
        <BODY>
          <EXPORTDATA>
            <REQUESTDESC>
              <REPORTNAME>List of Accounts</REPORTNAME>
              <STATICVARIABLES>
                <SVEXPORTFORMAT>$$SysName:XML</SVEXPORTFORMAT>
                <ACCOUNTTYPE>Companies</ACCOUNTTYPE>
              </STATICVARIABLES>
            </REQUESTDESC>
          </EXPORTDATA>
        </BODY>
      </ENVELOPE>`

      const response = await axios.post(`http://${tallyConfig.ip}:${tallyConfig.port}`, xml, {
        headers: { "Content-Type": "text/xml" },
        timeout: 1000,
      });

      return true;
    } else {
      return false;
    }
  } catch (error: any) {
    log.info(
      `[${F}], Client Id [${clientId}], Error: ${
        JSON.stringify(error?.response?.data) || error?.message || error
      }`,
    );

    return false;
  }
};

export const setOccupancyTallyStatus = async (
    clientId: number,
    occupancy: occupanciesTypes,
    status: number,
) => {
    const U = "Set Tally Status";
    const F = "setOccupancyTallyStatus";
  try {
    const isTallyEnabled = await clientConfigDB.getClientConfig({
      clientId,
      provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.INTERNAL,
      type: CONSTANTS.CLIENT_CONFIG_TYPE.INTERNAL.TALLY,
    });

    if (isTallyEnabled && Number(isTallyEnabled.value) === 1) {
      await occupancyDB.updateTallyStatus({
        id: occupancy.id,
        tallyStatus: status,
      });
    }

    return true;
  } catch (error: any) {
    log.info(
      `[${F}], Client Id [${clientId}], Error: ${
        JSON.stringify(error?.response?.data) || error?.message || error
      }`,
    );

    return false;
  }
};

export const syncOccupancyTallyStatus = async (
    clientId: number,
) => {
    const U = "Set Tally Status";
    const F = "setOccupancyTallyStatus";
  try {
    const isTallyEnabled = await clientConfigDB.getClientConfig({
      clientId,
      provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.INTERNAL,
      type: CONSTANTS.CLIENT_CONFIG_TYPE.INTERNAL.TALLY,
    });

    if (isTallyEnabled && Number(isTallyEnabled.value) === 1) {
      await occupancyDB.syncOccupancyTally({
        clientId,
      });
    }

    return true;
  } catch (error: any) {
    log.info(
      `[${F}], Client Id [${clientId}], Error: ${
        JSON.stringify(error?.response?.data) || error?.message || error
      }`,
    );

    return false;
  }
};

export const setDueTallyStatus = async (
    clientId: number,
    dueId: number,
    status: number,
) => {
    const U = "Set Tally Status";
    const F = "setDueTallyStatus";
  try {
    const isTallyEnabled = await clientConfigDB.getClientConfig({
      clientId,
      provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.INTERNAL,
      type: CONSTANTS.CLIENT_CONFIG_TYPE.INTERNAL.TALLY,
    });

    if (isTallyEnabled && Number(isTallyEnabled.value) === 1) {
      await duesDB.updateTallyStatus({
        id: dueId,
        tallyStatus: status,
      });
    }

    return true;
  } catch (error: any) {
    log.info(
      `[${F}], Client Id [${clientId}], Error: ${
        JSON.stringify(error?.response?.data) || error?.message || error
      }`,
    );

    return false;
  }
};

export const setMoveOutDueTallyStatus = async (
    clientId: number,
    dueId: number,
    status: number,
) => {
    const U = "Set Tally Status";
    const F = "setMoveOutDueTallyStatus";
  try {
    const isTallyEnabled = await clientConfigDB.getClientConfig({
      clientId,
      provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.INTERNAL,
      type: CONSTANTS.CLIENT_CONFIG_TYPE.INTERNAL.TALLY,
    });

    if (isTallyEnabled && Number(isTallyEnabled.value) === 1) {
      await moveOutDuesDB.updateTallyStatus({
        id: dueId,
        tallyStatus: status,
      });
    }

    return true;
  } catch (error: any) {
    log.info(
      `[${F}], Client Id [${clientId}], Error: ${
        JSON.stringify(error?.response?.data) || error?.message || error
      }`,
    );

    return false;
  }
};

export const syncDuesTallyStatus = async (
    clientId: number,
) => {
    const U = "Set Tally Status";
    const F = "syncDuesTallyStatus";
  try {
    const isTallyEnabled = await clientConfigDB.getClientConfig({
      clientId,
      provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.INTERNAL,
      type: CONSTANTS.CLIENT_CONFIG_TYPE.INTERNAL.TALLY,
    });

    if (isTallyEnabled && Number(isTallyEnabled.value) === 1) {
      await duesDB.syncDuesTally({
        clientId,
      });
      
      await moveOutDuesDB.syncDuesTally({
        clientId,
      });
    }

    return true;
  } catch (error: any) {
    log.info(
      `[${F}], Client Id [${clientId}], Error: ${
        JSON.stringify(error?.response?.data) || error?.message || error
      }`,
    );

    return false;
  }
};

export const setTransactionTallyStatus = async (
    clientId: number,
    transactionId: number,
    status: number,
) => {
    const U = "Set Tally Status";
    const F = "setTransactionTallyStatus";
  try {
    const isTallyEnabled = await clientConfigDB.getClientConfig({
      clientId,
      provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.INTERNAL,
      type: CONSTANTS.CLIENT_CONFIG_TYPE.INTERNAL.TALLY,
    });

    if (isTallyEnabled && Number(isTallyEnabled.value) === 1) {
      await transactionDB.updateTallyStatus({
        id: transactionId,
        tallyStatus: status,
      });
    }

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

    return false;
  }
};

export const setTransactionTallyBillRef = async (
  clientId: number,
  transactionId: number,
  tallyBillRef: string,
) => {
  const U = "Set Tally Status";
  const F = "setTransactionTallyBillRef";
  try {
    const isTallyEnabled = await clientConfigDB.getClientConfig({
      clientId,
      provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.INTERNAL,
      type: CONSTANTS.CLIENT_CONFIG_TYPE.INTERNAL.TALLY,
    });
    
    if (isTallyEnabled && Number(isTallyEnabled.value) === 1) {
      await transactionDB.updateTallyBillRef({
        id: transactionId,
        tallyBillRef: tallyBillRef,
      });
    }
    
    return true;
  } catch (error: any) {
    log.info(
      `[${F}], Client Id [${clientId}], Error: ${
        JSON.stringify(error?.response?.data) || error?.message || error
      }`,
    );
    
    return false;
  }
};

export const setTransactionTallyStatusByGId = async (
  clientId: number,
  gId: string,
  status: number,
) => {
  const U = "Set Tally Status";
  const F = "setTransactionTallyStatusByGId";
  try {
    const isTallyEnabled = await clientConfigDB.getClientConfig({
      clientId,
      provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.INTERNAL,
      type: CONSTANTS.CLIENT_CONFIG_TYPE.INTERNAL.TALLY,
    });

    if (isTallyEnabled && Number(isTallyEnabled.value) === 1) {
      await transactionDB.updateTallyStatusByGId({
        gId: gId,
        tallyStatus: status,
      });
    }
    
    return true;
  } catch (error: any) {
    log.info(
      `[${F}], Client Id [${clientId}], Error: ${
        JSON.stringify(error?.response?.data) || error?.message || error
      }`,
    );
    
    return false;
  }
};

export const syncTransactionTallyStatus = async (
  clientId: number,
) => {
  const U = "Set Tally Status";
  const F = "syncTransactionTallyStatus";
  try {
    const isTallyEnabled = await clientConfigDB.getClientConfig({
      clientId,
      provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.INTERNAL,
      type: CONSTANTS.CLIENT_CONFIG_TYPE.INTERNAL.TALLY,
    });
    
    if (isTallyEnabled && Number(isTallyEnabled.value) === 1) {
      await transactionDB.syncTransactionTally({
        clientId,
      });
    }
    
    return true;
  } catch (error: any) {
    log.info(
      `[${F}], [${U}], Client Id [${clientId}], Error: ${
        JSON.stringify(error?.response?.data) || error?.message || error
      }`,
    );
    
    return false;
  }
};

export const setExpenseJournalTallyStatus = async (
    clientId: number,
    expenseId: number,
    status: number,
) => {
    const U = "Set Tally Status";
    const F = "setExpenseJournalTallyStatus";
  try {
    const isTallyEnabled = await clientConfigDB.getClientConfig({
      clientId,
      provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.INTERNAL,
      type: CONSTANTS.CLIENT_CONFIG_TYPE.INTERNAL.TALLY,
    });

    if (isTallyEnabled && Number(isTallyEnabled.value) === 1) {
      await expenseDB.updateExpenseJournalTallyDetails({
        id: expenseId,
        tallyJournalStatus: status,
      });
    }

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

    return false;
  }
};

export const setExpensePaymentTallyStatus = async (
    clientId: number,
    expenseId: number,
    status: number,
) => {
    const U = "Set Tally Status";
    const F = "setExpensePaymentTallyStatus";
  try {
    const isTallyEnabled = await clientConfigDB.getClientConfig({
      clientId,
      provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.INTERNAL,
      type: CONSTANTS.CLIENT_CONFIG_TYPE.INTERNAL.TALLY,
    });

    if (isTallyEnabled && Number(isTallyEnabled.value) === 1) {
      await expenseDB.updateExpensePaymentTallyStatus({
        id: expenseId,
        tallyPaymentStatus: status,
      });
    }

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

    return false;
  }
};

export const syncExpenseJournalTally = async (
    clientId: number,
) => {
    const U = "Set Tally Status";
    const F = "syncExpenseJournalTally";
  try {
    const isTallyEnabled = await clientConfigDB.getClientConfig({
      clientId,
      provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.INTERNAL,
      type: CONSTANTS.CLIENT_CONFIG_TYPE.INTERNAL.TALLY,
    });

    if (isTallyEnabled && Number(isTallyEnabled.value) === 1) {
      await expenseDB.syncExpenseJournalTally({
        clientId,
      });
    }

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

    return false;
  }
};

export const syncExpensePaymentTally = async (
    clientId: number,
) => {
    const U = "Set Tally Status";
    const F = "syncExpensePaymentTally";
  try {
    const isTallyEnabled = await clientConfigDB.getClientConfig({
      clientId,
      provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.INTERNAL,
      type: CONSTANTS.CLIENT_CONFIG_TYPE.INTERNAL.TALLY,
    });

    if (isTallyEnabled && Number(isTallyEnabled.value) === 1) {
      await expenseDB.syncExpensePaymentTally({
        clientId,
      });
    }

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

    return false;
  }
};

export const setPropertyIncomeSecurityLedgerTally = async (
    clientId: number,
    propertyId: number,
    status: number,
) => {
    const U = "Set Tally Status";
    const F = "setPropertyIncomeSecurityLedgerTally";
  try {
    const isTallyEnabled = await clientConfigDB.getClientConfig({
      clientId,
      provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.INTERNAL,
      type: CONSTANTS.CLIENT_CONFIG_TYPE.INTERNAL.TALLY,
    });

    if (isTallyEnabled && Number(isTallyEnabled.value) === 1) {
      await propertyDB.updatePropertyTallyStatus({
        id: propertyId,
        tallyStatus: status,
      });
    }

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

    return false;
  }
};

export const syncPropertyIncomeSecurityLedgerTally = async (
    clientId: number,
) => {
    const U = "Set Tally Status";
    const F = "syncPropertyIncomeSecurityLedgerTally";
  try {
    const isTallyEnabled = await clientConfigDB.getClientConfig({
      clientId,
      provider: CONSTANTS.CLIENT_CONFIG_PROVIDER.INTERNAL,
      type: CONSTANTS.CLIENT_CONFIG_TYPE.INTERNAL.TALLY,
    });

    if (isTallyEnabled && Number(isTallyEnabled.value) === 1) {
      await propertyDB.syncPropertyIncomeSecurityLedgerTally({
        clientId,
      });
    }

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

    return false;
  }
};
