package cn.nianxx.thhotel.workflows.reservation.service.impl;

import static org.assertj.core.api.Assertions.assertThat;

import cn.nianxx.thhotel.workflows.reservation.common.request.ReservationInvoiceBookingRequest;
import cn.nianxx.thhotel.workflows.reservation.common.request.ReservationInvoiceChargeRequest;
import cn.nianxx.thhotel.workflows.reservation.common.request.ReservationInvoiceDocumentRequest;
import cn.nianxx.thhotel.workflows.reservation.common.request.ReservationInvoiceManualGenerationRequest;
import cn.nianxx.thhotel.workflows.reservation.common.request.ReservationInvoicePayloadRequest;
import cn.nianxx.thhotel.workflows.reservation.common.request.ReservationInvoiceRecipientRequest;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDate;
import java.util.List;
import org.apache.poi.ss.usermodel.PrintSetup;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.jupiter.api.Test;

class ReservationInvoiceExcelTemplateRendererTest {

    private final ReservationInvoiceExcelTemplateRenderer renderer = new ReservationInvoiceExcelTemplateRenderer();

    @Test
    void shouldRenderSinglePageA4InvoiceWithExpectedCells() throws Exception {
        byte[] workbookBytes = renderer.render(validRequest());
        writeSampleWhenRequested(workbookBytes);

        try (XSSFWorkbook workbook = new XSSFWorkbook(new ByteArrayInputStream(workbookBytes))) {
            var sheet = workbook.getSheetAt(0);

            assertThat(workbook.getNumberOfSheets()).isEqualTo(1);
            assertThat(workbook.getPrintArea(0)).isEqualTo("'Proforma Invoice'!$A$1:$H$52");
            assertThat(sheet.getPrintSetup().getPaperSize()).isEqualTo(PrintSetup.A4_PAPERSIZE);
            assertThat(sheet.getPrintSetup().getScale()).isEqualTo((short) 55);

            assertThat(sheet.getRow(4).getCell(7).getStringCellValue()).isEqualTo("Date : 17/07/2026");
            assertThat(sheet.getRow(5).getCell(2).getStringCellValue()).isEqualTo("Khun Ann");
            assertThat(sheet.getRow(6).getCell(2).getStringCellValue())
                    .isEqualTo("LIAN TAI TRAVEL (THAILAND) CO., LTD.");
            assertThat(sheet.getRow(13).getCell(2).getStringCellValue()).isEqualTo("12/07/2026");
            assertThat(sheet.getRow(18).getCell(7).getStringCellValue()).isEqualTo("Due Date               : 22/07/2026");
            assertThat(sheet.getRow(19).getCell(3).getStringCellValue()).isEqualTo("GRP-DEMO-0802");
            assertThat(sheet.getRow(21).getCell(3).getStringCellValue()).isEqualTo("02/08/2026");
            assertThat(sheet.getRow(22).getCell(3).getStringCellValue()).isEqualTo("05/08/2026");

            assertThat(sheet.getRow(25).getCell(1).getStringCellValue()).isEqualTo("GRP-DEMO-0802");
            assertThat(sheet.getRow(25).getCell(3).getStringCellValue()).isEqualTo("Deluxe Room");
            assertThat(sheet.getRow(25).getCell(7).getCellFormula()).isEqualTo("E26*F26*G26");
            assertThat(sheet.getRow(35).getCell(7).getCellFormula()).isEqualTo("SUM(H26:H35)/1.07");
            assertThat(sheet.getRow(37).getCell(7).getCellFormula()).isEqualTo("SUM(H26:H35)");
        }
    }

    private void writeSampleWhenRequested(byte[] workbookBytes) throws IOException {
        if (!Boolean.getBoolean("reservation.invoice.writeSample")) {
            return;
        }
        Path outputPath = Path.of("target/reservation-invoice-renderer/proforma-invoice-renderer-sample.xlsx");
        Files.createDirectories(outputPath.getParent());
        Files.write(outputPath, workbookBytes);
    }

    private ReservationInvoiceManualGenerationRequest validRequest() {
        return new ReservationInvoiceManualGenerationRequest(
                "HOTEL-TEST",
                "MANUAL",
                null,
                null,
                "PROFORMA_INVOICE_V1",
                new ReservationInvoicePayloadRequest(
                        new ReservationInvoiceDocumentRequest(
                                LocalDate.of(2026, 7, 17),
                                LocalDate.of(2026, 7, 12),
                                LocalDate.of(2026, 7, 22)),
                        new ReservationInvoiceRecipientRequest(
                                "LIAN_TAI",
                                "LIAN_TAI_KHUN_ANN",
                                "LIAN TAI TRAVEL (THAILAND) CO., LTD.",
                                "Khun Ann",
                                "2/86 Rajpattana Road, Rajpattana, Sapansoong, Bangkok, TH, 10240",
                                "061-397-2675",
                                "op.liantaitravel@gmail.com"),
                        new ReservationInvoiceBookingRequest(
                                "GRP-DEMO-0802",
                                LocalDate.of(2026, 8, 2),
                                LocalDate.of(2026, 8, 5),
                                "includingBF",
                                new BigDecimal("1200")),
                        List.of(new ReservationInvoiceChargeRequest(
                                "GRP-DEMO-0802",
                                "Deluxe Room",
                                new BigDecimal("2"),
                                new BigDecimal("3000"),
                                new BigDecimal("3")))));
    }
}
