package handlers

import (
	"aggios-app/backend/internal/domain"
	"aggios-app/backend/internal/repository"
	"aggios-app/backend/internal/api/middleware"
	"encoding/json"
	"log"
	"net/http"

	"github.com/google/uuid"
	"github.com/gorilla/mux"
)

type SolutionHandler struct {
	repo *repository.SolutionRepository
}

func NewSolutionHandler(repo *repository.SolutionRepository) *SolutionHandler {
	return &SolutionHandler{repo: repo}
}

// ==================== CRUD SOLUTIONS (SUPERADMIN) ====================

func (h *SolutionHandler) CreateSolution(w http.ResponseWriter, r *http.Request) {
	var solution domain.Solution
	if err := json.NewDecoder(r.Body).Decode(&solution); err != nil {
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusBadRequest)
		json.NewEncoder(w).Encode(map[string]string{
			"error":   "Invalid request body",
			"message": err.Error(),
		})
		return
	}

	solution.ID = uuid.New().String()

	if err := h.repo.CreateSolution(&solution); err != nil {
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusInternalServerError)
		json.NewEncoder(w).Encode(map[string]string{
			"error":   "Failed to create solution",
			"message": err.Error(),
		})
		return
	}

	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusCreated)
	json.NewEncoder(w).Encode(map[string]interface{}{
		"solution": solution,
	})
}

func (h *SolutionHandler) GetAllSolutions(w http.ResponseWriter, r *http.Request) {
	solutions, err := h.repo.GetAllSolutions()
	if err != nil {
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusInternalServerError)
		json.NewEncoder(w).Encode(map[string]string{
			"error":   "Failed to fetch solutions",
			"message": err.Error(),
		})
		return
	}

	if solutions == nil {
		solutions = []domain.Solution{}
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(map[string]interface{}{
		"solutions": solutions,
	})
}

func (h *SolutionHandler) GetSolution(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	solutionID := vars["id"]

	solution, err := h.repo.GetSolutionByID(solutionID)
	if err != nil {
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusNotFound)
		json.NewEncoder(w).Encode(map[string]string{
			"error":   "Solution not found",
			"message": err.Error(),
		})
		return
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(map[string]interface{}{
		"solution": solution,
	})
}

func (h *SolutionHandler) UpdateSolution(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	solutionID := vars["id"]

	var solution domain.Solution
	if err := json.NewDecoder(r.Body).Decode(&solution); err != nil {
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusBadRequest)
		json.NewEncoder(w).Encode(map[string]string{
			"error":   "Invalid request body",
			"message": err.Error(),
		})
		return
	}

	solution.ID = solutionID

	if err := h.repo.UpdateSolution(&solution); err != nil {
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusInternalServerError)
		json.NewEncoder(w).Encode(map[string]string{
			"error":   "Failed to update solution",
			"message": err.Error(),
		})
		return
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(map[string]string{
		"message": "Solution updated successfully",
	})
}

func (h *SolutionHandler) DeleteSolution(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	solutionID := vars["id"]

	if err := h.repo.DeleteSolution(solutionID); err != nil {
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusInternalServerError)
		json.NewEncoder(w).Encode(map[string]string{
			"error":   "Failed to delete solution",
			"message": err.Error(),
		})
		return
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(map[string]string{
		"message": "Solution deleted successfully",
	})
}

// ==================== TENANT SOLUTIONS (AGENCY) ====================

func (h *SolutionHandler) GetTenantSolutions(w http.ResponseWriter, r *http.Request) {
	tenantID, _ := r.Context().Value(middleware.TenantIDKey).(string)
	
	log.Printf("🔍 GetTenantSolutions: tenantID=%s", tenantID)
	
	if tenantID == "" {
		log.Printf("❌ GetTenantSolutions: Missing tenant_id")
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusBadRequest)
		json.NewEncoder(w).Encode(map[string]string{
			"error": "Missing tenant_id",
		})
		return
	}

	solutions, err := h.repo.GetTenantSolutions(tenantID)
	if err != nil {
		log.Printf("❌ GetTenantSolutions: Error fetching solutions: %v", err)
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusInternalServerError)
		json.NewEncoder(w).Encode(map[string]string{
			"error":   "Failed to fetch solutions",
			"message": err.Error(),
		})
		return
	}

	log.Printf("✅ GetTenantSolutions: Found %d solutions for tenant %s", len(solutions), tenantID)

	if solutions == nil {
		solutions = []domain.Solution{}
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(map[string]interface{}{
		"solutions": solutions,
	})
}

// ==================== PLAN SOLUTIONS ====================

func (h *SolutionHandler) GetPlanSolutions(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	planID := vars["plan_id"]

	solutions, err := h.repo.GetPlanSolutions(planID)
	if err != nil {
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusInternalServerError)
		json.NewEncoder(w).Encode(map[string]string{
			"error":   "Failed to fetch plan solutions",
			"message": err.Error(),
		})
		return
	}

	if solutions == nil {
		solutions = []domain.Solution{}
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(map[string]interface{}{
		"solutions": solutions,
	})
}

func (h *SolutionHandler) SetPlanSolutions(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	planID := vars["plan_id"]

	var req struct {
		SolutionIDs []string `json:"solution_ids"`
	}

	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusBadRequest)
		json.NewEncoder(w).Encode(map[string]string{
			"error":   "Invalid request body",
			"message": err.Error(),
		})
		return
	}

	if err := h.repo.SetPlanSolutions(planID, req.SolutionIDs); err != nil {
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusInternalServerError)
		json.NewEncoder(w).Encode(map[string]string{
			"error":   "Failed to update plan solutions",
			"message": err.Error(),
		})
		return
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(map[string]string{
		"message": "Plan solutions updated successfully",
	})
}
