package handlers

import (
	"fmt"
	"net/http"
	"strconv"

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

// StoreHandler handles public store endpoints
type StoreHandler struct {
	db      *database.DB
	storage *storage.Storage
}

// NewStoreHandler creates a new store handler
func NewStoreHandler(db *database.DB, store *storage.Storage) *StoreHandler {
	return &StoreHandler{db: db, storage: store}
}

// ListApps returns published apps for the store
func (h *StoreHandler) ListApps(w http.ResponseWriter, r *http.Request) {
	// Parse query parameters
	query := r.URL.Query().Get("q")
	category := r.URL.Query().Get("category")
	sort := r.URL.Query().Get("sort")
	page, _ := strconv.Atoi(r.URL.Query().Get("page"))
	limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))

	if page < 1 {
		page = 1
	}
	if limit < 1 || limit > 100 {
		limit = 20
	}

	apps, total, err := h.db.ListPublishedApps(r.Context(), query, category, sort, page, limit)
	if err != nil {
		Error(w, "failed to list apps: "+err.Error(), http.StatusInternalServerError)
		return
	}

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

// GetApp returns a published app by package ID
func (h *StoreHandler) GetApp(w http.ResponseWriter, r *http.Request) {
	packageID := chi.URLParam(r, "packageID")

	app, err := h.db.GetPublishedApp(r.Context(), packageID)
	if err != nil {
		Error(w, "app not found", http.StatusNotFound)
		return
	}

	JSON(w, http.StatusOK, app)
}

// Download returns download info for the latest version of an app
func (h *StoreHandler) Download(w http.ResponseWriter, r *http.Request) {
	packageID := chi.URLParam(r, "packageID")

	// Get app to find developer ID
	app, err := h.db.GetAppByPackageID(r.Context(), packageID)
	if err != nil {
		Error(w, "app not found", http.StatusNotFound)
		return
	}

	version, err := h.db.GetLatestPublishedVersion(r.Context(), packageID)
	if err != nil {
		Error(w, "no published version found", http.StatusNotFound)
		return
	}

	// Build download URL
	downloadURL := fmt.Sprintf("/downloads/%s/%s/%d/package.mosis",
		app.DeveloperID, app.ID, version.VersionCode)

	JSON(w, http.StatusOK, map[string]interface{}{
		"download_url": downloadURL,
		"version":      version.VersionName,
		"version_code": version.VersionCode,
		"size":         version.PackageSize,
		"signature":    version.Signature,
	})
}

// DownloadVersion returns download info for a specific version
func (h *StoreHandler) DownloadVersion(w http.ResponseWriter, r *http.Request) {
	packageID := chi.URLParam(r, "packageID")
	versionCodeStr := chi.URLParam(r, "versionCode")

	versionCode, err := strconv.Atoi(versionCodeStr)
	if err != nil {
		Error(w, "invalid version code", http.StatusBadRequest)
		return
	}

	// Get app to find developer ID
	app, err := h.db.GetAppByPackageID(r.Context(), packageID)
	if err != nil {
		Error(w, "app not found", http.StatusNotFound)
		return
	}

	version, err := h.db.GetPublishedVersionByCode(r.Context(), packageID, versionCode)
	if err != nil {
		Error(w, "version not found", http.StatusNotFound)
		return
	}

	// Build download URL
	downloadURL := fmt.Sprintf("/downloads/%s/%s/%d/package.mosis",
		app.DeveloperID, app.ID, version.VersionCode)

	JSON(w, http.StatusOK, map[string]interface{}{
		"download_url": downloadURL,
		"version":      version.VersionName,
		"version_code": version.VersionCode,
		"size":         version.PackageSize,
		"signature":    version.Signature,
	})
}

// CheckUpdates checks for app updates
func (h *StoreHandler) CheckUpdates(w http.ResponseWriter, r *http.Request) {
	// Parse request body for installed apps
	// For now, return empty updates
	JSON(w, http.StatusOK, map[string]interface{}{
		"updates": []interface{}{},
	})
}
