package router

import (
	"log"
	"net/http"
	"os"
	"time"

	"github.com/rede5/gohorsejobs/backend/internal/api/middleware"
	"github.com/rede5/gohorsejobs/backend/internal/database"
	"github.com/rede5/gohorsejobs/backend/internal/handlers"
	"github.com/rede5/gohorsejobs/backend/internal/infrastructure/persistence/postgres"
	"github.com/rede5/gohorsejobs/backend/internal/infrastructure/storage"
	"github.com/rede5/gohorsejobs/backend/internal/services"

	// Core Imports
	apiHandlers "github.com/rede5/gohorsejobs/backend/internal/api/handlers"
	authUC "github.com/rede5/gohorsejobs/backend/internal/core/usecases/auth"
	tenantUC "github.com/rede5/gohorsejobs/backend/internal/core/usecases/tenant"
	userUC "github.com/rede5/gohorsejobs/backend/internal/core/usecases/user"
	authInfra "github.com/rede5/gohorsejobs/backend/internal/infrastructure/auth"
	legacyMiddleware "github.com/rede5/gohorsejobs/backend/internal/middleware"

	// Admin Imports
	"github.com/rede5/gohorsejobs/backend/internal/admin/cloudflare"
	"github.com/rede5/gohorsejobs/backend/internal/admin/cpanel"

	_ "github.com/rede5/gohorsejobs/backend/docs" // Import generated docs
	httpSwagger "github.com/swaggo/http-swagger/v2"
)

func NewRouter() http.Handler {
	mux := http.NewServeMux()

	// Initialize Services
	jobService := services.NewJobService(database.DB)
	applicationService := services.NewApplicationService(database.DB)

	// --- CORE ARCHITECTURE INITIALIZATION ---
	// Infrastructure
	// Infrastructure,
	userRepo := postgres.NewUserRepository(database.DB)
	companyRepo := postgres.NewCompanyRepository(database.DB)

	jwtSecret := os.Getenv("JWT_SECRET")
	if jwtSecret == "" {
		// Fallback for dev, but really should be in env
		jwtSecret = "default-dev-secret-do-not-use-in-prod"
	}

	authService := authInfra.NewJWTService(jwtSecret, "todai-jobs")

	// UseCases
	loginUC := authUC.NewLoginUseCase(userRepo, authService)
	createCompanyUC := tenantUC.NewCreateCompanyUseCase(companyRepo, userRepo, authService)
	listCompaniesUC := tenantUC.NewListCompaniesUseCase(companyRepo)
	createUserUC := userUC.NewCreateUserUseCase(userRepo, authService)
	listUsersUC := userUC.NewListUsersUseCase(userRepo)
	deleteUserUC := userUC.NewDeleteUserUseCase(userRepo)

	// Handlers & Middleware
	coreHandlers := apiHandlers.NewCoreHandlers(loginUC, createCompanyUC, createUserUC, listUsersUC, deleteUserUC, listCompaniesUC)
	authMiddleware := middleware.NewMiddleware(authService)

	// Initialize Legacy Handlers
	jobHandler := handlers.NewJobHandler(jobService)
	applicationHandler := handlers.NewApplicationHandler(applicationService)

	// Initialize Admin Handlers
	cloudflareHandler := cloudflare.NewHandler()
	cpanelHandler := cpanel.NewHandler()

	// cachedPublicIP stores the public IP to avoid repeated external calls
	var cachedPublicIP string

	// Helper to get public IP
	getPublicIP := func() string {
		if cachedPublicIP != "" {
			return cachedPublicIP
		}
		client := http.Client{
			Timeout: 2 * time.Second,
		}
		resp, err := client.Get("https://api.ipify.org?format=text")
		if err != nil {
			return "127.0.0.1" // Fallback
		}
		defer resp.Body.Close()

		// simple read
		buf := make([]byte, 64)
		n, err := resp.Body.Read(buf)
		if err != nil && err.Error() != "EOF" {
			return "127.0.0.1"
		}
		cachedPublicIP = string(buf[:n])
		return cachedPublicIP
	}

	// --- ROOT ROUTE ---
	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		if r.URL.Path != "/" {
			http.NotFound(w, r)
			return
		}

		serverIP := getPublicIP()

		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		response := `{
	"message": "🐴 GoHorseJobs API is running!",
	"ip": "` + serverIP + `",
	"docs": "/docs",
	"health": "/health",
	"version": "1.0.0"
}`
		w.Write([]byte(response))
	})

	mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Write([]byte("OK"))
	})

	// --- CORE ROUTES ---
	// Public
	mux.HandleFunc("POST /api/v1/auth/login", coreHandlers.Login)
	mux.HandleFunc("POST /api/v1/companies", coreHandlers.CreateCompany)
	mux.HandleFunc("GET /api/v1/companies", coreHandlers.ListCompanies)

	// Protected
	// Note: In Go 1.22+, we can wrap specific patterns. Or we can just wrap the handler.
	// For simplicity, we wrap the handler function.
	mux.Handle("POST /api/v1/users", authMiddleware.HeaderAuthGuard(http.HandlerFunc(coreHandlers.CreateUser)))
	mux.Handle("GET /api/v1/users", authMiddleware.HeaderAuthGuard(http.HandlerFunc(coreHandlers.ListUsers)))
	mux.Handle("DELETE /api/v1/users/{id}", authMiddleware.HeaderAuthGuard(http.HandlerFunc(coreHandlers.DeleteUser)))

	// Job Routes
	mux.HandleFunc("GET /jobs", jobHandler.GetJobs)
	mux.HandleFunc("POST /jobs", jobHandler.CreateJob)
	mux.HandleFunc("GET /jobs/{id}", jobHandler.GetJobByID)
	mux.HandleFunc("PUT /jobs/{id}", jobHandler.UpdateJob)
	mux.HandleFunc("DELETE /jobs/{id}", jobHandler.DeleteJob)

	// Application Routes
	mux.HandleFunc("POST /applications", applicationHandler.CreateApplication)
	mux.HandleFunc("GET /applications", applicationHandler.GetApplications)
	mux.HandleFunc("GET /applications/{id}", applicationHandler.GetApplicationByID)
	mux.HandleFunc("PUT /applications/{id}/status", applicationHandler.UpdateApplicationStatus)

	// --- STORAGE ROUTES ---
	// Initialize S3 Storage (optional - graceful degradation if not configured)
	s3Storage, err := storage.NewS3Storage()
	if err != nil {
		log.Printf("Warning: S3 storage not available: %v", err)
	} else {
		storageHandler := handlers.NewStorageHandler(s3Storage)
		mux.Handle("POST /api/v1/storage/upload-url", authMiddleware.HeaderAuthGuard(http.HandlerFunc(storageHandler.GenerateUploadURL)))
		mux.Handle("POST /api/v1/storage/download-url", authMiddleware.HeaderAuthGuard(http.HandlerFunc(storageHandler.GenerateDownloadURL)))
		mux.Handle("DELETE /api/v1/storage/files", authMiddleware.HeaderAuthGuard(http.HandlerFunc(storageHandler.DeleteFile)))
		log.Println("S3 storage routes registered successfully")
	}

	// --- ADMIN ROUTES (Protected - SuperAdmin only) ---
	// Cloudflare Cache Management
	mux.Handle("GET /api/v1/admin/cloudflare/zones", authMiddleware.HeaderAuthGuard(http.HandlerFunc(cloudflareHandler.GetZones)))
	mux.Handle("POST /api/v1/admin/cloudflare/cache/purge-all", authMiddleware.HeaderAuthGuard(http.HandlerFunc(cloudflareHandler.PurgeAll)))
	mux.Handle("POST /api/v1/admin/cloudflare/cache/purge-urls", authMiddleware.HeaderAuthGuard(http.HandlerFunc(cloudflareHandler.PurgeByURLs)))
	mux.Handle("POST /api/v1/admin/cloudflare/cache/purge-tags", authMiddleware.HeaderAuthGuard(http.HandlerFunc(cloudflareHandler.PurgeByTags)))
	mux.Handle("POST /api/v1/admin/cloudflare/cache/purge-hosts", authMiddleware.HeaderAuthGuard(http.HandlerFunc(cloudflareHandler.PurgeByHosts)))

	// cPanel Email Management
	mux.Handle("GET /api/v1/admin/cpanel/emails", authMiddleware.HeaderAuthGuard(http.HandlerFunc(cpanelHandler.ListEmails)))
	mux.Handle("POST /api/v1/admin/cpanel/emails", authMiddleware.HeaderAuthGuard(http.HandlerFunc(cpanelHandler.CreateEmail)))
	mux.Handle("DELETE /api/v1/admin/cpanel/emails/{email}", authMiddleware.HeaderAuthGuard(http.HandlerFunc(cpanelHandler.DeleteEmail)))
	mux.Handle("PUT /api/v1/admin/cpanel/emails/{email}/password", authMiddleware.HeaderAuthGuard(http.HandlerFunc(cpanelHandler.ChangePassword)))
	mux.Handle("PUT /api/v1/admin/cpanel/emails/{email}/quota", authMiddleware.HeaderAuthGuard(http.HandlerFunc(cpanelHandler.UpdateQuota)))

	log.Println("Admin routes (Cloudflare, cPanel) registered successfully")

	// Swagger Route - available at /docs
	mux.HandleFunc("/docs/", httpSwagger.WrapHandler)

	// Apply middleware chain: Security Headers -> Rate Limiting -> CORS -> Router
	// Order matters: outer middleware runs first
	var handler http.Handler = mux
	handler = middleware.CORSMiddleware(handler)
	handler = legacyMiddleware.RateLimitMiddleware(100, time.Minute)(handler) // 100 req/min per IP
	handler = legacyMiddleware.SecurityHeadersMiddleware(handler)

	return handler
}
