package auth

import (
	"net/http"
	"strings"

	"photum-backend/internal/profissionais"
	"photum-backend/internal/storage"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

type Handler struct {
	service   *Service
	s3Service *storage.S3Service
}

func NewHandler(service *Service, s3Service *storage.S3Service) *Handler {
	return &Handler{service: service, s3Service: s3Service}
}

type uploadURLRequest struct {
	Filename    string `json:"filename" binding:"required"`
	ContentType string `json:"content_type" binding:"required"`
}

// GetUploadURL godoc
// @Summary      Get S3 Presigned URL for upload
// @Description  Get a pre-signed URL to upload a file directly to S3/Civo
// @Tags         auth
// @Accept       json
// @Produce      json
// @Param        request body uploadURLRequest true "Upload URL Request"
// @Success      200  {object}  map[string]string
// @Router       /auth/upload-url [post]
func (h *Handler) GetUploadURL(c *gin.Context) {
	var req uploadURLRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	uploadURL, publicURL, err := h.s3Service.GeneratePresignedURL(req.Filename, req.ContentType)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"upload_url": uploadURL,
		"public_url": publicURL,
	})
}

type registerRequest struct {
	Email            string `json:"email" binding:"required,email"`
	Senha            string `json:"senha" binding:"required,min=6"`
	Role             string `json:"role" binding:"required"`
	Nome             string `json:"nome" binding:"required"`
	Telefone         string `json:"telefone"`
	TipoProfissional string `json:"professional_type"`
	EmpresaID        string `json:"empresa_id"`
	Regiao           string `json:"regiao"`
	CpfCnpj          string `json:"cpf_cnpj"`
	Cep              string `json:"cep"`
	Endereco         string `json:"endereco"`
	Numero           string `json:"numero"`
	Complemento      string `json:"complemento"`
	Bairro           string `json:"bairro"`
	Cidade           string `json:"cidade"`
	Estado           string `json:"estado"`
}

// Register godoc
// @Summary      Register a new user
// @Description  Register a new user with email, password, name, phone, role and professional type
// @Tags         auth
// @Accept       json
// @Produce      json
// @Param        request body registerRequest true "Register Request"
// @Success      201  {object}  map[string]string
// @Failure      400  {object}  map[string]string
// @Failure      500  {object}  map[string]string
// @Router       /auth/register [post]
func (h *Handler) Register(c *gin.Context) {
	var req registerRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// Create professional data only if role is appropriate
	var profData *profissionais.CreateProfissionalInput
	if req.Role == "BUSINESS_OWNER" {
		profData = &profissionais.CreateProfissionalInput{
			Nome:     req.Nome,
			Whatsapp: &req.Telefone,
		}
	}

	var empresaIDPtr *string
	if req.EmpresaID != "" {
		empresaIDPtr = &req.EmpresaID
	}

	regiao := c.GetString("regiao")
	if regiao == "" {
		regiao = c.GetHeader("x-regiao")
	}
	// Default to SP if still empty
	if regiao == "" {
		regiao = "SP"
	}

	user, err := h.service.Register(c.Request.Context(), req.Email, req.Senha, req.Role, req.Nome, req.Telefone, req.TipoProfissional, empresaIDPtr, profData, regiao, req.CpfCnpj, req.Cep, req.Endereco, req.Numero, req.Complemento, req.Bairro, req.Cidade, req.Estado)
	if err != nil {
		if strings.Contains(err.Error(), "duplicate key") {
			c.JSON(http.StatusConflict, gin.H{"error": "email already registered"})
			return
		}
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	// Auto-login after registration
	tokenPair, _, _, err := h.service.Login(c.Request.Context(), req.Email, req.Senha)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "user created but failed to auto-login"})
		return
	}

	http.SetCookie(c.Writer, &http.Cookie{
		Name:     "refresh_token",
		Value:    tokenPair.RefreshToken,
		Path:     "/auth/refresh",
		HttpOnly: true,
		Secure:   false,
		SameSite: http.SameSiteStrictMode,
		MaxAge:   30 * 24 * 60 * 60,
	})

	// Set access_token cookie for fallback
	http.SetCookie(c.Writer, &http.Cookie{
		Name:     "access_token",
		Value:    tokenPair.AccessToken,
		Path:     "/",
		HttpOnly: true,
		Secure:   false,
		SameSite: http.SameSiteStrictMode,
		MaxAge:   15 * 60,
	})

	c.JSON(http.StatusCreated, gin.H{
		"message":      "user created",
		"access_token": tokenPair.AccessToken,
		"user": gin.H{
			"id":    uuid.UUID(user.ID.Bytes).String(),
			"email": user.Email,
			"role":  user.Role,
			"ativo": user.Ativo,
		},
	})
}

type loginRequest struct {
	Email string `json:"email" binding:"required,email" example:"admin@photum.com"`
	Senha string `json:"senha" binding:"required,min=6" example:"123456"`
}

type loginResponse struct {
	AccessToken  string       `json:"access_token"`
	ExpiresAt    string       `json:"expires_at"`
	User         userResponse `json:"user"`
	Profissional interface{}  `json:"profissional,omitempty"`
}

type userResponse struct {
	ID             string   `json:"id"`
	Email          string   `json:"email"`
	Role           string   `json:"role"`
	Ativo          bool     `json:"ativo"`
	Name           string   `json:"name,omitempty"`
	Phone          string   `json:"phone,omitempty"`
	CompanyID      string   `json:"company_id,omitempty"`
	CompanyName    string   `json:"company_name,omitempty"`
	AllowedRegions []string `json:"allowed_regions"`
	CpfCnpj        string   `json:"cpf_cnpj,omitempty"`
	Cep            string   `json:"cep,omitempty"`
	Endereco       string   `json:"endereco,omitempty"`
	Numero         string   `json:"numero,omitempty"`
	Complemento    string   `json:"complemento,omitempty"`
	Bairro         string   `json:"bairro,omitempty"`
	Cidade         string   `json:"cidade,omitempty"`
	Estado         string   `json:"estado,omitempty"`
}

// Login godoc
// @Summary      Login
// @Description  Login with email and password
// @Tags         auth
// @Accept       json
// @Produce      json
// @Param        request body loginRequest true "Login Request"
// @Success      200  {object}  loginResponse
// @Failure      401  {object}  map[string]string
// @Failure      500  {object}  map[string]string
// @Router       /auth/login [post]
func (h *Handler) Login(c *gin.Context) {
	var req loginRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	tokenPair, user, profData, err := h.service.Login(c.Request.Context(), req.Email, req.Senha)
	if err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid credentials"})
		return
	}

	http.SetCookie(c.Writer, &http.Cookie{
		Name:     "refresh_token",
		Value:    tokenPair.RefreshToken,
		Path:     "/auth/refresh",
		HttpOnly: true,
		Secure:   false,
		SameSite: http.SameSiteStrictMode,
		MaxAge:   30 * 24 * 60 * 60,
	})

	// Set access_token cookie for fallback
	http.SetCookie(c.Writer, &http.Cookie{
		Name:     "access_token",
		Value:    tokenPair.AccessToken,
		Path:     "/",
		HttpOnly: true,
		Secure:   false,
		SameSite: http.SameSiteStrictMode,
		MaxAge:   15 * 60, // 15 mins
	})

	// Handle Nullable Fields
	var companyID, companyName string
	if user.EmpresaID.Valid {
		companyID = uuid.UUID(user.EmpresaID.Bytes).String()
	}
	if user.EmpresaNome.Valid {
		companyName = user.EmpresaNome.String
	}

	// Prepare response
	uResp := userResponse{
		ID:             uuid.UUID(user.ID.Bytes).String(),
		Email:          user.Email,
		Role:           user.Role,
		Ativo:          user.Ativo, // Added this back from original
		Name:           user.Nome,
		CompanyID:      companyID,
		CompanyName:    companyName,
		AllowedRegions: user.RegioesPermitidas,
		Phone:          "",
	}

	// Helper to get phone from profData or Client Data
	if user.Role == "PHOTOGRAPHER" && profData != nil {
		if profData.Whatsapp.Valid {
			uResp.Phone = profData.Whatsapp.String
		}
	} else if user.Role == "EVENT_OWNER" {
		// Fetch Client Data
		clientData, err := h.service.GetClientData(c.Request.Context(), uResp.ID)
		if err == nil && clientData != nil {
			if clientData.Telefone.Valid {
				uResp.Phone = clientData.Telefone.String
			}
			if clientData.CpfCnpj.Valid {
				uResp.CpfCnpj = clientData.CpfCnpj.String
			}
			if clientData.Cep.Valid {
				uResp.Cep = clientData.Cep.String
			}
			if clientData.Endereco.Valid {
				uResp.Endereco = clientData.Endereco.String
			}
			if clientData.Numero.Valid {
				uResp.Numero = clientData.Numero.String
			}
			if clientData.Complemento.Valid {
				uResp.Complemento = clientData.Complemento.String
			}
			if clientData.Bairro.Valid {
				uResp.Bairro = clientData.Bairro.String
			}
			if clientData.Cidade.Valid {
				uResp.Cidade = clientData.Cidade.String
			}
			if clientData.Estado.Valid {
				uResp.Estado = clientData.Estado.String
			}
			// Use client name if available ?? Or user name is fine.
			// Usually user.Name comes from `usuarios` table, but `cadastro_clientes` also has nome.
			// Let's stick to user.Name for consistency, usually they should be same.
		}
	}

	resp := loginResponse{
		AccessToken: tokenPair.AccessToken,
		ExpiresAt:   "2025-...",
		User:        uResp,
	}
	if profData != nil {
		resp.Profissional = map[string]interface{}{
			"id":                     uuid.UUID(profData.ID.Bytes).String(),
			"nome":                   profData.Nome,
			"funcao_profissional_id": uuid.UUID(profData.FuncaoProfissionalID.Bytes).String(),
			"funcao_profissional":    "", // Deprecated/Removed from query
			"functions":              profData.Functions,
			"equipamentos":           profData.Equipamentos.String,
			"avatar_url":             profData.AvatarUrl.String,
		}
	}

	c.JSON(http.StatusOK, resp)
}

// Refresh godoc
// @Summary      Refresh access token
// @Description  Get a new access token using a valid refresh token
// @Tags         auth
// @Accept       json
// @Produce      json
// @Param        refresh_token body string false "Refresh Token"
// @Success      200  {object}  map[string]interface{}
// @Failure      401  {object}  map[string]string
// @Router       /auth/refresh [post]
func (h *Handler) Refresh(c *gin.Context) {
	refreshToken, err := c.Cookie("refresh_token")
	if err != nil {
		var req struct {
			RefreshToken string `json:"refresh_token"`
		}
		if err := c.ShouldBindJSON(&req); err == nil {
			refreshToken = req.RefreshToken
		}
	}

	if refreshToken == "" {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "refresh token required"})
		return
	}

	accessToken, accessExp, err := h.service.Refresh(c.Request.Context(), refreshToken)
	if err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid refresh token"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"access_token": accessToken,
		"expires_at":   accessExp,
	})
}

// Logout godoc
// @Summary      Logout user
// @Description  Revoke refresh token and clear cookie
// @Tags         auth
// @Accept       json
// @Produce      json
// @Param        refresh_token body string false "Refresh Token"
// @Success      200  {object}  map[string]string
// @Router       /auth/logout [post]
func (h *Handler) Logout(c *gin.Context) {
	refreshToken, err := c.Cookie("refresh_token")
	if err != nil {
		var req struct {
			RefreshToken string `json:"refresh_token"`
		}
		if err := c.ShouldBindJSON(&req); err == nil {
			refreshToken = req.RefreshToken
		}
	}

	if refreshToken != "" {
		_ = h.service.Logout(c.Request.Context(), refreshToken)
	}

	c.SetCookie("refresh_token", "", -1, "/", "", false, true)
	c.JSON(http.StatusOK, gin.H{"message": "logged out"})
}

// Me godoc
// @Summary      Get current user
// @Description  Get current authenticated user
// @Tags         auth
// @Accept       json
// @Produce      json
// @Success      200  {object}  loginResponse
// @Router       /api/me [get]
func (h *Handler) Me(c *gin.Context) {
	// User ID comes from context (AuthMiddleware)
	userID, exists := c.Get("userID")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
		return
	}

	// We can fetch fresh user data
	user, err := h.service.GetUser(c.Request.Context(), userID.(string))
	if err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "user not found"})
		return
	}

	var empresaNome string
	if user.EmpresaNome.Valid {
		empresaNome = user.EmpresaNome.String
	}
	var empresaID string
	if user.EmpresaID.Valid {
		empresaID = uuid.UUID(user.EmpresaID.Bytes).String()
	}

	// Ensure valid slice for JSON response (avoid null)
	allowedRegions := make([]string, 0)
	if user.RegioesPermitidas != nil {
		allowedRegions = append(allowedRegions, user.RegioesPermitidas...)
	}

	uResp := userResponse{
		ID:             uuid.UUID(user.ID.Bytes).String(),
		Email:          user.Email,
		Role:           user.Role,
		Ativo:          user.Ativo,
		Name:           user.Nome,
		Phone:          user.Whatsapp, // Default to user.Whatsapp
		CompanyName:    empresaNome,
		CompanyID:      empresaID,
		AllowedRegions: allowedRegions,
	}

	if user.Role == "EVENT_OWNER" {
		clientData, err := h.service.GetClientData(c.Request.Context(), uResp.ID)
		if err == nil && clientData != nil {
			if clientData.Telefone.Valid {
				uResp.Phone = clientData.Telefone.String
			}
			if clientData.CpfCnpj.Valid {
				uResp.CpfCnpj = clientData.CpfCnpj.String
			}
			if clientData.Cep.Valid {
				uResp.Cep = clientData.Cep.String
			}
			if clientData.Endereco.Valid {
				uResp.Endereco = clientData.Endereco.String
			}
			if clientData.Numero.Valid {
				uResp.Numero = clientData.Numero.String
			}
			if clientData.Complemento.Valid {
				uResp.Complemento = clientData.Complemento.String
			}
			if clientData.Bairro.Valid {
				uResp.Bairro = clientData.Bairro.String
			}
			if clientData.Cidade.Valid {
				uResp.Cidade = clientData.Cidade.String
			}
			if clientData.Estado.Valid {
				uResp.Estado = clientData.Estado.String
			}
		}
	}

	resp := loginResponse{
		User: uResp,
	}

	if user.Role == "PHOTOGRAPHER" || user.Role == "BUSINESS_OWNER" {
		regiao := c.GetString("regiao")
		if regiao == "" {
			regiao = c.GetHeader("x-regiao")
		}

		profData, err := h.service.GetProfessionalByUserID(c.Request.Context(), uuid.UUID(user.ID.Bytes).String())
		if err == nil && profData != nil {
			// Update phone from professional data if valid
			if profData.Whatsapp.Valid {
				resp.User.Phone = profData.Whatsapp.String
			}

			resp.Profissional = map[string]interface{}{
				"id":                     uuid.UUID(profData.ID.Bytes).String(),
				"nome":                   profData.Nome,
				"funcao_profissional_id": uuid.UUID(profData.FuncaoProfissionalID.Bytes).String(),
				"funcao_profissional":    "", // Deprecated
				"functions":              profData.Functions,
				"equipamentos":           profData.Equipamentos.String,
				"avatar_url":             profData.AvatarUrl.String,
			}
		}
	}

	c.JSON(http.StatusOK, resp)
}

type updateMeRequest struct {
	Nome        string `json:"name"`
	Telefone    string `json:"phone"`
	CpfCnpj     string `json:"cpf_cnpj"`
	Cep         string `json:"cep"`
	Endereco    string `json:"endereco"`
	Numero      string `json:"numero"`
	Complemento string `json:"complemento"`
	Bairro      string `json:"bairro"`
	Cidade      string `json:"cidade"`
	Estado      string `json:"estado"`
}

// UpdateMe godoc
// @Summary      Update current user profile
// @Description  Update profile information (Name, Phone, Address). Currently for EVENT_OWNER.
// @Tags         auth
// @Accept       json
// @Produce      json
// @Success      200  {object}  map[string]string
// @Failure      400  {object}  map[string]string
// @Failure      500  {object}  map[string]string
// @Router       /api/me [put]
func (h *Handler) UpdateMe(c *gin.Context) {
	userID, exists := c.Get("userID")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
		return
	}

	var req updateMeRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid payload: " + err.Error()})
		return
	}

	// For now, we assume this is mostly for Clients (EVENT_OWNER)
	// based on the fields provided (address, cpf, etc).
	// Future: Check role and call appropriate service if needed.
	// But UpdateClientData uses "UpdateCadastroCliente" which is linked to user_id.
	// If the user does not have a client record, it might fail or do nothing if query uses WHERE exists?
	// The query uses UPDATE, so if no row, no update.

	// We should probably check role or just try to update.
	// But to be safe, let's just call UpdateClientData.
	// If the user is a Photographer, they should use the /profissionais/me PUT (if exists) or similar.
	// But wait, the user complaint is about Clients.

	err := h.service.UpdateClientData(c.Request.Context(), userID.(string), UpdateClientInput{
		Nome:        req.Nome,
		Telefone:    req.Telefone,
		CpfCnpj:     req.CpfCnpj,
		Cep:         req.Cep,
		Endereco:    req.Endereco,
		Numero:      req.Numero,
		Complemento: req.Complemento,
		Bairro:      req.Bairro,
		Cidade:      req.Cidade,
		Estado:      req.Estado,
	})

	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to update profile: " + err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "profile updated successfully"})
}

// ListPending godoc
// @Summary      List pending users
// @Description  List users with ativo=false
// @Tags         admin
// @Accept       json
// @Produce      json
// @Success      200  {array}   map[string]interface{}
// @Failure      500  {object}  map[string]string
// @Security     BearerAuth
// @Router       /api/admin/users/pending [get]
func (h *Handler) ListPending(c *gin.Context) {
	regiao := c.GetString("regiao")
	if regiao == "" {
		regiao = c.GetHeader("x-regiao")
	}

	users, err := h.service.ListPendingUsers(c.Request.Context(), regiao)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	// Map to response
	// The generated type ListUsuariosPendingRow fields are:
	// ID       pgtype.UUID
	// Email    string
	// Role     string
	// Ativo    bool
	// CriadoEm pgtype.Timestamptz
	// Nome     pgtype.Text
	// Whatsapp pgtype.Text

	resp := make([]map[string]interface{}, len(users))
	for i, u := range users {
		nome := u.Nome
		whatsapp := u.Whatsapp

		var empresaNome string
		if u.EmpresaNome.Valid {
			empresaNome = u.EmpresaNome.String
		}

		resp[i] = map[string]interface{}{
			"id":                uuid.UUID(u.ID.Bytes).String(),
			"email":             u.Email,
			"role":              u.Role,
			"ativo":             u.Ativo,
			"created_at":        u.CriadoEm.Time,
			"name":              nome, // Mapped to name for frontend compatibility
			"phone":             whatsapp,
			"company_name":      empresaNome,
			"professional_type": u.TipoProfissional.String, // Add this
		}
	}

	c.JSON(http.StatusOK, resp)
}

// Approve godoc
// @Summary      Approve user
// @Description  Set user ativo=true
// @Tags         admin
// @Accept       json
// @Produce      json
// @Param        id   path      string  true  "User ID"
// @Success      200  {object}  map[string]string
// @Failure      400  {object}  map[string]string
// @Failure      500  {object}  map[string]string
// @Security     BearerAuth
// @Router       /api/admin/users/{id}/approve [patch]
func (h *Handler) Approve(c *gin.Context) {
	id := c.Param("id")
	if id == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "id required"})
		return
	}

	err := h.service.ApproveUser(c.Request.Context(), id)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "user approved"})
}

// AdminCreateUser godoc
// @Summary      Create user (Admin)
// @Description  Create a new user with specific role (Admin only)
// @Tags         admin
// @Accept       json
// @Produce      json
// @Param        request body registerRequest true "Create User Request"
// @Success      201  {object}  map[string]string
// @Failure      400  {object}  map[string]string
// @Failure      500  {object}  map[string]string
// @Security     BearerAuth
// @Router       /api/admin/users [post]
func (h *Handler) AdminCreateUser(c *gin.Context) {
	var req registerRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// Just reuse the request struct but call AdminCreateUser service
	regiao := c.GetString("regiao")

	// If Admin explicitly sends regiao in body, use it (override context)
	if req.Regiao != "" {
		regiao = req.Regiao
	}

	if regiao == "" {
		// Fallback or Error? Admin creation usually implies target region.
		// Let's assume header is present or default.
		regiao = "SP" // Default for now if missing? Or error?
	}
	user, err := h.service.AdminCreateUser(c.Request.Context(), req.Email, req.Senha, req.Role, req.Nome, req.TipoProfissional, true, regiao, req.EmpresaID, req.Telefone, req.CpfCnpj, req.Cep, req.Endereco, req.Numero, req.Complemento, req.Bairro, req.Cidade, req.Estado)
	if err != nil {
		if strings.Contains(err.Error(), "duplicate key") {
			c.JSON(http.StatusConflict, gin.H{"error": "email already registered"})
			return
		}
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusCreated, gin.H{
		"message": "user created",
		"id":      uuid.UUID(user.ID.Bytes).String(),
		"email":   user.Email,
	})
}

type updateRoleRequest struct {
	Role string `json:"role" binding:"required"`
}

// UpdateRole godoc
// @Summary      Update user role
// @Description  Update user role (Admin only)
// @Tags         admin
// @Accept       json
// @Produce      json
// @Param        id   path      string  true  "User ID"
// @Param        request body updateRoleRequest true "Update Role Request"
// @Success      200  {object}  map[string]string
// @Failure      400  {object}  map[string]string
// @Failure      500  {object}  map[string]string
// @Security     BearerAuth
// @Router       /api/admin/users/{id}/role [patch]
func (h *Handler) UpdateRole(c *gin.Context) {
	id := c.Param("id")
	if id == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "id required"})
		return
	}

	var req updateRoleRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	err := h.service.UpdateUserRole(c.Request.Context(), id, req.Role)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "role updated"})
}

// DeleteUser godoc
// @Summary      Delete user
// @Description  Delete user (Admin only)
// @Tags         admin
// @Accept       json
// @Produce      json
// @Param        id   path      string  true  "User ID"
// @Success      200  {object}  map[string]string
// @Failure      400  {object}  map[string]string
// @Failure      500  {object}  map[string]string
// @Security     BearerAuth
// @Router       /api/admin/users/{id} [delete]
func (h *Handler) DeleteUser(c *gin.Context) {
	id := c.Param("id")
	if id == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "id required"})
		return
	}

	err := h.service.DeleteUser(c.Request.Context(), id)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "user deleted"})
}

// ListUsers godoc
// @Summary      List all users
// @Description  List all users (Admin only)
// @Tags         admin
// @Accept       json
// @Produce      json
// @Success      200  {array}   map[string]interface{}
// @Failure      500  {object}  map[string]string
// @Security     BearerAuth
// @Router       /api/admin/users [get]
func (h *Handler) ListUsers(c *gin.Context) {
	regiao := c.GetString("regiao")
	if regiao == "" {
		regiao = c.GetHeader("x-regiao")
	}
	users, err := h.service.ListUsers(c.Request.Context(), regiao)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	resp := make([]map[string]interface{}, len(users))
	for i, u := range users {
		empresaId := ""
		if u.EmpresaID.Valid {
			empresaId = uuid.UUID(u.EmpresaID.Bytes).String()
		}

		resp[i] = map[string]interface{}{
			"id":                uuid.UUID(u.ID.Bytes).String(),
			"email":             u.Email,
			"role":              u.Role,
			"ativo":             u.Ativo,
			"created_at":        u.CriadoEm.Time,
			"name":              u.Nome,
			"phone":             u.Whatsapp,
			"company_name":      u.EmpresaNome.String,
			"company_id":        empresaId,
			"professional_type": u.TipoProfissional.String,
		}
	}

	c.JSON(http.StatusOK, resp)
}

// GetUser godoc
// @Summary      Get user by ID
// @Description  Get user details by ID (Admin only)
// @Tags         admin
// @Accept       json
// @Produce      json
// @Param        id   path      string  true  "User ID"
// @Success      200  {object}  map[string]interface{}
// @Failure      400  {object}  map[string]string
// @Failure      404  {object}  map[string]string
// @Failure      500  {object}  map[string]string
// @Security     BearerAuth
// @Router       /api/admin/users/{id} [get]
func (h *Handler) GetUser(c *gin.Context) {
	id := c.Param("id")
	if id == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "id required"})
		return
	}

	user, err := h.service.GetUser(c.Request.Context(), id)
	if err != nil {
		if strings.Contains(err.Error(), "no rows") {
			c.JSON(http.StatusNotFound, gin.H{"error": "user not found"})
			return
		}
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	var empresaNome string
	if user.EmpresaNome.Valid {
		empresaNome = user.EmpresaNome.String
	}
	var empresaID string
	if user.EmpresaID.Valid {
		empresaID = uuid.UUID(user.EmpresaID.Bytes).String()
	}

	resp := loginResponse{
		User: userResponse{
			ID:             uuid.UUID(user.ID.Bytes).String(),
			Email:          user.Email,
			Role:           user.Role,
			Ativo:          user.Ativo,
			Name:           user.Nome,
			Phone:          user.Whatsapp,
			CompanyName:    empresaNome,
			CompanyID:      empresaID,
			AllowedRegions: user.RegioesPermitidas,
		},
	}

	c.JSON(http.StatusOK, resp)
}
