// Package api provides the HTTP API for mosis-portal
package api

import (
	"log"
	"net/http"

	"github.com/go-chi/chi/v5"
	chimw "github.com/go-chi/chi/v5/middleware"
	"omixlab.com/mosis-portal/internal/api/handlers"
	"omixlab.com/mosis-portal/internal/api/middleware"
	"omixlab.com/mosis-portal/internal/auth"
	"omixlab.com/mosis-portal/internal/config"
	"omixlab.com/mosis-portal/internal/database"
	"omixlab.com/mosis-portal/internal/storage"
	"omixlab.com/mosis-portal/internal/telemetry"
	"omixlab.com/mosis-portal/internal/web"
)

// NewRouter creates and configures the HTTP router
func NewRouter(cfg *config.Config, db *database.DB) http.Handler {
	r := chi.NewRouter()

	// Middleware
	r.Use(chimw.Logger)
	r.Use(chimw.Recoverer)
	r.Use(chimw.RealIP)
	r.Use(chimw.RequestID)

	// Initialize storage
	store, err := storage.New(cfg.StoragePath)
	if err != nil {
		log.Fatalf("Failed to initialize storage: %v", err)
	}

	// Initialize telemetry service
	telemetryDB := cfg.StoragePath + "/telemetry.db"
	telemetrySvc, err := telemetry.New(telemetryDB)
	if err != nil {
		log.Fatalf("Failed to initialize telemetry service: %v", err)
	}

	// Initialize auth components
	jwtManager := auth.NewJWTManager(cfg.JWTSecret)
	oauthManager := auth.NewOAuthManager(
		cfg.BaseURL,
		cfg.GitHubClientID, cfg.GitHubClientSecret,
		cfg.GoogleClientID, cfg.GoogleClientSecret,
	)
	authMiddleware := middleware.NewAuthMiddleware(jwtManager, db)
	authHandler := handlers.NewAuthHandler(oauthManager, jwtManager, db)
	appHandler := handlers.NewAppHandler(db, store)
	storeHandler := handlers.NewStoreHandler(db, store)
	adminHandler := handlers.NewAdminHandler(db, store)
	telemetryHandler := handlers.NewTelemetryHandler(db, telemetrySvc)

	// Health check
	r.Get("/health", func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Write([]byte("ok"))
	})

	// API v1
	r.Route("/v1", func(r chi.Router) {
		// Auth routes (public)
		r.Route("/auth", func(r chi.Router) {
			// OAuth - use GET for initiating (redirect based)
			r.Get("/oauth/github", authHandler.OAuthStart(auth.ProviderGitHub))
			r.Get("/oauth/github/callback", authHandler.OAuthCallback(auth.ProviderGitHub))
			r.Get("/oauth/google", authHandler.OAuthStart(auth.ProviderGoogle))
			r.Get("/oauth/google/callback", authHandler.OAuthCallback(auth.ProviderGoogle))

			// Token management
			r.Post("/refresh", authHandler.Refresh)
			r.Post("/logout", authHandler.Logout)

			// Current user (requires auth)
			r.With(authMiddleware.RequireAuth).Get("/me", authHandler.Me)
		})

		// Protected developer routes
		r.Group(func(r chi.Router) {
			r.Use(authMiddleware.RequireAuth)

			// Developer apps
			r.Route("/apps", func(r chi.Router) {
				r.Get("/", appHandler.List)
				r.Post("/", appHandler.Create)
				r.Get("/{appID}", appHandler.Get)
				r.Patch("/{appID}", appHandler.Update)
				r.Delete("/{appID}", appHandler.Delete)

				// Icon upload
				r.Post("/{appID}/icon", appHandler.UploadIcon)

				// Versions
				r.Route("/{appID}/versions", func(r chi.Router) {
					r.Get("/", appHandler.ListVersions)
					r.Post("/", appHandler.CreateVersion)
					r.Get("/{versionID}", appHandler.GetVersion)
					r.Post("/{versionID}/submit", appHandler.SubmitVersion)
					r.Post("/{versionID}/publish", appHandler.PublishVersion)

					// Package upload
					r.Post("/{versionID}/upload", appHandler.UploadPackage)
				})

				// Analytics
				r.Route("/{appID}/analytics", func(r chi.Router) {
					r.Get("/overview", telemetryHandler.GetAnalyticsOverview)
					r.Get("/events", telemetryHandler.GetAnalyticsEvents)
				})

				// Crashes
				r.Route("/{appID}/crashes", func(r chi.Router) {
					r.Get("/", telemetryHandler.GetCrashes)
					r.Get("/{crashID}", telemetryHandler.GetCrash)
					r.Patch("/{crashID}", telemetryHandler.UpdateCrashStatus)
				})
			})

			// API Keys
			r.Route("/api-keys", func(r chi.Router) {
				r.Get("/", handlers.NotImplemented)
				r.Post("/", handlers.NotImplemented)
				r.Delete("/{keyID}", handlers.NotImplemented)
			})

			// Signing Keys
			r.Route("/signing-keys", func(r chi.Router) {
				r.Get("/", handlers.NotImplemented)
				r.Post("/", handlers.NotImplemented)
				r.Delete("/{keyID}", handlers.NotImplemented)
			})
		})

		// Public store endpoints
		r.Route("/store", func(r chi.Router) {
			r.Get("/apps", storeHandler.ListApps)
			r.Get("/apps/updates", storeHandler.CheckUpdates)
			r.Get("/apps/{packageID}", storeHandler.GetApp)
			r.Get("/apps/{packageID}/download", storeHandler.Download)
			r.Get("/apps/{packageID}/versions/{versionCode}/download", storeHandler.DownloadVersion)
		})

		// Telemetry endpoints (public - devices send events here)
		r.Route("/telemetry", func(r chi.Router) {
			r.Post("/events", telemetryHandler.RecordEvents)
			r.Post("/crash", telemetryHandler.RecordCrash)
		})
	})

	// Admin API routes (JSON responses)
	r.Route("/api/admin", func(r chi.Router) {
		r.Use(authMiddleware.RequireAuth)
		r.Get("/stats", adminHandler.Dashboard)
		r.Get("/review-queue", adminHandler.ReviewQueue)
		r.Get("/review/{versionID}", adminHandler.ReviewDetail)
		r.Post("/review/{versionID}/approve", adminHandler.ApproveVersion)
		r.Post("/review/{versionID}/reject", adminHandler.RejectVersion)
		r.Get("/review/{versionID}/validate", adminHandler.ValidatePackage)
	})

	// Web UI routes (htmx + Go templates)
	webHandler, err := web.NewHandler(db)
	if err != nil {
		log.Printf("Warning: Failed to initialize web handler: %v", err)
	} else {
		webHandler.SetStorage(store)
		webHandler.SetTelemetry(telemetrySvc)
		sessionMW := web.NewSessionMiddleware(db, cfg.JWTSecret)

		// Public web pages
		r.Group(func(r chi.Router) {
			r.Use(sessionMW.LoadSession)
			r.Get("/", func(w http.ResponseWriter, r *http.Request) {
				http.Redirect(w, r, "/dashboard", http.StatusSeeOther)
			})
			r.Get("/login", webHandler.Login)
		})

		// Protected web pages
		r.Group(func(r chi.Router) {
			r.Use(sessionMW.LoadSession)
			r.Use(sessionMW.RequireSession)
			r.Get("/dashboard", webHandler.Dashboard)
			r.Get("/apps/new", webHandler.AppNew)
			r.Get("/apps/{appID}", webHandler.AppDetail)
			r.Get("/apps/{appID}/analytics", webHandler.AppAnalytics)
			r.Get("/apps/{appID}/crashes", webHandler.AppCrashes)

			// htmx partials
			r.Get("/partials/apps", webHandler.AppListPartial)

			// Admin pages (htmx UI)
			r.Get("/admin/review-queue", webHandler.AdminReviewQueue)
			r.Get("/admin/review/{versionID}", webHandler.AdminReviewDetail)
			r.Get("/admin/partials/review-queue", webHandler.AdminReviewQueuePartial)
			r.Post("/admin/review/{versionID}/approve", webHandler.AdminApprove)
			r.Post("/admin/review/{versionID}/reject", webHandler.AdminReject)
			r.Get("/admin/review/{versionID}/validate", webHandler.AdminValidate)
		})

		// Auth callback that sets session (after OAuth)
		r.Get("/auth/callback", func(w http.ResponseWriter, r *http.Request) {
			developerID := r.URL.Query().Get("developer_id")
			if developerID == "" {
				http.Redirect(w, r, "/login?error=Authentication failed", http.StatusSeeOther)
				return
			}
			web.SetSession(w, developerID)
			http.Redirect(w, r, "/dashboard", http.StatusSeeOther)
		})

		// Logout (clears session)
		r.Get("/auth/logout", func(w http.ResponseWriter, r *http.Request) {
			web.ClearSession(w)
			http.Redirect(w, r, "/login", http.StatusSeeOther)
		})
	}

	// Documentation site
	docsHandler, err := web.NewDocsHandler()
	if err != nil {
		log.Printf("Warning: Failed to initialize docs handler: %v", err)
	} else {
		r.Handle("/docs", docsHandler)
		r.Handle("/docs/*", docsHandler)
	}

	// Static file servers for packages and assets
	// Downloads - serve package files with proper headers
	r.Handle("/downloads/*", http.StripPrefix("/downloads/",
		http.FileServer(http.Dir(store.PackagesPath()))))

	// Assets - serve icons and screenshots
	r.Handle("/assets/*", http.StripPrefix("/assets/",
		http.FileServer(http.Dir(store.AssetsPath()))))

	return r
}
