package elinps

import (
	"crypto/rand"
	"encoding/hex"
	"encoding/json"
	"net/http"

	"github.com/go-chi/chi/v5"
	"github.com/jackc/pgx/v5/pgxpool"
)

// PainelHandlers expõe o painel de exploração em /painel.
//
// O painel é protegido por senha via SENHA_PAINEL.
// A sessão é um cookie simples com token gerado a cada inicialização.
type PainelHandlers struct {
	auth  AuthPainel
	store *Store
}

func NewPainelHandlers(pool *pgxpool.Pool, senha string) *PainelHandlers {
	token := gerarTokenPainel()
	return &PainelHandlers{
		auth:  AuthPainel{Senha: senha, Token: token},
		store: NewStore(pool),
	}
}

// Router monta as rotas do painel.
func (p *PainelHandlers) Router() http.Handler {
	r := chi.NewRouter()

	// Login
	r.Get("/login", p.auth.handlerLoginGet)
	r.Post("/login", p.auth.handlerLoginPost)

	// Dashboard
	r.With(func(next http.Handler) http.Handler { return p.auth.middleware(next) }).Get("/", func(w http.ResponseWriter, r *http.Request) {
		p.auth.handlerPainel(w, r, p.store)
	})

	// Export CSV (todas as respostas do filtro atual)
	// Protegido pelo mesmo middleware do painel.
	r.With(func(next http.Handler) http.Handler { return p.auth.middleware(next) }).Get("/export.csv", func(w http.ResponseWriter, r *http.Request) {
		p.auth.handlerExportCSV(w, r, p.store)
	})

	// Debug: conferir IP real / headers.
	// Protegido pelo mesmo middleware do painel.
	r.With(func(next http.Handler) http.Handler { return p.auth.middleware(next) }).Get("/debug/ip", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		_ = json.NewEncoder(w).Encode(map[string]any{
			"remote_addr":       r.RemoteAddr,
			"x_forwarded_for":   r.Header.Get("X-Forwarded-For"),
			"x_real_ip":         r.Header.Get("X-Real-IP"),
			"x_forwarded_proto": r.Header.Get("X-Forwarded-Proto"),
			"x_forwarded_host":  r.Header.Get("X-Forwarded-Host"),
			"user_agent":        r.UserAgent(),
		})
	})

	return r
}

func gerarTokenPainel() string {
	// Token aleatório para o cookie do painel.
	// Importante: muda a cada boot (ao reiniciar o servidor, precisa logar de novo).
	b := make([]byte, 32)
	_, _ = rand.Read(b)
	return hex.EncodeToString(b)
}
