const PilonInvoices = require("../../models/PilonInvoices");
const PilonInvoicesFiles = require("../../models/PilonInvoicesFiles");
const PilonDataDumpLogs = require("../../models/PilonDataDumpLogs");
const { Op } = require("sequelize");
const sequelize = require("../../connection/db");
const axios = require("axios");

exports.getAllPilonInvoices = async (req, res, next) => {
  const {
    pageNumber = 1,
    pageSize = 20,
    filterField = "",
    filterValue = "",
  } = req.query;

  try {
    const offset = (pageNumber - 1) * pageSize;
    const limit = parseInt(pageSize);

    const validFields = Object.keys(PilonInvoices.rawAttributes);

    if (filterField && !validFields.includes(filterField)) {
      return res.status(400).json({
        success: false,
        message: `Invalid filter field: ${filterField}`,
      });
    }

    const whereCondition =
      filterField && filterValue
        ? { [filterField]: { [Op.like]: `%${filterValue}%` } }
        : {};

    const { rows, count } = await PilonInvoices.findAndCountAll({
      where: whereCondition,
      include: [
        {
          model: PilonInvoicesFiles,
          as: "files",
        },
      ],
      limit,
      offset,
      order: [["createdAt", "DESC"]],
    });

    res.status(200).json({
      success: true,
      data: rows,
      pagination: {
        totalRecords: count,
        currentPage: parseInt(pageNumber),
        totalPages: Math.ceil(count / pageSize),
      },
    });
  } catch (err) {
    next(err);
  }
};

const pilonInvoiceResponseMapper = (invoice) => ({
  id: invoice.id,
  amount: invoice.amount,
  invoiceNo: invoice.invoice_no,
  clienCode: invoice.clien_code,
  supplierCode: invoice.supplier_code,
  status: invoice.status,
  statusDescription: invoice.status_description,
  discountPercentage: invoice.discount_percentage,
  discountAmount: invoice.discount_amount,
  newPayee: invoice.new_payee,
  fundRequestDate: invoice.fund_request_date?.toISOString() || null,
  earlyPayDate: invoice.early_payment_date?.toISOString() || null,
  buyerpaymentDate: invoice.buyer_payment_date?.toISOString() || null,
  createdAt: invoice.createdAt?.toISOString(),
  updatedAt: invoice.updatedAt?.toISOString(),
});

exports.pilonPostReturnFile = async (req, res, next) => {
  const {
    amount = 0,
    invoiceNo,
    clienCode,
    supplierCode,
    status,
    statusDescription,
    discountPercentage,
    discountAmount = 0,
    newPayee,
    fundRequestDate,
    earlyPayDate,
    buyerpaymentDate,
  } = req.body;

  if (!invoiceNo || !clienCode || !supplierCode) {
    return res.status(400).json({
      success: false,
      message: "Missing required fields: invoiceNo, clienCode, or supplierCode",
    });
  }

  const transaction = await sequelize.transaction();

  try {
    const pilonInvoice = await PilonInvoices.create(
      {
        amount,
        invoice_no: invoiceNo,
        clien_code: clienCode,
        supplier_code: supplierCode,
        status,
        status_description: statusDescription,
        discount_percentage: discountPercentage,
        discount_amount: discountAmount,
        new_payee: newPayee,
        fund_request_date: fundRequestDate ? new Date(fundRequestDate) : null,
        early_payment_date: earlyPayDate ? new Date(earlyPayDate) : null,
        buyer_payment_date: buyerpaymentDate
          ? new Date(buyerpaymentDate)
          : null,
      },
      { transaction }
    );

    await transaction.commit();

    res.status(201).json({
      success: true,
      message: "Pilon invoice created successfully.",
      data: pilonInvoiceResponseMapper(pilonInvoice),
    });
  } catch (err) {
    await transaction.rollback();
    console.error("Error creating Pilon invoice:", err);
    next(err);
  }
};

exports.postInvoiceDocument = async (req, res, next) => {
  const CLIENT_ID = "60a7adcf-0f02-4a4a-889d-b747f532e643";
  const CLIENT_SECRET =
    "a97e05224c24a06902f365802231d25df0f5745286afd6ebcd90519d8b914ecc";
  const API_URL = "https://alon-df-api-prod.pilon.sg/v1/invoice/document";

  const { distributorCode, documentNo, docDate, dueDate, amount } = req.body;

  if (!distributorCode || !documentNo || !docDate || !dueDate || !amount) {
    return res.status(200).json({
      success: false,
      message:
        "Missing required fields: distributorCode, documentNo, docDate, dueDate, or amount",
    });
  }

  const transaction = await sequelize.transaction();

  try {
    const documents = [
      {
        distributor_code: distributorCode,
        document_no: documentNo,
        doc_date: docDate,
        due_date: dueDate,
        amount: amount,
      },
    ];

    const payload = { documents };

    const response = await axios.post(API_URL, payload, {
      headers: {
        "Content-Type": "application/json",
        "client-id": CLIENT_ID,
        "client-secret": CLIENT_SECRET,
      },
    });

    if (response?.data?.success) {
      await PilonDataDumpLogs.create(
        {
          distributorCode,
          documentNo,
          docDate,
          dueDate,
          amount,
          status: true,
          responseData: JSON.stringify(response.data),
        },
        { transaction }
      );
    } else {
      await PilonDataDumpLogs.create(
        {
          distributorCode,
          documentNo,
          docDate,
          dueDate,
          amount,
          status: false,
          responseData: JSON.stringify(response.data),
        },
        { transaction }
      );
    }

    await transaction.commit();
    res.status(200).json({ success: true });
  } catch (err) {
    await transaction.rollback();

    await PilonDataDumpLogs.create({
      distributorCode,
      documentNo,
      docDate,
      dueDate,
      amount,
      status: false,
      responseData: err.response
        ? JSON.stringify(err.response.data)
        : err.message,
    });

    if (err.response) {
      res.status(err.response.status || 500).json({
        success: false,
        message: "API request failed",
        error: err.response.data,
      });
    } else {
      res.status(500).json({
        success: false,
        message: "Request failed",
        error: err.message,
      });
    }
  }
};
