package render

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"strings"
	"time"

	"leadb2b.org/internal/api"
)

type viaCEPResponse struct {
	CEP        string `json:"cep"`
	UF         string `json:"uf"`
	Localidade string `json:"localidade"`
	SIAFI      string `json:"siafi"`
	Erro       bool   `json:"erro"`
}

// NormalizeCEPDigits retorna 8 dígitos do CEP ou vazio se inválido.
func NormalizeCEPDigits(raw string) string {
	digits := strings.Map(func(r rune) rune {
		if r >= '0' && r <= '9' {
			return r
		}
		return -1
	}, raw)
	if len(digits) != 8 {
		return ""
	}
	return digits
}

// FormatCEPDisplay formata 8 dígitos como 00000-000.
func FormatCEPDisplay(digits string) string {
	digits = NormalizeCEPDigits(digits)
	if digits == "" {
		return ""
	}
	return digits[:5] + "-" + digits[5:]
}

// EnrichSearchFromCEP preenche UF e município (código RFB/SIAFI) a partir do CEP via ViaCEP.
func EnrichSearchFromCEP(ctx context.Context, p SearchForm) (SearchForm, string) {
	digits := NormalizeCEPDigits(p.CEP)
	if digits == "" {
		return p, ""
	}
	p.CEP = digits

	info, err := lookupViaCEP(ctx, digits)
	if err != nil || info.Erro {
		return p, ""
	}

	notice := ""
	if p.UF == "" && info.UF != "" {
		p.UF = strings.ToUpper(info.UF)
		notice = fmt.Sprintf("UF definida automaticamente pelo CEP (%s).", p.UF)
	}
	if p.Municipio == "" && info.SIAFI != "" {
		p.Municipio = strings.TrimSpace(info.SIAFI)
		if notice == "" {
			notice = fmt.Sprintf("Município definido automaticamente pelo CEP (%s).", info.Localidade)
		} else {
			notice += fmt.Sprintf(" Município: %s.", info.Localidade)
		}
	}
	return p, notice
}

func lookupViaCEP(ctx context.Context, digits string) (*viaCEPResponse, error) {
	url := "https://viacep.com.br/ws/" + digits + "/json/"
	req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
	if err != nil {
		return nil, err
	}
	client := &http.Client{Timeout: 6 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	if resp.StatusCode >= 400 {
		return nil, fmt.Errorf("viacep status %d", resp.StatusCode)
	}
	var out viaCEPResponse
	if err := json.NewDecoder(resp.Body).Decode(&out); err != nil {
		return nil, err
	}
	return &out, nil
}

// FilterItemsByCEP mantém itens cujo CEP (8 dígitos) coincide. A API ignora o parâmetro cep na listagem.
func FilterItemsByCEP(items []api.EstabelecimentoOut, cep string) []api.EstabelecimentoOut {
	want := NormalizeCEPDigits(cep)
	if want == "" || len(items) == 0 {
		return items
	}
	out := make([]api.EstabelecimentoOut, 0, len(items))
	for _, item := range items {
		if NormalizeCEPDigits(item.CEP) == want {
			out = append(out, item)
		}
	}
	return out
}
