package sync_test

import (
	"testing"
	"time"

	"git.mchus.pro/mchus/quoteforge/internal/localdb"
	"git.mchus.pro/mchus/quoteforge/internal/models"
	syncsvc "git.mchus.pro/mchus/quoteforge/internal/services/sync"
)

func TestSyncPricelists_BackfillsLotCategoryForUsedPricelistItems(t *testing.T) {
	local := newLocalDBForSyncTest(t)
	serverDB := newServerDBForSyncTest(t)

	if err := serverDB.AutoMigrate(
		&models.Pricelist{},
		&models.PricelistItem{},
		&models.Lot{},
		&models.StockLog{},
	); err != nil {
		t.Fatalf("migrate server tables: %v", err)
	}

	serverPL := models.Pricelist{
		Source:       "estimate",
		Version:      "2026-02-11-001",
		Notification: "server",
		CreatedBy:    "tester",
		IsActive:     true,
		CreatedAt:    time.Now().Add(-1 * time.Hour),
	}
	if err := serverDB.Create(&serverPL).Error; err != nil {
		t.Fatalf("create server pricelist: %v", err)
	}
	if err := serverDB.Create(&models.PricelistItem{
		PricelistID:  serverPL.ID,
		LotName:      "CPU_A",
		LotCategory:  "CPU",
		Price:        10,
		PriceMethod:  "",
		MetaPrices:   "",
		ManualPrice:  nil,
		AvailableQty: nil,
	}).Error; err != nil {
		t.Fatalf("create server pricelist item: %v", err)
	}

	if err := local.SaveLocalPricelist(&localdb.LocalPricelist{
		ServerID:  serverPL.ID,
		Source:    serverPL.Source,
		Version:   serverPL.Version,
		Name:      serverPL.Notification,
		CreatedAt: serverPL.CreatedAt,
		SyncedAt:  time.Now(),
		IsUsed:    false,
	}); err != nil {
		t.Fatalf("seed local pricelist: %v", err)
	}
	localPL, err := local.GetLocalPricelistByServerID(serverPL.ID)
	if err != nil {
		t.Fatalf("get local pricelist: %v", err)
	}

	if err := local.SaveLocalPricelistItems([]localdb.LocalPricelistItem{
		{
			PricelistID: localPL.ID,
			LotName:     "CPU_A",
			LotCategory: "",
			Price:       10,
		},
	}); err != nil {
		t.Fatalf("seed local pricelist items: %v", err)
	}

	if err := local.SaveConfiguration(&localdb.LocalConfiguration{
		UUID:             "cfg-1",
		OriginalUsername: "tester",
		Name:             "cfg",
		Items:            localdb.LocalConfigItems{{LotName: "CPU_A", Quantity: 1, UnitPrice: 10}},
		IsActive:         true,
		PricelistID:      &serverPL.ID,
		SyncStatus:       "synced",
		CreatedAt:        time.Now().Add(-30 * time.Minute),
		UpdatedAt:        time.Now().Add(-30 * time.Minute),
	}); err != nil {
		t.Fatalf("seed local configuration with pricelist ref: %v", err)
	}

	svc := syncsvc.NewServiceWithDB(serverDB, local)
	if _, err := svc.SyncPricelists(); err != nil {
		t.Fatalf("sync pricelists: %v", err)
	}

	items, err := local.GetLocalPricelistItems(localPL.ID)
	if err != nil {
		t.Fatalf("load local items: %v", err)
	}
	if len(items) != 1 {
		t.Fatalf("expected 1 local item, got %d", len(items))
	}
	if items[0].LotCategory != "CPU" {
		t.Fatalf("expected lot_category backfilled to CPU, got %q", items[0].LotCategory)
	}
}

func TestSyncPricelistItems_EnrichesStockFromLocalPartnumberBook(t *testing.T) {
	local := newLocalDBForSyncTest(t)
	serverDB := newServerDBForSyncTest(t)

	if err := serverDB.AutoMigrate(
		&models.Pricelist{},
		&models.PricelistItem{},
		&models.Lot{},
		&models.StockLog{},
	); err != nil {
		t.Fatalf("migrate server tables: %v", err)
	}

	serverPL := models.Pricelist{
		Source:       "warehouse",
		Version:      "2026-03-07-001",
		Notification: "server",
		CreatedBy:    "tester",
		IsActive:     true,
		CreatedAt:    time.Now().Add(-1 * time.Hour),
	}
	if err := serverDB.Create(&serverPL).Error; err != nil {
		t.Fatalf("create server pricelist: %v", err)
	}
	if err := serverDB.Create(&models.PricelistItem{
		PricelistID: serverPL.ID,
		LotName:     "CPU_A",
		LotCategory: "CPU",
		Price:       10,
	}).Error; err != nil {
		t.Fatalf("create server pricelist item: %v", err)
	}
	qty := 7.0
	if err := serverDB.Create(&models.StockLog{
		Partnumber: "CPU-PN-1",
		Date:       time.Now(),
		Price:      100,
		Qty:        &qty,
	}).Error; err != nil {
		t.Fatalf("create stock log: %v", err)
	}

	if err := local.SaveLocalPricelist(&localdb.LocalPricelist{
		ServerID:  serverPL.ID,
		Source:    serverPL.Source,
		Version:   serverPL.Version,
		Name:      serverPL.Notification,
		CreatedAt: serverPL.CreatedAt,
		SyncedAt:  time.Now(),
		IsUsed:    false,
	}); err != nil {
		t.Fatalf("seed local pricelist: %v", err)
	}
	localPL, err := local.GetLocalPricelistByServerID(serverPL.ID)
	if err != nil {
		t.Fatalf("get local pricelist: %v", err)
	}

	if err := local.DB().Create(&localdb.LocalPartnumberBook{
		ServerID:        1,
		Version:         "2026-03-07-001",
		CreatedAt:       time.Now(),
		IsActive:        true,
		PartnumbersJSON: localdb.LocalStringList{"CPU-PN-1"},
	}).Error; err != nil {
		t.Fatalf("create local partnumber book: %v", err)
	}
	if err := local.DB().Create(&localdb.LocalPartnumberBookItem{
		Partnumber: "CPU-PN-1",
		LotsJSON: localdb.LocalPartnumberBookLots{
			{LotName: "CPU_A", Qty: 1},
		},
		Description: "CPU PN",
	}).Error; err != nil {
		t.Fatalf("create local partnumber book item: %v", err)
	}

	svc := syncsvc.NewServiceWithDB(serverDB, local)
	if _, err := svc.SyncPricelistItems(localPL.ID); err != nil {
		t.Fatalf("sync pricelist items: %v", err)
	}

	items, err := local.GetLocalPricelistItems(localPL.ID)
	if err != nil {
		t.Fatalf("load local items: %v", err)
	}
	if len(items) != 1 {
		t.Fatalf("expected 1 local item, got %d", len(items))
	}
	if items[0].AvailableQty == nil {
		t.Fatalf("expected available_qty to be set")
	}
	if *items[0].AvailableQty != 7 {
		t.Fatalf("expected available_qty=7, got %v", *items[0].AvailableQty)
	}
	if len(items[0].Partnumbers) != 1 || items[0].Partnumbers[0] != "CPU-PN-1" {
		t.Fatalf("expected partnumbers [CPU-PN-1], got %v", items[0].Partnumbers)
	}
}
