package de.assecutor.votianlt.service;

import de.assecutor.votianlt.model.invoices.CustomerInvoice;
import de.assecutor.votianlt.model.invoices.CustomerInvoiceData;
import de.assecutor.votianlt.model.invoices.CustomerInvoiceItem;
import org.springframework.stereotype.Service;

import com.itextpdf.html2pdf.HtmlConverter;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.time.LocalDate;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.Locale;

@Service
public class CustomerInvoiceService {

    public CustomerInvoice createCustomerInvoice(String customerId, String jobId) {
        CustomerInvoice invoice = new CustomerInvoice();

        // Set basic invoice details
        invoice.setInvoiceNumber("INV-" + System.currentTimeMillis());
        invoice.setInvoiceDate(LocalDate.now());
        invoice.setDeliveryDate(LocalDate.now());
        invoice.setDescription("Logistikdienstleistungen für Auftrag " + jobId);

        // Set sender details (your company)
        invoice.setSenderName("Assecutor GmbH");
        invoice.setSenderAddress("Hauptstraße 456");
        invoice.setSenderPostcode("12345");
        invoice.setSenderCity("Berlin");
        invoice.setSenderCountry("Deutschland");
        invoice.setSenderTaxNumber("12/345/67890");
        invoice.setSenderVatId("DE123456789");
        invoice.setSenderPhone("+49 30 12345678");
        invoice.setSenderEmail("info@assecutor.de");
        invoice.setSenderWebsite("https://www.assecutor.de");

        // Payment terms
        invoice.setPaymentTerms("Zahlbar innerhalb von 14 Tagen netto ohne Abzug.");
        invoice.setPaymentDueDate(LocalDate.now().plusDays(14));
        invoice.setIban("DE89 3704 0044 0532 0130 00");
        invoice.setBic("COBADEFFXXX");

        // Legal information
        invoice.setLegalNotes("Geschäftsführer: Max Mustermann | Registergericht: Berlin | HRB 123456");

        return invoice;
    }

    public CustomerInvoiceData createCustomerInvoiceData(String customerId, String jobId) {
        CustomerInvoiceData invoiceData = new CustomerInvoiceData();

        // Rechnungsdetails
        invoiceData.setInvoiceNumber("INV-" + System.currentTimeMillis());
        invoiceData.setInvoiceDate(LocalDate.now());
        invoiceData.setDeliveryDate(LocalDate.now());
        invoiceData.setDescription("Logistikdienstleistungen für Auftrag " + jobId);

        // Rechnungssteller (vollständige Angaben nach deutschem Recht)
        invoiceData.setSenderName("Assecutor GmbH");
        invoiceData.setSenderAddress("Hauptstraße 456");
        invoiceData.setSenderPostcode("12345");
        invoiceData.setSenderCity("Berlin");
        invoiceData.setSenderCountry("Deutschland");
        invoiceData.setSenderTaxNumber("12/345/67890");
        invoiceData.setSenderVatId("DE123456789");
        invoiceData.setSenderPhone("+49 30 12345678");
        invoiceData.setSenderEmail("info@assecutor.de");
        invoiceData.setSenderWebsite("https://www.assecutor.de");

        // Rechnungsempfänger
        invoiceData.setRecipientName("Max Mustermann");
        invoiceData.setRecipientCompany("Musterfirma GmbH");
        invoiceData.setRecipientAddress("Musterstraße 123");
        invoiceData.setRecipientPostcode("54321");
        invoiceData.setRecipientCity("Hamburg");
        invoiceData.setRecipientCountry("Deutschland");
        invoiceData.setRecipientVatId("DE987654321");

        // Rechnungsposten
        List<CustomerInvoiceItem> items = new ArrayList<>();
        BigDecimal vatRate = new BigDecimal("0.19"); // 19% MwSt.

        CustomerInvoiceItem item1 = new CustomerInvoiceItem(
            new BigDecimal("2"), "Std.", "Transportdienstleistung",
            new BigDecimal("85.00"), vatRate);
        CustomerInvoiceItem item2 = new CustomerInvoiceItem(
            new BigDecimal("1"), "Stk.", "Logistikkoordination",
            new BigDecimal("120.00"), vatRate);
        CustomerInvoiceItem item3 = new CustomerInvoiceItem(
            new BigDecimal("50"), "km", "Kilometergebühr",
            new BigDecimal("0.60"), vatRate);

        items.add(item1);
        items.add(item2);
        items.add(item3);
        invoiceData.setItems(items);

        // Beträge berechnen
        BigDecimal netAmount = items.stream()
            .map(CustomerInvoiceItem::getNetTotal)
            .reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal vatAmount = netAmount.multiply(vatRate);
        BigDecimal totalAmount = netAmount.add(vatAmount);

        invoiceData.setNetAmount(netAmount);
        invoiceData.setVatRate(vatRate);
        invoiceData.setVatAmount(vatAmount);
        invoiceData.setTotalAmount(totalAmount);

        // Zahlungsdetails
        invoiceData.setPaymentTerms("Zahlbar innerhalb von 14 Tagen netto ohne Abzug.");
        invoiceData.setPaymentDueDate(LocalDate.now().plusDays(14));
        invoiceData.setBankAccount("Assecutor GmbH");
        invoiceData.setIban("DE89 3704 0044 0532 0130 00");
        invoiceData.setBic("COBADEFFXXX");

        // Rechtliche Hinweise
        invoiceData.setLegalNotes("Geschäftsführer: Max Mustermann | Registergericht: Berlin | HRB 123456");

        return invoiceData;
    }
    
    public byte[] generateCustomerInvoicePdf() throws Exception {
        // Backward-compatible sample generation
        CustomerInvoiceData sampleData = createCustomerInvoiceData("customerId", "jobId");
        return generateCustomerInvoicePdf(sampleData);
    }

    /**
     * Generate a Customer Invoice PDF from provided data using the HTML template.
     */
    public byte[] generateCustomerInvoicePdf(CustomerInvoiceData data) throws Exception {
        // Read the HTML template
        String htmlContent = readCustomerInvoiceHtmlTemplate();

        // Fill HTML with provided data
        String filledHtml = fillCustomerInvoiceHtmlWithInvoiceData(htmlContent, data);

        // Generate PDF from HTML
        return generatePdfFromHtmlString(filledHtml);
    }

    private String readCustomerInvoiceHtmlTemplate() throws Exception {
        // Read the HTML template file from classpath (works in Docker/production)
        try (java.io.InputStream inputStream = getClass().getClassLoader()
                .getResourceAsStream("templates/customer_invoice.html")) {
            if (inputStream == null) {
                throw new java.io.IOException("Template file not found: templates/customer_invoice.html");
            }
            return new String(inputStream.readAllBytes(), java.nio.charset.StandardCharsets.UTF_8);
        }
    }

    private String fillCustomerInvoiceHtmlWithInvoiceData(String html, CustomerInvoiceData data) {
        String filledHtml = html;
        // Replace invoice header data
        filledHtml = filledHtml.replace("${invoiceData.invoiceNumber}", nvl(data.getInvoiceNumber()));
        filledHtml = filledHtml.replace("${invoiceData.invoiceDate}", nvl(data.getFormattedInvoiceDate()));
        filledHtml = filledHtml.replace("${invoiceData.deliveryDate}", nvl(data.getFormattedDeliveryDate()));
        filledHtml = filledHtml.replace("${invoiceData.description}", nvl(data.getDescription()));

        // Replace sender details (complete legal information)
        filledHtml = filledHtml.replace("${invoiceData.senderName}", nvl(data.getSenderName()));
        filledHtml = filledHtml.replace("${invoiceData.senderAddress}", nvl(data.getSenderAddress()));
        filledHtml = filledHtml.replace("${invoiceData.senderPostcode}", nvl(data.getSenderPostcode()));
        filledHtml = filledHtml.replace("${invoiceData.senderCity}", nvl(data.getSenderCity()));
        filledHtml = filledHtml.replace("${invoiceData.senderCountry}", nvl(data.getSenderCountry()));
        filledHtml = filledHtml.replace("${invoiceData.senderTaxNumber}", nvl(data.getSenderTaxNumber()));
        filledHtml = filledHtml.replace("${invoiceData.senderVatId}", nvl(data.getSenderVatId()));
        filledHtml = filledHtml.replace("${invoiceData.senderPhone}", nvl(data.getSenderPhone()));
        filledHtml = filledHtml.replace("${invoiceData.senderEmail}", nvl(data.getSenderEmail()));
        filledHtml = filledHtml.replace("${invoiceData.senderWebsite}", nvl(data.getSenderWebsite()));

        // Replace recipient details
        filledHtml = filledHtml.replace("${invoiceData.recipientName}", nvl(data.getRecipientName()));
        filledHtml = filledHtml.replace("${invoiceData.recipientCompany}", nvl(data.getRecipientCompany()));
        filledHtml = filledHtml.replace("${invoiceData.recipientAddress}", nvl(data.getRecipientAddress()));
        filledHtml = filledHtml.replace("${invoiceData.recipientPostcode}", nvl(data.getRecipientPostcode()));
        filledHtml = filledHtml.replace("${invoiceData.recipientCity}", nvl(data.getRecipientCity()));
        filledHtml = filledHtml.replace("${invoiceData.recipientCountry}", nvl(data.getRecipientCountry()));
        filledHtml = filledHtml.replace("${invoiceData.recipientVatId}", nvl(data.getRecipientVatId()));

        // Replace invoice items
        if (data.getItems() != null && !data.getItems().isEmpty()) {
            StringBuilder itemRows = new StringBuilder();
            for (CustomerInvoiceItem item : data.getItems()) {
                itemRows.append("<tr>");
                itemRows.append("<td style='text-align: center;'>")
                    .append(formatDecimal(item.getQuantity()))
                    .append(" ").append(nvl(item.getUnit()))
                    .append("</td>");
                itemRows.append("<td>").append(nvl(item.getDescription())).append("</td>");
                itemRows.append("<td style='text-align: right;'>")
                    .append(formatCurrency(item.getUnitPrice()))
                    .append("</td>");
                itemRows.append("<td style='text-align: right;'>")
                    .append(formatCurrency(item.getNetTotal()))
                    .append("</td>");
                itemRows.append("</tr>");
            }
            filledHtml = filledHtml.replace("<!-- ITEM_ROWS -->", itemRows.toString());
        }

        // Replace amounts
        filledHtml = filledHtml.replace("${invoiceData.netAmount}", nvl(data.getFormattedNetAmount()));
        filledHtml = filledHtml.replace("${invoiceData.vatRate}", nvl(data.getFormattedVatRate()));
        filledHtml = filledHtml.replace("${invoiceData.vatAmount}", nvl(data.getFormattedVatAmount()));
        filledHtml = filledHtml.replace("${invoiceData.totalAmount}", nvl(data.getFormattedTotalAmount()));

        // Replace payment details
        filledHtml = filledHtml.replace("${invoiceData.paymentTerms}", nvl(data.getPaymentTerms()));
        filledHtml = filledHtml.replace("${invoiceData.paymentDueDate}", nvl(data.getFormattedPaymentDueDate()));
        filledHtml = filledHtml.replace("${invoiceData.bankAccount}", nvl(data.getBankAccount()));
        filledHtml = filledHtml.replace("${invoiceData.iban}", nvl(data.getIban()));
        filledHtml = filledHtml.replace("${invoiceData.bic}", nvl(data.getBic()));

        // Replace legal notes
        filledHtml = filledHtml.replace("${invoiceData.legalNotes}", nvl(data.getLegalNotes()));
        filledHtml = filledHtml.replace("${invoiceData.reverseChargeNote}", nvl(data.getReverseChargeNote()));

        return filledHtml;
    }

    private String nvl(String value) {
        return value != null ? value : "";
    }

    private String formatCurrency(BigDecimal amount) {
        if (amount == null) return "0,00 €";
        return NumberFormat.getCurrencyInstance(Locale.GERMANY).format(amount);
    }

    private String formatDecimal(BigDecimal value) {
        if (value == null) return "0";
        return NumberFormat.getNumberInstance(Locale.GERMANY).format(value);
    }

    private byte[] generatePdfFromHtmlString(String htmlContent) throws Exception {
        // Create PDF using iText library
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        // Convert HTML to PDF using iText 8 HtmlConverter
        HtmlConverter.convertToPdf(htmlContent, baos);

        return baos.toByteArray();
    }
}
