package handlers

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

	"github.com/rede5/gohorsejobs/backend/internal/api/middleware"
	"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
	cloudflareService *services.CloudflareService
}

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, cloudflareService *services.CloudflareService) *AdminHandlers {
	return &AdminHandlers{
		adminService:      adminService,
		auditService:      auditService,
		jobService:        jobService,
		cloudflareService: cloudflareService,
	}
}

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) {
	ctx := r.Context()
	page, _ := strconv.Atoi(r.URL.Query().Get("page"))
	limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
	status := r.URL.Query().Get("status")

	// Extract role and companyID for scoping
	roles := middleware.ExtractRoles(ctx.Value(middleware.ContextRoles))
	isSuperadmin := false
	for _, role := range roles {
		if role == "SUPERADMIN" || role == "superadmin" {
			isSuperadmin = true
			break
		}
	}

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

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

	// If Admin (not Superadmin), scope to their company
	if !isSuperadmin {
		companyID, _ := ctx.Value(middleware.ContextTenantID).(string)
		if companyID != "" {
			filter.CompanyID = &companyID
		}
	}

	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) {
	ctx := r.Context()

	// Extract role for scoping
	roles := middleware.ExtractRoles(ctx.Value(middleware.ContextRoles))
	isSuperadmin := false
	for _, role := range roles {
		if role == "SUPERADMIN" || role == "superadmin" {
			isSuperadmin = true
			break
		}
	}

	var companyID *string
	if !isSuperadmin {
		if cid, ok := ctx.Value(middleware.ContextTenantID).(string); ok && cid != "" {
			companyID = &cid
		}
	}

	candidates, stats, err := h.adminService.ListCandidates(ctx, companyID)
	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)
}

// UpdateCompany updates a company's information
// @Summary      Update Company
// @Description  Updates company information by ID (admin only)
// @Tags         Companies
// @Accept       json
// @Produce      json
// @Param        id   path      string  true  "Company ID"
// @Param        body body      dto.UpdateCompanyRequest  true  "Company update data"
// @Success      200  {object}  object
// @Failure      400  {string}  string "Invalid Request"
// @Failure      401  {string}  string "Unauthorized"
// @Failure      500  {string}  string "Internal Server Error"
// @Security     BearerAuth
// @Router       /api/v1/companies/{id} [patch]
func (h *AdminHandlers) UpdateCompany(w http.ResponseWriter, r *http.Request) {
	id := r.PathValue("id")
	var req dto.UpdateCompanyRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, "Invalid Request", http.StatusBadRequest)
		return
	}

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

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

// DeleteCompany deletes a company
// @Summary      Delete Company
// @Description  Deletes a company by ID (admin only)
// @Tags         Companies
// @Param        id   path      string  true  "Company ID"
// @Success      204  "No Content"
// @Failure      401  {string}  string "Unauthorized"
// @Failure      500  {string}  string "Internal Server Error"
// @Security     BearerAuth
// @Router       /api/v1/companies/{id} [delete]
func (h *AdminHandlers) DeleteCompany(w http.ResponseWriter, r *http.Request) {
	id := r.PathValue("id")
	if err := h.adminService.DeleteCompany(r.Context(), id); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.WriteHeader(http.StatusNoContent)
}

func (h *AdminHandlers) PurgeCache(w http.ResponseWriter, r *http.Request) {
	if err := h.cloudflareService.PurgeCache(r.Context()); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(map[string]string{"message": "Cache purge requested"})
}

// ============================================================================
// Email Templates CRUD Handlers
// ============================================================================

func (h *AdminHandlers) ListEmailTemplates(w http.ResponseWriter, r *http.Request) {
	templates, err := h.adminService.ListEmailTemplates(r.Context())
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(templates)
}

func (h *AdminHandlers) GetEmailTemplate(w http.ResponseWriter, r *http.Request) {
	slug := r.PathValue("slug")
	tmpl, err := h.adminService.GetEmailTemplate(r.Context(), slug)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	if tmpl == nil {
		http.Error(w, "Template not found", http.StatusNotFound)
		return
	}
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(tmpl)
}

func (h *AdminHandlers) CreateEmailTemplate(w http.ResponseWriter, r *http.Request) {
	var req dto.CreateEmailTemplateRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, "Invalid request", http.StatusBadRequest)
		return
	}
	if req.Slug == "" || req.Subject == "" {
		http.Error(w, "Slug and subject are required", http.StatusBadRequest)
		return
	}

	tmpl, err := h.adminService.CreateEmailTemplate(r.Context(), req)
	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(tmpl)
}

func (h *AdminHandlers) UpdateEmailTemplate(w http.ResponseWriter, r *http.Request) {
	slug := r.PathValue("slug")
	var req dto.UpdateEmailTemplateRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, "Invalid request", http.StatusBadRequest)
		return
	}

	tmpl, err := h.adminService.UpdateEmailTemplate(r.Context(), slug, req)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

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

func (h *AdminHandlers) DeleteEmailTemplate(w http.ResponseWriter, r *http.Request) {
	slug := r.PathValue("slug")
	if err := h.adminService.DeleteEmailTemplate(r.Context(), slug); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.WriteHeader(http.StatusNoContent)
}

// ============================================================================
// Email Settings Handlers
// ============================================================================

func (h *AdminHandlers) GetEmailSettings(w http.ResponseWriter, r *http.Request) {
	settings, err := h.adminService.GetEmailSettings(r.Context())
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	if settings == nil {
		// Return empty object with defaults
		settings = &dto.EmailSettingsDTO{
			Provider:    "smtp",
			SMTPSecure:  true,
			SenderName:  "GoHorse Jobs",
			SenderEmail: "no-reply@gohorsejobs.com",
		}
	}
	// Mask password in response
	if settings.SMTPPass != nil {
		masked := "********"
		settings.SMTPPass = &masked
	}
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(settings)
}

func (h *AdminHandlers) UpdateEmailSettings(w http.ResponseWriter, r *http.Request) {
	var req dto.UpdateEmailSettingsRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, "Invalid request", http.StatusBadRequest)
		return
	}

	settings, err := h.adminService.UpdateEmailSettings(r.Context(), req)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	// Mask password in response
	if settings.SMTPPass != nil {
		masked := "********"
		settings.SMTPPass = &masked
	}
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(settings)
}
