package handlers

import (
	"encoding/json"
	"net/http"

	"git.warky.dev/wdevs/whatshooked/pkg/utils"
	"git.warky.dev/wdevs/whatshooked/pkg/whatsapp/businessapi"
	"go.mau.fi/whatsmeow/types"
)

// ListCatalogs returns product catalogs for a Business API account.
// POST /api/catalogs  {"account_id"}
func (h *Handlers) ListCatalogs(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	var req struct {
		AccountID string `json:"account_id"`
	}
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	baClient, err := h.getBusinessAPIClient(req.AccountID)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	resp, err := baClient.ListCatalogs(r.Context())
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	writeJSON(w, resp)
}

// ListProducts returns products in a specific catalog.
// POST /api/catalogs/products  {"account_id","catalog_id"}
func (h *Handlers) ListProducts(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	var req struct {
		AccountID string `json:"account_id"`
		CatalogID string `json:"catalog_id"`
	}
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	if req.CatalogID == "" {
		http.Error(w, "catalog_id is required", http.StatusBadRequest)
		return
	}

	baClient, err := h.getBusinessAPIClient(req.AccountID)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	resp, err := baClient.ListProducts(r.Context(), req.CatalogID)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	writeJSON(w, resp)
}

// SendCatalogMessage sends a catalog message that shares the full product catalog.
// POST /api/send/catalog  {"account_id","to","body_text","thumbnail_product_retailer_id"}
func (h *Handlers) SendCatalogMessage(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	var req struct {
		AccountID                  string `json:"account_id"`
		To                         string `json:"to"`
		BodyText                   string `json:"body_text"`
		ThumbnailProductRetailerID string `json:"thumbnail_product_retailer_id"`
	}
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	if req.BodyText == "" {
		http.Error(w, "body_text is required", http.StatusBadRequest)
		return
	}

	baClient, err := h.getBusinessAPIClient(req.AccountID)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	jid, err := types.ParseJID(utils.FormatPhoneToJID(req.To, h.config.Server.DefaultCountryCode))
	if err != nil {
		http.Error(w, "Invalid phone number", http.StatusBadRequest)
		return
	}

	if _, err := baClient.SendCatalogMessage(r.Context(), jid, req.BodyText, req.ThumbnailProductRetailerID); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	writeJSON(w, map[string]string{"status": "ok"})
}

// SendSingleProduct sends a single-product interactive message.
// POST /api/send/product  {"account_id","to","catalog_id","product_retailer_id","body_text","footer_text"}
func (h *Handlers) SendSingleProduct(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	var req struct {
		AccountID         string `json:"account_id"`
		To                string `json:"to"`
		CatalogID         string `json:"catalog_id"`
		ProductRetailerID string `json:"product_retailer_id"`
		BodyText          string `json:"body_text"`
		FooterText        string `json:"footer_text"`
	}
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	if req.CatalogID == "" || req.ProductRetailerID == "" || req.BodyText == "" {
		http.Error(w, "catalog_id, product_retailer_id, and body_text are required", http.StatusBadRequest)
		return
	}

	baClient, err := h.getBusinessAPIClient(req.AccountID)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	jid, err := types.ParseJID(utils.FormatPhoneToJID(req.To, h.config.Server.DefaultCountryCode))
	if err != nil {
		http.Error(w, "Invalid phone number", http.StatusBadRequest)
		return
	}

	if _, err := baClient.SendSingleProduct(r.Context(), jid, req.CatalogID, req.ProductRetailerID, req.BodyText, req.FooterText); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	writeJSON(w, map[string]string{"status": "ok"})
}

// SendProductList sends a multi-product list message (up to 30 products across up to 10 sections).
// POST /api/send/product-list  {"account_id","to","header_text","body_text","footer_text","catalog_id","sections":[...]}
func (h *Handlers) SendProductList(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	var req struct {
		AccountID  string                           `json:"account_id"`
		To         string                           `json:"to"`
		HeaderText string                           `json:"header_text"`
		BodyText   string                           `json:"body_text"`
		FooterText string                           `json:"footer_text"`
		CatalogID  string                           `json:"catalog_id"`
		Sections   []businessapi.ProductListSection `json:"sections"`
	}
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	if req.CatalogID == "" || req.HeaderText == "" || req.BodyText == "" || len(req.Sections) == 0 {
		http.Error(w, "catalog_id, header_text, body_text, and sections are required", http.StatusBadRequest)
		return
	}

	baClient, err := h.getBusinessAPIClient(req.AccountID)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	jid, err := types.ParseJID(utils.FormatPhoneToJID(req.To, h.config.Server.DefaultCountryCode))
	if err != nil {
		http.Error(w, "Invalid phone number", http.StatusBadRequest)
		return
	}

	if _, err := baClient.SendProductList(r.Context(), jid, req.HeaderText, req.BodyText, req.FooterText, req.CatalogID, req.Sections); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	writeJSON(w, map[string]string{"status": "ok"})
}
