package controller

import (
	"bytes"
	"testing"
	"time"

	entity "gitlab.com/mbugroup/lti-api.git/internal/entities"

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

func TestBuildPurchaseExportWorkbookHeadersAndRows(t *testing.T) {
	content, err := buildPurchaseExportWorkbook([]entity.Purchase{
		buildPurchaseForExportTest(
			1,
			"PR-00011",
			"PO-00011",
			time.Date(2026, time.April, 22, 0, 0, 0, 0, time.UTC),
			"Supplier A",
			"Manager Purchase",
			nil,
			"catatan",
			[]entity.PurchaseItem{
				buildPurchaseItemForExportTest(11, "Pakan Starter", 1000000, "Location A"),
				buildPurchaseItemForExportTest(12, "Vitamin A", 350000, "Location B"),
				buildPurchaseItemForExportTest(11, "Pakan Starter", 0, ""),
			},
		),
		buildPurchaseForExportTest(
			2,
			"PR-00012",
			"",
			time.Time{},
			"Supplier B",
			"Manager Purchase",
			ptrApprovalAction(entity.ApprovalActionRejected),
			"",
			[]entity.PurchaseItem{
				buildPurchaseItemForExportTest(21, "Obat X", 75000, ""),
			},
		),
	})
	if err != nil {
		t.Fatalf("buildPurchaseExportWorkbook 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()

	expectedHeaders := map[string]string{
		"A1": "PR Number",
		"B1": "PO Number",
		"C1": "Tanggal PO",
		"D1": "Supplier",
		"E1": "Lokasi",
		"F1": "Status",
		"G1": "Grand Total",
		"H1": "Products",
		"I1": "Notes",
	}
	for cell, expected := range expectedHeaders {
		got, err := file.GetCellValue(purchaseExportSheetName, 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)
		}
	}

	assertPurchaseCellEquals(t, file, "A2", "PR-00011")
	assertPurchaseCellEquals(t, file, "B2", "PO-00011")
	assertPurchaseCellEquals(t, file, "C2", "22-04-2026")
	assertPurchaseCellEquals(t, file, "D2", "Supplier A")
	assertPurchaseCellEquals(t, file, "E2", "Location A")
	assertPurchaseCellEquals(t, file, "F2", "Manager Purchase")
	assertPurchaseCellEquals(t, file, "G2", "Rp 1.350.000")
	assertPurchaseCellEquals(t, file, "H2", "Pakan Starter, Vitamin A")
	assertPurchaseCellEquals(t, file, "I2", "catatan")

	assertPurchaseCellEquals(t, file, "A3", "PR-00012")
	assertPurchaseCellEquals(t, file, "B3", "-")
	assertPurchaseCellEquals(t, file, "C3", "-")
	assertPurchaseCellEquals(t, file, "E3", "-")
	assertPurchaseCellEquals(t, file, "F3", "Ditolak")
	assertPurchaseCellEquals(t, file, "G3", "Rp 75.000")
	assertPurchaseCellEquals(t, file, "H3", "Obat X")
	assertPurchaseCellEquals(t, file, "I3", "-")
}

func assertPurchaseCellEquals(t *testing.T, file *excelize.File, cell, expected string) {
	t.Helper()
	got, err := file.GetCellValue(purchaseExportSheetName, 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 buildPurchaseForExportTest(
	id uint,
	prNumber, poNumber string,
	poDate time.Time,
	supplierName, stepName string,
	action *entity.ApprovalAction,
	notes string,
	items []entity.PurchaseItem,
) entity.Purchase {
	var poNumberRef *string
	if poNumber != "" {
		poNumberRef = &poNumber
	}
	var poDateRef *time.Time
	if !poDate.IsZero() {
		poDateRef = &poDate
	}
	var notesRef *string
	if notes != "" {
		notesRef = &notes
	}

	return entity.Purchase{
		Id:       id,
		PrNumber: prNumber,
		PoNumber: poNumberRef,
		PoDate:   poDateRef,
		Notes:    notesRef,
		Supplier: entity.Supplier{
			Id:   id + 100,
			Name: supplierName,
		},
		LatestApproval: &entity.Approval{
			Id:       id + 1000,
			StepName: stepName,
			Action:   action,
		},
		Items: items,
	}
}

func buildPurchaseItemForExportTest(productID uint, productName string, totalPrice float64, locationName string) entity.PurchaseItem {
	item := entity.PurchaseItem{
		ProductId:  productID,
		TotalPrice: totalPrice,
		Product: &entity.Product{
			Id:   productID,
			Name: productName,
		},
	}

	if locationName != "" {
		locationID := productID + 1000
		warehouseID := productID + 500
		item.Warehouse = &entity.Warehouse{
			Id: warehouseID,
			Location: &entity.Location{
				Id:   locationID,
				Name: locationName,
			},
		}
	}

	return item
}

func ptrApprovalAction(value entity.ApprovalAction) *entity.ApprovalAction {
	return &value
}
