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"

	_ "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)

	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")
	}

	// Swagger Route
	mux.HandleFunc("/swagger/", 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
}
