package handlers

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

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

// PartnumberBooksHandler provides read-only access to local partnumber book snapshots.
type PartnumberBooksHandler struct {
	localDB *localdb.LocalDB
}

func NewPartnumberBooksHandler(localDB *localdb.LocalDB) *PartnumberBooksHandler {
	return &PartnumberBooksHandler{localDB: localDB}
}

// List returns all local partnumber book snapshots.
// GET /api/partnumber-books
func (h *PartnumberBooksHandler) List(c *gin.Context) {
	bookRepo := repository.NewPartnumberBookRepository(h.localDB.DB())
	books, err := bookRepo.ListBooks()
	if err != nil {
		RespondError(c, http.StatusInternalServerError, "internal server error", err)
		return
	}

	type bookSummary struct {
		ID        uint   `json:"id"`
		ServerID  int    `json:"server_id"`
		Version   string `json:"version"`
		CreatedAt string `json:"created_at"`
		IsActive  bool   `json:"is_active"`
		ItemCount int64  `json:"item_count"`
	}

	summaries := make([]bookSummary, 0, len(books))
	for _, b := range books {
		summaries = append(summaries, bookSummary{
			ID:        b.ID,
			ServerID:  b.ServerID,
			Version:   b.Version,
			CreatedAt: b.CreatedAt.Format("2006-01-02"),
			IsActive:  b.IsActive,
			ItemCount: bookRepo.CountBookItems(b.ID),
		})
	}

	c.JSON(http.StatusOK, gin.H{
		"items":       summaries,
		"total_count": len(summaries),
		"page":        1,
		"per_page":    len(summaries),
		"total_pages": 1,
	})
}

// GetItems returns items for a partnumber book by server ID.
// GET /api/partnumber-books/:id
func (h *PartnumberBooksHandler) GetItems(c *gin.Context) {
	idStr := c.Param("id")
	id, err := strconv.ParseUint(idStr, 10, 64)
	if err != nil {
		c.JSON(http.StatusUnprocessableEntity, gin.H{"error": "invalid book ID"})
		return
	}

	bookRepo := repository.NewPartnumberBookRepository(h.localDB.DB())
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	perPage, _ := strconv.Atoi(c.DefaultQuery("per_page", "100"))
	search := strings.TrimSpace(c.Query("search"))
	if page < 1 {
		page = 1
	}
	if perPage < 1 || perPage > 500 {
		perPage = 100
	}

	book, err := h.localDB.GetLocalPartnumberBookByServerID(uint(id))
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "partnumber book not found"})
		return
	}

	items, total, err := bookRepo.GetBookItemsPage(book.ID, search, page, perPage)
	if err != nil {
		RespondError(c, http.StatusInternalServerError, "internal server error", err)
		return
	}

	totalPages := int((total + int64(perPage) - 1) / int64(perPage))
	if totalPages < 1 {
		totalPages = 1
	}
	c.JSON(http.StatusOK, gin.H{
		"book_id":     book.ServerID,
		"version":     book.Version,
		"is_active":   book.IsActive,
		"partnumbers": book.PartnumbersJSON,
		"items":       items,
		"total_count": total,
		"page":        page,
		"per_page":    perPage,
		"total_pages": totalPages,
		"search":      search,
		"book_total":  bookRepo.CountBookItems(book.ID),
		"lot_count":   bookRepo.CountDistinctLots(book.ID),
	})
}
