package handler

import (
	"errors"
	"net/http"
	"strings"

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

// CreateCompany godoc
// @Summary Registro de empresas
// @Description Cadastra farmácia, distribuidora ou administrador com CNPJ e licença sanitária.
// @Tags Empresas
// @Accept json
// @Produce json
// @Param company body registerCompanyRequest true "Dados da empresa"
// @Success 201 {object} domain.Company
// @Router /api/v1/companies [post]
func (h *Handler) CreateCompany(w http.ResponseWriter, r *http.Request) {
	var req registerCompanyRequest
	if err := decodeJSON(r.Context(), r, &req); err != nil {
		writeError(w, http.StatusBadRequest, err)
		return
	}

	company := &domain.Company{
		Category:      req.Category,
		CNPJ:          req.CNPJ,
		CorporateName: req.CorporateName,
		LicenseNumber: req.LicenseNumber,
		Latitude:      req.Latitude,
		Longitude:     req.Longitude,
		City:          req.City,
		State:         req.State,
	}

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

	writeJSON(w, http.StatusCreated, company)
}

// ListCompanies godoc
// @Summary Lista empresas
// @Tags Empresas
// @Produce json
// @Success 200 {array} domain.Company
// @Router /api/v1/companies [get]
func (h *Handler) ListCompanies(w http.ResponseWriter, r *http.Request) {
	page, pageSize := parsePagination(r)
	filter := domain.CompanyFilter{
		Category: r.URL.Query().Get("category"),
		Search:   r.URL.Query().Get("search"),
		City:     r.URL.Query().Get("city"),
		State:    r.URL.Query().Get("state"),
	}

	result, err := h.svc.ListCompanies(r.Context(), filter, page, pageSize)
	if err != nil {
		writeError(w, http.StatusInternalServerError, err)
		return
	}
	writeJSON(w, http.StatusOK, result)
}

// GetCompany godoc
// @Summary Obter empresa
// @Tags Empresas
// @Produce json
// @Param id path string true "Company ID"
// @Success 200 {object} domain.Company
// @Failure 404 {object} map[string]string
// @Router /api/v1/companies/{id} [get]
func (h *Handler) GetCompany(w http.ResponseWriter, r *http.Request) {
	id, err := parseUUIDFromPath(r.URL.Path)
	if err != nil {
		writeError(w, http.StatusBadRequest, err)
		return
	}

	company, err := h.svc.GetCompany(r.Context(), id)
	if err != nil {
		writeError(w, http.StatusNotFound, err)
		return
	}

	writeJSON(w, http.StatusOK, company)
}

// UpdateCompany godoc
// @Summary Atualizar empresa
// @Tags Empresas
// @Accept json
// @Produce json
// @Param id path string true "Company ID"
// @Param payload body updateCompanyRequest true "Campos para atualização"
// @Success 200 {object} domain.Company
// @Failure 400 {object} map[string]string
// @Failure 404 {object} map[string]string
// @Router /api/v1/companies/{id} [patch]
func (h *Handler) UpdateCompany(w http.ResponseWriter, r *http.Request) {
	id, err := parseUUIDFromPath(r.URL.Path)
	if err != nil {
		writeError(w, http.StatusBadRequest, err)
		return
	}

	var req updateCompanyRequest
	if err := decodeJSON(r.Context(), r, &req); err != nil {
		writeError(w, http.StatusBadRequest, err)
		return
	}

	company, err := h.svc.GetCompany(r.Context(), id)
	if err != nil {
		writeError(w, http.StatusNotFound, err)
		return
	}

	if req.Category != nil {
		company.Category = *req.Category
	}
	if req.CNPJ != nil {
		company.CNPJ = *req.CNPJ
	}
	if req.CorporateName != nil {
		company.CorporateName = *req.CorporateName
	}
	if req.LicenseNumber != nil {
		company.LicenseNumber = *req.LicenseNumber
	}
	if req.IsVerified != nil {
		company.IsVerified = *req.IsVerified
	}
	if req.Latitude != nil {
		company.Latitude = *req.Latitude
	}
	if req.Longitude != nil {
		company.Longitude = *req.Longitude
	}
	if req.City != nil {
		company.City = *req.City
	}
	if req.State != nil {
		company.State = *req.State
	}

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

	writeJSON(w, http.StatusOK, company)
}

// DeleteCompany godoc
// @Summary Remover empresa
// @Tags Empresas
// @Param id path string true "Company ID"
// @Success 204 ""
// @Failure 400 {object} map[string]string
// @Failure 404 {object} map[string]string
// @Router /api/v1/companies/{id} [delete]
func (h *Handler) DeleteCompany(w http.ResponseWriter, r *http.Request) {
	id, err := parseUUIDFromPath(r.URL.Path)
	if err != nil {
		writeError(w, http.StatusBadRequest, err)
		return
	}

	if err := h.svc.DeleteCompany(r.Context(), id); err != nil {
		writeError(w, http.StatusBadRequest, err)
		return
	}

	w.WriteHeader(http.StatusNoContent)
}

// VerifyCompany godoc
// @Summary Verificar empresa
// @Tags Empresas
// @Security BearerAuth
// @Param id path string true "Company ID"
// @Success 200 {object} domain.Company
// @Router /api/v1/companies/{id}/verify [patch]
// VerifyCompany toggles the verification flag for a company (admin only).
func (h *Handler) VerifyCompany(w http.ResponseWriter, r *http.Request) {
	if !strings.HasSuffix(r.URL.Path, "/verify") {
		http.NotFound(w, r)
		return
	}

	id, err := parseUUIDFromPath(r.URL.Path)
	if err != nil {
		writeError(w, http.StatusBadRequest, err)
		return
	}

	company, err := h.svc.VerifyCompany(r.Context(), id)
	if err != nil {
		writeError(w, http.StatusInternalServerError, err)
		return
	}

	writeJSON(w, http.StatusOK, company)
}

// GetMyCompany godoc
// @Summary Obter minha empresa
// @Tags Empresas
// @Security BearerAuth
// @Produce json
// @Success 200 {object} domain.Company
// @Router /api/v1/companies/me [get]
// GetMyCompany returns the company linked to the authenticated user.
func (h *Handler) GetMyCompany(w http.ResponseWriter, r *http.Request) {
	claims, ok := middleware.GetClaims(r.Context())
	if !ok || claims.CompanyID == nil {
		writeError(w, http.StatusBadRequest, errors.New("missing company context"))
		return
	}

	company, err := h.svc.GetCompany(r.Context(), *claims.CompanyID)
	if err != nil {
		writeError(w, http.StatusNotFound, err)
		return
	}

	writeJSON(w, http.StatusOK, company)
}

// GetCompanyRating godoc
// @Summary Obter avaliação da empresa
// @Tags Empresas
// @Produce json
// @Param id path string true "Company ID"
// @Success 200 {object} domain.CompanyRating
// @Router /api/v1/companies/{id}/rating [get]
// GetCompanyRating exposes the average score for a company.
func (h *Handler) GetCompanyRating(w http.ResponseWriter, r *http.Request) {
	if !strings.HasSuffix(r.URL.Path, "/rating") {
		http.NotFound(w, r)
		return
	}

	id, err := parseUUIDFromPath(r.URL.Path)
	if err != nil {
		writeError(w, http.StatusBadRequest, err)
		return
	}

	rating, err := h.svc.GetCompanyRating(r.Context(), id)
	if err != nil {
		writeError(w, http.StatusInternalServerError, err)
		return
	}

	writeJSON(w, http.StatusOK, rating)
}
