package handlers

import (
	"encoding/json"
	"net/http"
	"strconv"

	"github.com/rede5/gohorsejobs/backend/internal/dto"
	"github.com/rede5/gohorsejobs/backend/internal/services"
)

type AdminHandlers struct {
	adminService *services.AdminService
	auditService *services.AuditService
	jobService   *services.JobService
}

type RoleAccess struct {
	Role        string   `json:"role"`
	Description string   `json:"description"`
	Actions     []string `json:"actions"`
}

type UpdateCompanyStatusRequest struct {
	Active   *bool `json:"active,omitempty"`
	Verified *bool `json:"verified,omitempty"`
}

type UpdateJobStatusRequest struct {
	Status string `json:"status"`
}

type CreateTagRequest struct {
	Name     string `json:"name"`
	Category string `json:"category"`
}

type UpdateTagRequest struct {
	Name   *string `json:"name,omitempty"`
	Active *bool   `json:"active,omitempty"`
}

func NewAdminHandlers(adminService *services.AdminService, auditService *services.AuditService, jobService *services.JobService) *AdminHandlers {
	return &AdminHandlers{
		adminService: adminService,
		auditService: auditService,
		jobService:   jobService,
	}
}

func (h *AdminHandlers) ListAccessRoles(w http.ResponseWriter, r *http.Request) {
	roles := []RoleAccess{
		{
			Role:        "admin",
			Description: "Administrador geral da plataforma",
			Actions: []string{
				"criar/editar/excluir usuários",
				"aprovar empresas",
				"moderar vagas",
				"gerir tags e categorias",
			},
		},
		{
			Role:        "moderador",
			Description: "Moderação de vagas e conteúdo",
			Actions: []string{
				"aprovar, recusar ou pausar vagas",
				"marcar vagas denunciadas",
				"revisar empresas pendentes",
			},
		},
		{
			Role:        "suporte",
			Description: "Suporte ao usuário",
			Actions: []string{
				"acessar perfil de usuário",
				"resetar senhas",
				"analisar logs de acesso",
			},
		},
		{
			Role:        "financeiro",
			Description: "Gestão financeira e faturamento",
			Actions: []string{
				"ver planos e pagamentos",
				"exportar relatórios financeiros",
				"controlar notas e cobranças",
			},
		},
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(roles)
}

func (h *AdminHandlers) ListLoginAudits(w http.ResponseWriter, r *http.Request) {
	limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
	entries, err := h.auditService.ListLogins(r.Context(), limit)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(entries)
}

func (h *AdminHandlers) ListCompanies(w http.ResponseWriter, r *http.Request) {
	page, _ := strconv.Atoi(r.URL.Query().Get("page"))
	if page < 1 {
		page = 1
	}
	limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
	if limit < 1 {
		limit = 10
	}

	var verified *bool
	if verifiedParam := r.URL.Query().Get("verified"); verifiedParam != "" {
		value := verifiedParam == "true"
		verified = &value
	}

	companies, total, err := h.adminService.ListCompanies(r.Context(), verified, page, limit)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	response := dto.PaginatedResponse{
		Data: companies,
		Pagination: dto.Pagination{
			Page:  page,
			Limit: limit,
			Total: total,
		},
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(response)
}

func (h *AdminHandlers) UpdateCompanyStatus(w http.ResponseWriter, r *http.Request) {
	id := r.PathValue("id")

	var req UpdateCompanyStatusRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, "Invalid Request", http.StatusBadRequest)
		return
	}

	company, err := h.adminService.UpdateCompanyStatus(r.Context(), id, req.Active, req.Verified)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(company)
}

func (h *AdminHandlers) ListJobs(w http.ResponseWriter, r *http.Request) {
	page, _ := strconv.Atoi(r.URL.Query().Get("page"))
	limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
	status := r.URL.Query().Get("status")

	filter := dto.JobFilterQuery{
		PaginationQuery: dto.PaginationQuery{
			Page:  page,
			Limit: limit,
		},
	}

	if status != "" {
		filter.Status = &status
	}

	jobs, total, err := h.jobService.GetJobs(filter)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	response := dto.PaginatedResponse{
		Data: jobs,
		Pagination: dto.Pagination{
			Page:  page,
			Limit: limit,
			Total: total,
		},
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(response)
}

func (h *AdminHandlers) UpdateJobStatus(w http.ResponseWriter, r *http.Request) {
	id := r.PathValue("id")

	var req UpdateJobStatusRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, "Invalid Request", http.StatusBadRequest)
		return
	}
	if req.Status == "" {
		http.Error(w, "Status is required", http.StatusBadRequest)
		return
	}

	status := req.Status
	job, err := h.jobService.UpdateJob(id, dto.UpdateJobRequest{Status: &status})
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(job)
}

func (h *AdminHandlers) DuplicateJob(w http.ResponseWriter, r *http.Request) {
	id := r.PathValue("id")

	job, err := h.adminService.DuplicateJob(r.Context(), id)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusCreated)
	json.NewEncoder(w).Encode(job)
}

func (h *AdminHandlers) ListTags(w http.ResponseWriter, r *http.Request) {
	category := r.URL.Query().Get("category")
	if category == "" {
		category = ""
	}

	var categoryFilter *string
	if category != "" {
		categoryFilter = &category
	}

	tags, err := h.adminService.ListTags(r.Context(), categoryFilter)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(tags)
}

func (h *AdminHandlers) CreateTag(w http.ResponseWriter, r *http.Request) {
	var req CreateTagRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, "Invalid Request", http.StatusBadRequest)
		return
	}
	if req.Name == "" || req.Category == "" {
		http.Error(w, "Name and category are required", http.StatusBadRequest)
		return
	}

	tag, err := h.adminService.CreateTag(r.Context(), req.Name, req.Category)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusCreated)
	json.NewEncoder(w).Encode(tag)
}

func (h *AdminHandlers) UpdateTag(w http.ResponseWriter, r *http.Request) {
	idStr := r.PathValue("id")
	id, err := strconv.Atoi(idStr)
	if err != nil {
		http.Error(w, "Invalid tag ID", http.StatusBadRequest)
		return
	}

	var req UpdateTagRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, "Invalid Request", http.StatusBadRequest)
		return
	}

	tag, err := h.adminService.UpdateTag(r.Context(), id, req.Name, req.Active)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(tag)
}

func (h *AdminHandlers) ListCandidates(w http.ResponseWriter, r *http.Request) {
	candidates, stats, err := h.adminService.ListCandidates(r.Context())
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	response := dto.CandidateListResponse{
		Stats:      stats,
		Candidates: candidates,
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(response)
}
