const db = require('../db/models');
const Vat_declarationsDBApi = require('../db/api/vat_declarations');
const processFile = require("../middlewares/upload");
const ValidationError = require('./notifications/errors/validation');
const csv = require('csv-parser');
const axios = require('axios');
const config = require('../config');
const stream = require('stream');





module.exports = class Vat_declarationsService {
  static async create(data, currentUser) {
    const transaction = await db.sequelize.transaction();
    try {
      await Vat_declarationsDBApi.create(
        data,
        {
          currentUser,
          transaction,
        },
      );

      await transaction.commit();
    } catch (error) {
      await transaction.rollback();
      throw error;
    }
  };

  static async bulkImport(req, res, sendInvitationEmails = true, host) {
    const transaction = await db.sequelize.transaction();

    try {
      await processFile(req, res);
      const bufferStream = new stream.PassThrough();
      const results = [];

      await bufferStream.end(Buffer.from(req.file.buffer, "utf-8")); // convert Buffer to Stream

      await new Promise((resolve, reject) => {
        bufferStream
          .pipe(csv())
          .on('data', (data) => results.push(data))
          .on('end', async () => {
            console.log('CSV results', results);
            resolve();
          })
          .on('error', (error) => reject(error));
      })

      await Vat_declarationsDBApi.bulkImport(results, {
          transaction,
          ignoreDuplicates: true,
          validate: true,
          currentUser: req.currentUser
      });

      await transaction.commit();
    } catch (error) {
      await transaction.rollback();
      throw error;
    }
  }

  static async update(data, id, currentUser) {
    const transaction = await db.sequelize.transaction();
    try {
      let vat_declarations = await Vat_declarationsDBApi.findBy(
        {id},
        {transaction},
      );

      if (!vat_declarations) {
        throw new ValidationError(
          'vat_declarationsNotFound',
        );
      }

      const updatedVat_declarations = await Vat_declarationsDBApi.update(
        id,
        data,
        {
          currentUser,
          transaction,
        },
      );

      await transaction.commit();
      return updatedVat_declarations;

    } catch (error) {
      await transaction.rollback();
      throw error;
    }
  };

  static async deleteByIds(ids, currentUser) {
    const transaction = await db.sequelize.transaction();

    try {
      await Vat_declarationsDBApi.deleteByIds(ids, {
        currentUser,
        transaction,
      });

      await transaction.commit();
    } catch (error) {
      await transaction.rollback();
      throw error;
    }
  }

  static async remove(id, currentUser) {
    const transaction = await db.sequelize.transaction();

    try {
      await Vat_declarationsDBApi.remove(
        id,
        {
          currentUser,
          transaction,
        },
      );

      await transaction.commit();
    } catch (error) {
      await transaction.rollback();
      throw error;
    }
  }

  static async getErcaData(id, currentUser) {
    const vatDeclaration = await db.vat_declarations.findByPk(id, {
      include: [
        { model: db.tax_periods, as: 'tax_period' },
        { model: db.merchants, as: 'merchant' }
      ]
    });

    if (!vatDeclaration) {
      throw new ValidationError('vat_declarationsNotFound');
    }

    const { tax_period, merchant, merchantId } = vatDeclaration;
    const { start_date, end_date } = tax_period;

    const salesLines = await db.sales_invoice_lines.findAll({
      include: [
        {
          model: db.sales_invoices,
          as: 'sales_invoice',
          where: {
            merchantId,
            invoice_date: {
              [db.Sequelize.Op.between]: [start_date, end_date]
            }
          }
        }
      ]
    });

    const purchaseLines = await db.purchase_invoice_lines.findAll({
      include: [
        {
          model: db.purchase_invoices,
          as: 'purchase_invoice',
          where: {
            merchantId,
            invoice_date: {
              [db.Sequelize.Op.between]: [start_date, end_date]
            }
          }
        }
      ]
    });

    const ercaData = {
      merchant: merchant,
      tax_period: tax_period,
      sectionA: {
        line5: { total: 0, vat: 0 }, // Taxable Sales
        line15: { total: 0 },        // Zero-rated Sales
        line20: { total: 0 },        // Tax-exempt Sales
        line25: { total: 0 },        // Reverse Taxation
        line35: { total: 0, vat: 0 }, // Debit note adjustment
        line45: { total: 0, vat: 0 }, // Credit note adjustment
        line55: { total: 0 },        // Total Sales
        line60: { vat: 0 }           // Total Output VAT
      },
      sectionB: {
        line65: { total: 0, vat: 0 }, // Local Capital Purchase
        line75: { total: 0, vat: 0 }, // Imported Capital Purchase
        line85: { total: 0 },        // Capital Purchase no VAT
        line90: { total: 0, vat: 0 }  // Total Capital Purchases
      }
    };

    salesLines.forEach(line => {
      const amount = parseFloat(line.line_subtotal) || 0;
      const vat = parseFloat(line.vat_amount) || 0;

      if (line.vat_treatment === 'standard_15') {
        ercaData.sectionA.line5.total += amount;
        ercaData.sectionA.line5.vat += vat;
      } else if (line.vat_treatment === 'zero_rated') {
        ercaData.sectionA.line15.total += amount;
      } else if (line.vat_treatment === 'exempt') {
        ercaData.sectionA.line20.total += amount;
      }
    });

    // Formulas for Section A
    ercaData.sectionA.line55.total =
      ercaData.sectionA.line5.total +
      ercaData.sectionA.line15.total +
      ercaData.sectionA.line20.total +
      ercaData.sectionA.line25.total +
      ercaData.sectionA.line35.total -
      ercaData.sectionA.line45.total;

    ercaData.sectionA.line60.vat =
      ercaData.sectionA.line5.vat +
      ercaData.sectionA.line35.vat -
      ercaData.sectionA.line45.vat;

    // Formulas for Section B (Total)
    ercaData.sectionB.line90.total =
      ercaData.sectionB.line65.total +
      ercaData.sectionB.line75.total +
      ercaData.sectionB.line85.total;

    ercaData.sectionB.line90.vat =
      ercaData.sectionB.line65.vat +
      ercaData.sectionB.line75.vat;

    return ercaData;
  }
};