package router

import (
	"encoding/json"
	"net/http"
	"os"
	"time"

	// Added this import
	"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/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/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)
	locationRepo := postgres.NewLocationRepository(database.DB)

	// Utils Services (Moved up for dependency injection)
	credentialsService := services.NewCredentialsService(database.DB)
	settingsService := services.NewSettingsService(database.DB)
	storageService := services.NewStorageService(credentialsService)
	fcmService := services.NewFCMService(credentialsService)
	cloudflareService := services.NewCloudflareService(credentialsService)
	emailService := services.NewEmailService(database.DB, credentialsService)
	locationService := services.NewLocationService(locationRepo)

	adminService := services.NewAdminService(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)
	registerCandidateUC := authUC.NewRegisterCandidateUseCase(userRepo, companyRepo, authService, emailService)
	createCompanyUC := tenantUC.NewCreateCompanyUseCase(companyRepo, userRepo, authService)
	listCompaniesUC := tenantUC.NewListCompaniesUseCase(companyRepo)
	createUserUC := userUC.NewCreateUserUseCase(userRepo, authService)
	listUsersUC := userUC.NewListUsersUseCase(userRepo)
	deleteUserUC := userUC.NewDeleteUserUseCase(userRepo)
	updateUserUC := userUC.NewUpdateUserUseCase(userRepo)
	updatePasswordUC := userUC.NewUpdatePasswordUseCase(userRepo, authService)
	auditService := services.NewAuditService(database.DB)
	notificationService := services.NewNotificationService(database.DB, fcmService)
	ticketService := services.NewTicketService(database.DB)
	authMiddleware := middleware.NewMiddleware(authService)

	// Chat Services
	appwriteService := services.NewAppwriteService(credentialsService)
	chatService := services.NewChatService(database.DB, appwriteService)
	chatHandlers := apiHandlers.NewChatHandlers(chatService)

	coreHandlers := apiHandlers.NewCoreHandlers(
		loginUC,
		registerCandidateUC,
		createCompanyUC,
		createUserUC,
		listUsersUC,
		deleteUserUC,
		updateUserUC,
		updatePasswordUC,
		listCompaniesUC,
		auditService,
		notificationService, // Added
		ticketService,       // Added
		adminService,        // Added for RBAC support
		credentialsService,  // Added for Encrypted Credentials
	)

	settingsHandler := apiHandlers.NewSettingsHandler(settingsService)
	storageHandler := apiHandlers.NewStorageHandler(storageService)
	adminHandlers := apiHandlers.NewAdminHandlers(adminService, auditService, jobService, cloudflareService)
	locationHandlers := apiHandlers.NewLocationHandlers(locationService)

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

	// --- IP HELPER ---
	GetClientIP := func(r *http.Request) string {
		forwarded := r.Header.Get("X-Forwarded-For")
		if forwarded != "" {
			return forwarded
		}
		return r.RemoteAddr
	}

	// --- HEALTH CHECK ---
	mux.HandleFunc("GET /health", func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "text/plain")
		w.Write([]byte("OK"))
	})

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

		response := map[string]interface{}{
			"message": "🐴 GoHorseJobs API is running!",
			"ip":      GetClientIP(r),
			"docs":    "/docs",
			"health":  "/health",
			"version": "1.0.0",
		}

		w.Header().Set("Content-Type", "application/json")
		if err := json.NewEncoder(w).Encode(response); err != nil {
			http.Error(w, "Internal Server Error", http.StatusInternalServerError)
		}
	})

	// --- CORE ROUTES ---
	// Public
	mux.HandleFunc("POST /api/v1/auth/login", coreHandlers.Login)
	mux.HandleFunc("POST /api/v1/auth/logout", coreHandlers.Logout)
	mux.HandleFunc("POST /api/v1/auth/register", coreHandlers.RegisterCandidate)
	mux.HandleFunc("POST /api/v1/auth/register/candidate", coreHandlers.RegisterCandidate)
	mux.HandleFunc("POST /api/v1/auth/register/company", coreHandlers.CreateCompany)
	mux.HandleFunc("POST /api/v1/companies", coreHandlers.CreateCompany)
	// Public/Protected with RBAC (Smart Handler)
	mux.Handle("GET /api/v1/companies", authMiddleware.OptionalHeaderAuthGuard(http.HandlerFunc(coreHandlers.ListCompanies)))

	adminOnly := authMiddleware.RequireRoles("ADMIN", "SUPERADMIN", "admin", "superadmin")

	// Protected Core
	mux.Handle("POST /api/v1/users", authMiddleware.HeaderAuthGuard(http.HandlerFunc(coreHandlers.CreateUser)))
	mux.Handle("GET /api/v1/users", authMiddleware.HeaderAuthGuard(adminOnly(http.HandlerFunc(coreHandlers.ListUsers))))
	mux.Handle("PATCH /api/v1/users/{id}", authMiddleware.HeaderAuthGuard(http.HandlerFunc(coreHandlers.UpdateUser)))
	mux.Handle("DELETE /api/v1/users/{id}", authMiddleware.HeaderAuthGuard(http.HandlerFunc(coreHandlers.DeleteUser)))

	// Job Routes
	mux.HandleFunc("GET /api/v1/jobs", jobHandler.GetJobs)
	mux.Handle("POST /api/v1/jobs", authMiddleware.HeaderAuthGuard(http.HandlerFunc(jobHandler.CreateJob)))
	mux.HandleFunc("GET /api/v1/jobs/{id}", jobHandler.GetJobByID)
	mux.Handle("PUT /api/v1/jobs/{id}", authMiddleware.HeaderAuthGuard(http.HandlerFunc(jobHandler.UpdateJob)))
	mux.Handle("DELETE /api/v1/jobs/{id}", authMiddleware.HeaderAuthGuard(http.HandlerFunc(jobHandler.DeleteJob)))

	// --- ADMIN ROUTES (Consolidated to Standard Paths with RBAC) ---
	// /api/v1/admin/access/roles -> /api/v1/users/roles
	mux.Handle("GET /api/v1/users/roles", authMiddleware.HeaderAuthGuard(adminOnly(http.HandlerFunc(adminHandlers.ListAccessRoles))))

	// /api/v1/admin/audit/logins -> /api/v1/audit/logins
	mux.Handle("GET /api/v1/audit/logins", authMiddleware.HeaderAuthGuard(adminOnly(http.HandlerFunc(adminHandlers.ListLoginAudits))))

	// Public /api/v1/users/me (Authenticated)
	mux.Handle("GET /api/v1/users/me", authMiddleware.HeaderAuthGuard(http.HandlerFunc(coreHandlers.Me)))
	mux.Handle("PATCH /api/v1/users/me/profile", authMiddleware.HeaderAuthGuard(http.HandlerFunc(coreHandlers.UpdateMyProfile)))
	mux.Handle("PATCH /api/v1/users/me/password", authMiddleware.HeaderAuthGuard(http.HandlerFunc(coreHandlers.UpdateMyPassword)))

	// /api/v1/admin/companies -> Handled by coreHandlers.ListCompanies (Smart Branching)
	// Needs to be wired with Optional Auth to support both Public and Admin.
	// I will create OptionalHeaderAuthGuard in middleware next.

	// Company Management
	mux.Handle("PATCH /api/v1/companies/{id}/status", authMiddleware.HeaderAuthGuard(adminOnly(http.HandlerFunc(adminHandlers.UpdateCompanyStatus))))
	mux.Handle("PATCH /api/v1/companies/{id}", authMiddleware.HeaderAuthGuard(adminOnly(http.HandlerFunc(adminHandlers.UpdateCompany))))
	mux.Handle("DELETE /api/v1/companies/{id}", authMiddleware.HeaderAuthGuard(adminOnly(http.HandlerFunc(adminHandlers.DeleteCompany))))

	// /api/v1/admin/jobs -> /api/v1/jobs?mode=admin (Need Smart Handler) or just separate path /api/v1/jobs/management?
	// User said "remove admin from ALL routes".
	// Maybe /api/v1/management/jobs?
	// Or just /api/v1/jobs (guarded)?
	// JobHandler.GetJobs is Public.
	// I will leave /api/v1/admin/jobs mapped to `GET /api/v1/jobs` for now (Collision).
	// OK, I will map it to `GET /api/v1/jobs/moderation` for clearer distinction without "admin" prefix?
	// Or simply `GET /api/v1/jobs` handle it?
	// Given safe constraints, `GET /api/v1/jobs/moderation` is safer than breaking public `GET /api/v1/jobs`.
	mux.Handle("GET /api/v1/jobs/moderation", authMiddleware.HeaderAuthGuard(adminOnly(http.HandlerFunc(adminHandlers.ListJobs))))

	// /api/v1/admin/jobs/{id}/status
	mux.Handle("PATCH /api/v1/jobs/{id}/status", authMiddleware.HeaderAuthGuard(adminOnly(http.HandlerFunc(adminHandlers.UpdateJobStatus))))

	// /api/v1/admin/jobs/{id}/duplicate -> /api/v1/jobs/{id}/duplicate
	mux.Handle("POST /api/v1/jobs/{id}/duplicate", authMiddleware.HeaderAuthGuard(adminOnly(http.HandlerFunc(adminHandlers.DuplicateJob))))

	// /api/v1/tags (GET public/auth, POST/PATCH admin)
	mux.Handle("GET /api/v1/tags", authMiddleware.HeaderAuthGuard(http.HandlerFunc(adminHandlers.ListTags)))
	mux.Handle("POST /api/v1/tags", authMiddleware.HeaderAuthGuard(adminOnly(http.HandlerFunc(adminHandlers.CreateTag))))
	mux.Handle("PATCH /api/v1/tags/{id}", authMiddleware.HeaderAuthGuard(adminOnly(http.HandlerFunc(adminHandlers.UpdateTag))))

	// /api/v1/admin/candidates -> /api/v1/candidates
	mux.Handle("GET /api/v1/candidates", authMiddleware.HeaderAuthGuard(adminOnly(http.HandlerFunc(adminHandlers.ListCandidates))))

	// Get Company by ID (Public)
	mux.HandleFunc("GET /api/v1/companies/{id}", coreHandlers.GetCompanyByID)

	// Location Routes (Public)
	mux.HandleFunc("GET /api/v1/locations/countries", locationHandlers.ListCountries)
	mux.HandleFunc("GET /api/v1/locations/countries/{id}/states", locationHandlers.ListStatesByCountry)
	mux.HandleFunc("GET /api/v1/locations/states/{id}/cities", locationHandlers.ListCitiesByState)
	mux.HandleFunc("GET /api/v1/locations/search", locationHandlers.SearchLocations)

	// Notifications Route
	mux.Handle("GET /api/v1/notifications", authMiddleware.HeaderAuthGuard(http.HandlerFunc(coreHandlers.ListNotifications)))
	mux.Handle("POST /api/v1/tokens", authMiddleware.HeaderAuthGuard(http.HandlerFunc(coreHandlers.SaveFCMToken)))

	// Support Ticket Routes
	mux.Handle("GET /api/v1/support/tickets", authMiddleware.HeaderAuthGuard(http.HandlerFunc(coreHandlers.ListTickets)))
	mux.Handle("POST /api/v1/support/tickets", authMiddleware.HeaderAuthGuard(http.HandlerFunc(coreHandlers.CreateTicket)))
	mux.Handle("GET /api/v1/support/tickets/all", authMiddleware.HeaderAuthGuard(http.HandlerFunc(coreHandlers.ListAllTickets)))
	mux.Handle("GET /api/v1/support/tickets/{id}", authMiddleware.HeaderAuthGuard(http.HandlerFunc(coreHandlers.GetTicket)))
	mux.Handle("POST /api/v1/support/tickets/{id}/messages", authMiddleware.HeaderAuthGuard(http.HandlerFunc(coreHandlers.AddMessage)))
	mux.Handle("PATCH /api/v1/support/tickets/{id}", authMiddleware.HeaderAuthGuard(http.HandlerFunc(coreHandlers.UpdateTicket)))
	mux.Handle("PATCH /api/v1/support/tickets/{id}/close", authMiddleware.HeaderAuthGuard(http.HandlerFunc(coreHandlers.CloseTicket)))
	mux.Handle("DELETE /api/v1/support/tickets/{id}", authMiddleware.HeaderAuthGuard(http.HandlerFunc(coreHandlers.DeleteTicket)))

	// System Settings
	mux.Handle("GET /api/v1/system/settings/{key}", authMiddleware.OptionalHeaderAuthGuard(http.HandlerFunc(settingsHandler.GetSettings)))
	mux.Handle("POST /api/v1/system/settings/{key}", authMiddleware.HeaderAuthGuard(adminOnly(http.HandlerFunc(settingsHandler.SaveSettings))))

	// Storage (Presigned URL)
	mux.Handle("GET /api/v1/storage/upload-url", authMiddleware.OptionalHeaderAuthGuard(http.HandlerFunc(storageHandler.GetUploadURL)))
	// Storage (Direct Proxy)
	mux.Handle("POST /api/v1/storage/upload", authMiddleware.OptionalHeaderAuthGuard(http.HandlerFunc(storageHandler.UploadFile)))

	mux.Handle("POST /api/v1/system/cloudflare/purge", authMiddleware.HeaderAuthGuard(adminOnly(http.HandlerFunc(adminHandlers.PurgeCache))))

	// Email Templates & Settings (Admin Only)
	mux.Handle("GET /api/v1/admin/email-templates", authMiddleware.HeaderAuthGuard(adminOnly(http.HandlerFunc(adminHandlers.ListEmailTemplates))))
	mux.Handle("POST /api/v1/admin/email-templates", authMiddleware.HeaderAuthGuard(adminOnly(http.HandlerFunc(adminHandlers.CreateEmailTemplate))))
	mux.Handle("GET /api/v1/admin/email-templates/{slug}", authMiddleware.HeaderAuthGuard(adminOnly(http.HandlerFunc(adminHandlers.GetEmailTemplate))))
	mux.Handle("PUT /api/v1/admin/email-templates/{slug}", authMiddleware.HeaderAuthGuard(adminOnly(http.HandlerFunc(adminHandlers.UpdateEmailTemplate))))
	mux.Handle("DELETE /api/v1/admin/email-templates/{slug}", authMiddleware.HeaderAuthGuard(adminOnly(http.HandlerFunc(adminHandlers.DeleteEmailTemplate))))
	mux.Handle("GET /api/v1/admin/email-settings", authMiddleware.HeaderAuthGuard(adminOnly(http.HandlerFunc(adminHandlers.GetEmailSettings))))
	mux.Handle("PUT /api/v1/admin/email-settings", authMiddleware.HeaderAuthGuard(adminOnly(http.HandlerFunc(adminHandlers.UpdateEmailSettings))))

	// Chat Routes
	mux.Handle("GET /api/v1/conversations", authMiddleware.HeaderAuthGuard(http.HandlerFunc(chatHandlers.ListConversations)))
	mux.Handle("GET /api/v1/conversations/{id}/messages", authMiddleware.HeaderAuthGuard(http.HandlerFunc(chatHandlers.ListMessages)))
	mux.Handle("POST /api/v1/conversations/{id}/messages", authMiddleware.HeaderAuthGuard(http.HandlerFunc(chatHandlers.SendMessage)))

	// Application Routes
	mux.Handle("POST /api/v1/applications", authMiddleware.OptionalHeaderAuthGuard(http.HandlerFunc(applicationHandler.CreateApplication)))
	mux.Handle("GET /api/v1/applications/me", authMiddleware.HeaderAuthGuard(http.HandlerFunc(applicationHandler.GetMyApplications)))
	mux.HandleFunc("GET /api/v1/applications", applicationHandler.GetApplications)
	mux.HandleFunc("GET /api/v1/applications/{id}", applicationHandler.GetApplicationByID)
	mux.HandleFunc("PUT /api/v1/applications/{id}/status", applicationHandler.UpdateApplicationStatus)
	mux.HandleFunc("DELETE /api/v1/applications/{id}", applicationHandler.DeleteApplication)

	// Payment Routes
	mux.Handle("POST /api/v1/payments/create-checkout", authMiddleware.HeaderAuthGuard(http.HandlerFunc(paymentHandler.CreateCheckout)))
	mux.HandleFunc("POST /api/v1/payments/webhook", paymentHandler.HandleWebhook)
	mux.HandleFunc("GET /api/v1/payments/status/{id}", paymentHandler.GetPaymentStatus)

	// --- STORAGE ROUTES (Legacy Removed) ---

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

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

	return handler
}
