// Package handlers contains HTTP request handlers
package handlers

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

	"github.com/go-chi/chi/v5"
	"omixlab.com/mosis-portal/internal/database"
	"omixlab.com/mosis-portal/internal/review"
	"omixlab.com/mosis-portal/internal/storage"
)

// AdminHandler handles admin operations
type AdminHandler struct {
	db      *database.DB
	store   *storage.Storage
	review  *review.Service
}

// NewAdminHandler creates a new admin handler
func NewAdminHandler(db *database.DB, store *storage.Storage) *AdminHandler {
	return &AdminHandler{
		db:     db,
		store:  store,
		review: review.New(db),
	}
}

// Dashboard returns the admin dashboard with stats
func (h *AdminHandler) Dashboard(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()

	pending, approved, rejected, err := h.db.GetReviewStats(ctx)
	if err != nil {
		Error(w, http.StatusInternalServerError, "database_error", err.Error())
		return
	}

	JSON(w, http.StatusOK, map[string]interface{}{
		"stats": map[string]int{
			"pending":  pending,
			"approved": approved,
			"rejected": rejected,
		},
	})
}

// ReviewQueue lists versions pending review
func (h *AdminHandler) ReviewQueue(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()

	// Parse pagination
	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 > 100 {
		limit = 20
	}
	offset := (page - 1) * limit

	versions, total, err := h.db.GetVersionsInReview(ctx, limit, offset)
	if err != nil {
		Error(w, http.StatusInternalServerError, "database_error", err.Error())
		return
	}

	JSON(w, http.StatusOK, map[string]interface{}{
		"items": versions,
		"pagination": map[string]int{
			"page":       page,
			"limit":      limit,
			"total":      total,
			"total_pages": (total + limit - 1) / limit,
		},
	})
}

// ReviewDetail returns details for a specific version under review
func (h *AdminHandler) ReviewDetail(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()
	versionID := chi.URLParam(r, "versionID")

	versionWithApp, err := h.db.GetVersionWithApp(ctx, versionID)
	if err != nil {
		Error(w, http.StatusNotFound, "not_found", "Version not found")
		return
	}

	// If package exists, run validation to get flags
	var validationResult *review.FullValidationResult
	if versionWithApp.Version.PackageURL != "" {
		packagePath := h.store.GetPackagePath(versionWithApp.Version.PackageURL)
		result, err := h.review.ValidatePackage(packagePath)
		if err == nil {
			validationResult = result
		}
	}

	JSON(w, http.StatusOK, map[string]interface{}{
		"version":    versionWithApp.Version,
		"app":        versionWithApp.App,
		"developer": map[string]string{
			"name":  versionWithApp.DeveloperName,
			"email": versionWithApp.DeveloperEmail,
		},
		"validation": validationResult,
	})
}

// ApproveVersion approves a version
func (h *AdminHandler) ApproveVersion(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()
	versionID := chi.URLParam(r, "versionID")

	// Parse request body
	var req struct {
		Notes string `json:"notes"`
	}
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		// Notes are optional, continue with empty
	}

	// Verify version exists and is in review
	version, err := h.db.GetVersion(ctx, versionID)
	if err != nil {
		Error(w, http.StatusNotFound, "not_found", "Version not found")
		return
	}

	if version.Status != "in_review" {
		Error(w, http.StatusBadRequest, "invalid_status", "Version is not in review")
		return
	}

	// Approve the version
	if err := h.review.ApproveVersion(ctx, versionID, req.Notes); err != nil {
		Error(w, http.StatusInternalServerError, "database_error", err.Error())
		return
	}

	JSON(w, http.StatusOK, map[string]interface{}{
		"success": true,
		"message": "Version approved and published",
	})
}

// RejectVersion rejects a version
func (h *AdminHandler) RejectVersion(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()
	versionID := chi.URLParam(r, "versionID")

	// Parse request body
	var req struct {
		Reason  string `json:"reason"`
		Message string `json:"message"`
	}
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		Error(w, http.StatusBadRequest, "invalid_body", "Invalid request body")
		return
	}

	if req.Reason == "" {
		Error(w, http.StatusBadRequest, "missing_reason", "Rejection reason is required")
		return
	}

	// Verify version exists and is in review
	version, err := h.db.GetVersion(ctx, versionID)
	if err != nil {
		Error(w, http.StatusNotFound, "not_found", "Version not found")
		return
	}

	if version.Status != "in_review" {
		Error(w, http.StatusBadRequest, "invalid_status", "Version is not in review")
		return
	}

	// Reject the version
	feedback := &review.RejectionFeedback{
		Reason:      req.Reason,
		Message:     req.Message,
		CanResubmit: true,
	}
	if err := h.review.RejectVersion(ctx, versionID, feedback); err != nil {
		Error(w, http.StatusInternalServerError, "database_error", err.Error())
		return
	}

	JSON(w, http.StatusOK, map[string]interface{}{
		"success": true,
		"message": "Version rejected",
	})
}

// ValidatePackage runs validation on a package and returns results
func (h *AdminHandler) ValidatePackage(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()
	versionID := chi.URLParam(r, "versionID")

	// Get version with package info
	version, err := h.db.GetVersion(ctx, versionID)
	if err != nil {
		Error(w, http.StatusNotFound, "not_found", "Version not found")
		return
	}

	if version.PackageURL == "" {
		Error(w, http.StatusBadRequest, "no_package", "Version has no uploaded package")
		return
	}

	// Run validation
	packagePath := h.store.GetPackagePath(version.PackageURL)
	result, err := h.review.ValidatePackage(packagePath)
	if err != nil {
		Error(w, http.StatusInternalServerError, "validation_error", err.Error())
		return
	}

	JSON(w, http.StatusOK, result)
}
