package controller

import (
	"bytes"
	"testing"
	"time"

	approvalDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/approvals/dto"
	"gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/dto"
	locationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/locations/dto"
	supplierDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/suppliers/dto"

	"github.com/xuri/excelize/v2"
)

func TestBuildExpenseExportWorkbookHeadersAndRows(t *testing.T) {
	realizationDate := time.Date(2026, time.April, 22, 0, 0, 0, 0, time.UTC)

	content, err := buildExpenseExportWorkbook([]dto.ExpenseListDTO{
		{
			ExpenseBaseDTO: dto.ExpenseBaseDTO{
				PoNumber:        "PO-00011",
				ReferenceNumber: "EXP-00011",
				RealizationDate: &realizationDate,
				TransactionDate: time.Date(2026, time.April, 22, 0, 0, 0, 0, time.UTC),
				Category:        "BOP",
				Supplier: &supplierDTO.SupplierRelationDTO{
					Name: "Supplier A",
				},
				Location: &locationDTO.LocationRelationDTO{
					Name: "Farm A",
				},
			},
			GrandTotal: 1234567,
			LatestApproval: &approvalDTO.ApprovalRelationDTO{
				StepName: "Finance",
			},
		},
		{
			ExpenseBaseDTO: dto.ExpenseBaseDTO{
				PoNumber:        "",
				ReferenceNumber: "",
				Category:        "",
			},
			GrandTotal: 75000,
			LatestApproval: &approvalDTO.ApprovalRelationDTO{
				StepName: "Head Area",
				Action:   expenseStrPtr("REJECTED"),
			},
		},
		{
			ExpenseBaseDTO: dto.ExpenseBaseDTO{},
			GrandTotal:     0,
			LatestApproval: nil,
		},
	})
	if err != nil {
		t.Fatalf("buildExpenseExportWorkbook returned error: %v", err)
	}

	file, err := excelize.OpenReader(bytes.NewReader(content))
	if err != nil {
		t.Fatalf("failed to open workbook bytes: %v", err)
	}
	defer file.Close()

	sheets := file.GetSheetList()
	if len(sheets) != 1 || sheets[0] != expenseExportSheetName {
		t.Fatalf("expected single sheet %q, got %+v", expenseExportSheetName, sheets)
	}

	expectedHeaders := map[string]string{
		"A1": "No",
		"B1": "No. PO",
		"C1": "No. Referensi",
		"D1": "Tanggal Realisasi",
		"E1": "Tanggal Transaksi",
		"F1": "Kategori",
		"G1": "Supplier",
		"H1": "Lokasi",
		"I1": "Grand Total",
		"J1": "Status",
	}
	for cell, expected := range expectedHeaders {
		got, err := file.GetCellValue(expenseExportSheetName, cell)
		if err != nil {
			t.Fatalf("GetCellValue(%s) failed: %v", cell, err)
		}
		if got != expected {
			t.Fatalf("expected %s=%q, got %q", cell, expected, got)
		}
	}

	assertExpenseCellEquals(t, file, "A2", "1")
	assertExpenseCellEquals(t, file, "B2", "PO-00011")
	assertExpenseCellEquals(t, file, "C2", "EXP-00011")
	assertExpenseCellEquals(t, file, "D2", "22-04-2026")
	assertExpenseCellEquals(t, file, "E2", "22-04-2026")
	assertExpenseCellEquals(t, file, "F2", "BOP")
	assertExpenseCellEquals(t, file, "G2", "Supplier A")
	assertExpenseCellEquals(t, file, "H2", "Farm A")
	assertExpenseCellEquals(t, file, "J2", "Finance")

	rawGrandTotal, err := file.GetCellValue(expenseExportSheetName, "I2", excelize.Options{RawCellValue: true})
	if err != nil {
		t.Fatalf("GetCellValue(I2, RawCellValue) failed: %v", err)
	}
	if rawGrandTotal != "1234567" {
		t.Fatalf("expected raw I2 grand total 1234567, got %q", rawGrandTotal)
	}

	assertExpenseCellEquals(t, file, "B3", "-")
	assertExpenseCellEquals(t, file, "C3", "-")
	assertExpenseCellEquals(t, file, "D3", "-")
	assertExpenseCellEquals(t, file, "E3", "-")
	assertExpenseCellEquals(t, file, "F3", "-")
	assertExpenseCellEquals(t, file, "G3", "-")
	assertExpenseCellEquals(t, file, "H3", "-")
	assertExpenseCellEquals(t, file, "J3", "Ditolak")

	assertExpenseCellEquals(t, file, "J4", "-")
}

func assertExpenseCellEquals(t *testing.T, file *excelize.File, cell, expected string) {
	t.Helper()
	got, err := file.GetCellValue(expenseExportSheetName, cell)
	if err != nil {
		t.Fatalf("GetCellValue(%s) failed: %v", cell, err)
	}
	if got != expected {
		t.Fatalf("expected %s=%q, got %q", cell, expected, got)
	}
}

func expenseStrPtr(value string) *string {
	return &value
}
