package handler

import (
	"errors"
	"net/http"

	jsoniter "github.com/json-iterator/go"

	"github.com/gofrs/uuid/v5"

	"github.com/saveinmed/backend-go/internal/domain"
	"github.com/saveinmed/backend-go/internal/usecase"
)

var json = jsoniter.ConfigCompatibleWithStandardLibrary

type Handler struct {
	svc *usecase.Service
}

func New(svc *usecase.Service) *Handler {
	return &Handler{svc: svc}
}

// Register godoc
// @Summary Cadastro de usuário
// @Description Cria um usuário e opcionalmente uma empresa, retornando token JWT.
// @Tags Autenticação
// @Accept json
// @Produce json
// @Param payload body registerAuthRequest true "Dados do usuário e empresa"
// @Success 201 {object} authResponse
// @Failure 400 {object} map[string]string
// @Failure 500 {object} map[string]string
// @Router /api/v1/auth/register [post]
func (h *Handler) Register(w http.ResponseWriter, r *http.Request) {
	var req registerAuthRequest
	if err := decodeJSON(r.Context(), r, &req); err != nil {
		writeError(w, http.StatusBadRequest, err)
		return
	}

	var company *domain.Company
	if req.Company != nil {
		company = &domain.Company{
			ID:            req.Company.ID,
			Category:      req.Company.Category,
			CNPJ:          req.Company.CNPJ,
			CorporateName: req.Company.CorporateName,
			LicenseNumber: req.Company.LicenseNumber,
			Latitude:      req.Company.Latitude,
			Longitude:     req.Company.Longitude,
			City:          req.Company.City,
			State:         req.Company.State,
		}
	}

	var companyID uuid.UUID
	if req.CompanyID != nil {
		companyID = *req.CompanyID
	}

	user := &domain.User{
		CompanyID: companyID,
		Role:      req.Role,
		Name:      req.Name,
		Email:     req.Email,
	}

	if user.CompanyID == uuid.Nil && company == nil {
		writeError(w, http.StatusBadRequest, errors.New("company_id or company payload is required"))
		return
	}

	if err := h.svc.RegisterAccount(r.Context(), company, user, req.Password); err != nil {
		writeError(w, http.StatusInternalServerError, err)
		return
	}

	token, exp, err := h.svc.Authenticate(r.Context(), user.Email, req.Password)
	if err != nil {
		writeError(w, http.StatusInternalServerError, err)
		return
	}

	writeJSON(w, http.StatusCreated, authResponse{Token: token, ExpiresAt: exp})
}

// Login godoc
// @Summary Login
// @Description Autentica usuário e retorna token JWT.
// @Tags Autenticação
// @Accept json
// @Produce json
// @Param payload body loginRequest true "Credenciais"
// @Success 200 {object} authResponse
// @Failure 400 {object} map[string]string
// @Failure 401 {object} map[string]string
// @Router /api/v1/auth/login [post]
func (h *Handler) Login(w http.ResponseWriter, r *http.Request) {
	var req loginRequest
	if err := decodeJSON(r.Context(), r, &req); err != nil {
		writeError(w, http.StatusBadRequest, err)
		return
	}

	token, exp, err := h.svc.Authenticate(r.Context(), req.Email, req.Password)
	if err != nil {
		writeError(w, http.StatusUnauthorized, err)
		return
	}

	writeJSON(w, http.StatusOK, authResponse{Token: token, ExpiresAt: exp})
}
