package handlers

import (
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"path/filepath"
	"testing"
	"time"

	"git.mchus.pro/mchus/quoteforge/internal/localdb"
	"github.com/gin-gonic/gin"
)

func TestPricelistGetItems_ReturnsLotCategoryFromLocalPricelistItems(t *testing.T) {
	gin.SetMode(gin.TestMode)

	local, err := localdb.New(filepath.Join(t.TempDir(), "local.db"))
	if err != nil {
		t.Fatalf("init local db: %v", err)
	}
	t.Cleanup(func() { _ = local.Close() })

	if err := local.SaveLocalPricelist(&localdb.LocalPricelist{
		ServerID:  1,
		Source:    "estimate",
		Version:   "S-2026-02-11-001",
		Name:      "test",
		CreatedAt: time.Now(),
		SyncedAt:  time.Now(),
		IsUsed:    false,
	}); err != nil {
		t.Fatalf("save local pricelist: %v", err)
	}
	localPL, err := local.GetLocalPricelistByServerID(1)
	if err != nil {
		t.Fatalf("get local pricelist: %v", err)
	}
	if err := local.SaveLocalPricelistItems([]localdb.LocalPricelistItem{
		{
			PricelistID: localPL.ID,
			LotName:     "NO_UNDERSCORE_NAME",
			LotCategory: "CPU",
			Price:       10,
		},
	}); err != nil {
		t.Fatalf("save local pricelist items: %v", err)
	}

	h := NewPricelistHandler(local)

	req, _ := http.NewRequest("GET", "/api/pricelists/1/items?page=1&per_page=50", nil)
	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = req
	c.Params = gin.Params{{Key: "id", Value: "1"}}

	h.GetItems(c)

	if w.Code != http.StatusOK {
		t.Fatalf("expected status 200, got %d: %s", w.Code, w.Body.String())
	}

	var resp struct {
		Items []struct {
			LotName   string `json:"lot_name"`
			Category  string `json:"category"`
			UnitPrice any    `json:"price"`
		} `json:"items"`
	}
	if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil {
		t.Fatalf("unmarshal response: %v", err)
	}
	if len(resp.Items) != 1 {
		t.Fatalf("expected 1 item, got %d", len(resp.Items))
	}
	if resp.Items[0].LotName != "NO_UNDERSCORE_NAME" {
		t.Fatalf("expected lot_name NO_UNDERSCORE_NAME, got %q", resp.Items[0].LotName)
	}
	if resp.Items[0].Category != "CPU" {
		t.Fatalf("expected category CPU, got %q", resp.Items[0].Category)
	}
}

func TestPricelistList_ActiveOnlyExcludesPricelistsWithoutItems(t *testing.T) {
	gin.SetMode(gin.TestMode)

	local, err := localdb.New(filepath.Join(t.TempDir(), "local_active_only.db"))
	if err != nil {
		t.Fatalf("init local db: %v", err)
	}
	t.Cleanup(func() { _ = local.Close() })

	if err := local.SaveLocalPricelist(&localdb.LocalPricelist{
		ServerID:  10,
		Source:    "estimate",
		Version:   "E-1",
		Name:      "with-items",
		CreatedAt: time.Now().Add(-time.Minute),
		SyncedAt:  time.Now().Add(-time.Minute),
	}); err != nil {
		t.Fatalf("save with-items pricelist: %v", err)
	}
	withItems, err := local.GetLocalPricelistByServerID(10)
	if err != nil {
		t.Fatalf("load with-items pricelist: %v", err)
	}
	if err := local.SaveLocalPricelistItems([]localdb.LocalPricelistItem{
		{
			PricelistID: withItems.ID,
			LotName:     "CPU_X",
			LotCategory: "CPU",
			Price:       100,
		},
	}); err != nil {
		t.Fatalf("save with-items pricelist items: %v", err)
	}

	if err := local.SaveLocalPricelist(&localdb.LocalPricelist{
		ServerID:  11,
		Source:    "estimate",
		Version:   "E-2",
		Name:      "without-items",
		CreatedAt: time.Now(),
		SyncedAt:  time.Now(),
	}); err != nil {
		t.Fatalf("save without-items pricelist: %v", err)
	}

	h := NewPricelistHandler(local)

	req, _ := http.NewRequest("GET", "/api/pricelists?source=estimate&active_only=true", nil)
	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = req

	h.List(c)

	if w.Code != http.StatusOK {
		t.Fatalf("expected status 200, got %d: %s", w.Code, w.Body.String())
	}

	var resp struct {
		Items []struct {
			ID uint `json:"id"`
		} `json:"items"`
		TotalCount int `json:"total_count"`
	}
	if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil {
		t.Fatalf("unmarshal response: %v", err)
	}
	if resp.TotalCount != 1 {
		t.Fatalf("expected total=1, got %d", resp.TotalCount)
	}
	if len(resp.Items) != 1 {
		t.Fatalf("expected 1 pricelist, got %d", len(resp.Items))
	}
	if resp.Items[0].ID != 10 {
		t.Fatalf("expected pricelist id=10, got %d", resp.Items[0].ID)
	}
}
