package handlers

import (
	"net/http"
	"strconv"
	"strings"

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

type ComponentHandler struct {
	componentService *services.ComponentService
	localDB          *localdb.LocalDB
}

func NewComponentHandler(componentService *services.ComponentService, localDB *localdb.LocalDB) *ComponentHandler {
	return &ComponentHandler{
		componentService: componentService,
		localDB:          localDB,
	}
}

func (h *ComponentHandler) List(c *gin.Context) {
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	perPage, _ := strconv.Atoi(c.DefaultQuery("per_page", "20"))
	if page < 1 {
		page = 1
	}
	if perPage < 1 {
		perPage = 20
	}

	filter := repository.ComponentFilter{
		Category:      c.Query("category"),
		Search:        c.Query("search"),
		HasPrice:      c.Query("has_price") == "true",
		ExcludeHidden: c.Query("include_hidden") != "true", // По умолчанию скрытые не показываются
	}

	localFilter := localdb.ComponentFilter{
		Category: filter.Category,
		Search:   filter.Search,
		HasPrice: filter.HasPrice,
	}
	offset := (page - 1) * perPage
	localComps, total, err := h.localDB.ListComponents(localFilter, offset, perPage)
	if err != nil {
		RespondError(c, http.StatusInternalServerError, "internal server error", err)
		return
	}

	components := make([]services.ComponentView, len(localComps))
	for i, lc := range localComps {
		components[i] = services.ComponentView{
			LotName:      lc.LotName,
			Description:  lc.LotDescription,
			Category:     lc.Category,
			CategoryName: lc.Category,
			Model:        lc.Model,
		}
	}

	totalPages := int((total + int64(perPage) - 1) / int64(perPage))
	if totalPages < 1 {
		totalPages = 1
	}
	c.JSON(http.StatusOK, &services.ComponentListResult{
		Items:      components,
		TotalCount: total,
		Page:       page,
		PerPage:    perPage,
		TotalPages: totalPages,
	})
}

func (h *ComponentHandler) Get(c *gin.Context) {
	lotName := c.Param("lot_name")
	component, err := h.localDB.GetLocalComponent(lotName)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "component not found"})
		return
	}

	c.JSON(http.StatusOK, services.ComponentView{
		LotName:      component.LotName,
		Description:  component.LotDescription,
		Category:     component.Category,
		CategoryName: component.Category,
		Model:        component.Model,
	})
}

func (h *ComponentHandler) GetCategories(c *gin.Context) {
	// Build display_order lookup from the canonical list.
	orderMap := make(map[string]int, len(models.DefaultCategories))
	for _, cat := range models.DefaultCategories {
		orderMap[strings.ToUpper(cat.Code)] = cat.DisplayOrder
	}

	codes, err := h.localDB.GetLocalComponentCategories()
	if err == nil && len(codes) > 0 {
		categories := make([]models.Category, 0, len(codes))
		for _, code := range codes {
			trimmed := strings.TrimSpace(code)
			if trimmed == "" {
				continue
			}
			order := orderMap[strings.ToUpper(trimmed)]
			if order == 0 {
				order = models.MaxKnownDisplayOrder + 1
			}
			categories = append(categories, models.Category{
				Code:         trimmed,
				Name:         trimmed,
				DisplayOrder: order,
			})
		}
		c.JSON(http.StatusOK, categories)
		return
	}

	c.JSON(http.StatusOK, models.DefaultCategories)
}

func (h *ComponentHandler) GetConfiguratorSettings(c *gin.Context) {
	s, _ := h.localDB.GetConfiguratorSettings()
	if s == nil {
		s = &localdb.ConfiguratorSettings{}
	}

	if len(s.ConfigTypes) == 0 {
		s.ConfigTypes = defaultConfigTypes()
	}
	if len(s.TabConfig) == 0 {
		s.TabConfig = defaultTabConfig()
	}
	if len(s.AlwaysVisibleTabs) == 0 {
		s.AlwaysVisibleTabs = []string{"base", "storage", "pci"}
	}
	if len(s.RequiredCategories) == 0 {
		s.RequiredCategories = map[string][]string{"server": {"CPU", "MEM", "BB"}}
	}

	c.JSON(http.StatusOK, s)
}

func defaultConfigTypes() []localdb.ConfigTypeDef {
	return []localdb.ConfigTypeDef{
		{
			Code:         "server",
			NameRu:       "Сервер",
			DisplayOrder: 10,
			Categories: []string{
				"MB", "CPU", "MEM", "RAID",
				"SSD", "HDD", "M2", "EDSFF", "HHHL",
				"GPU", "NIC", "HCA", "DPU", "HBA",
				"PSU", "PS", "ACC", "RISERS", "CARD", "BB",
			},
		},
		{
			Code:         "storage",
			NameRu:       "СХД",
			DisplayOrder: 20,
			Categories: []string{
				"DKC", "CPU", "MEM", "PS",
				"SSD", "HDD", "M2", "EDSFF", "HHHL",
				"NIC", "HBA", "HCA", "ACC", "CARD",
			},
		},
	}
}

func defaultTabConfig() []localdb.TabDef {
	return []localdb.TabDef{
		{
			Key:          "base",
			Label:        "Base",
			SingleSelect: true,
			Categories:   []string{"MB", "CPU", "MEM", "ENC", "DKC", "CTL"},
		},
		{
			Key:          "storage",
			Label:        "Storage",
			SingleSelect: false,
			Categories:   []string{"RAID", "M2", "SSD", "HDD", "EDSFF", "HHHL"},
			Sections: []localdb.TabSection{
				{Title: "RAID Контроллеры", Categories: []string{"RAID"}},
				{Title: "Диски", Categories: []string{"M2", "SSD", "HDD", "EDSFF", "HHHL"}},
			},
		},
		{
			Key:          "pci",
			Label:        "PCI",
			SingleSelect: false,
			Categories:   []string{"GPU", "DPU", "NIC", "HCA", "HBA", "HIC"},
			Sections: []localdb.TabSection{
				{Title: "GPU / DPU", Categories: []string{"GPU", "DPU"}},
				{Title: "NIC / HCA", Categories: []string{"NIC", "HCA"}},
				{Title: "HBA", Categories: []string{"HBA"}},
				{Title: "HIC", Categories: []string{"HIC"}},
			},
		},
		{
			Key:          "power",
			Label:        "Power",
			SingleSelect: false,
			Categories:   []string{"PS", "PSU"},
		},
		{
			Key:          "accessories",
			Label:        "Accessories",
			SingleSelect: false,
			Categories:   []string{"ACC", "CARD"},
		},
		{
			Key:          "sw",
			Label:        "SW",
			SingleSelect: false,
			Categories:   []string{"SW"},
		},
	}
}
