package routes

import (
	"lost-and-found/internal/controllers"
	"lost-and-found/internal/middleware"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"gorm.io/gorm"
)

// SetupRoutes configures all application routes
func SetupRoutes(router *gin.Engine, db *gorm.DB, logger *zap.Logger) {
	// Initialize controllers
	authController := controllers.NewAuthController(db, logger)
	userController := controllers.NewUserController(db)
	itemController := controllers.NewItemController(db)
	lostItemController := controllers.NewLostItemController(db)
	claimController := controllers.NewClaimController(db)
	matchController := controllers.NewMatchController(db)
	categoryController := controllers.NewCategoryController(db)
	archiveController := controllers.NewArchiveController(db)
	adminController := controllers.NewAdminController(db)
	reportController := controllers.NewReportController(db)
	uploadController := controllers.NewUploadController(db)
	managerController := controllers.NewManagerController(db)
	roleController := controllers.NewRoleController(db)
	notificationController := controllers.NewNotificationController(db)
	aiController := controllers.NewAIController(db)

	// API group
	api := router.Group("/api")
	{
		// ==========================================
		// 1. Public Routes (No Auth)
		// ==========================================
		api.POST("/register", authController.Register)
		api.POST("/login", authController.Login)
		api.POST("/refresh-token", authController.RefreshToken)

		api.GET("/categories", categoryController.GetAllCategories)
		api.GET("/categories/:id", categoryController.GetCategoryByID)

		// Optional Auth for Items (Public can view, Manager sees details)
		itemsGroup := api.Group("/items")
		itemsGroup.Use(middleware.OptionalJWTMiddleware(db))
		{
			itemsGroup.GET("", itemController.GetAllItems)
			itemsGroup.GET("/:id", itemController.GetItemByID)
		}

		// ==========================================
		// 2. Authenticated Routes (Basic User Access)
		// ==========================================
		// Middleware: Cek Token Valid & User Active
		authenticated := api.Group("")
		authenticated.Use(middleware.JWTMiddleware(db))
		{

			authenticated.POST("/ai/chat", aiController.Chat)
    authenticated.GET("/ai/history", aiController.GetHistory)
    authenticated.DELETE("/ai/history", aiController.ClearHistory)
			// Profile (Siapapun yang login bisa akses ini)
			authenticated.GET("/me", authController.GetMe)
			authenticated.GET("/user/profile", userController.GetProfile)
			authenticated.PUT("/user/profile", userController.UpdateProfile)
			authenticated.POST("/user/change-password", userController.ChangePassword)
			authenticated.GET("/user/stats", userController.GetStats)
			
			authenticated.POST("/lost-items/:id/direct-claim", lostItemController.DirectClaimToOwner)
			authenticated.POST("/user/lost-items/:id/direct-claim", lostItemController.DirectClaimToOwner)
			authenticated.POST("/claims/:id/respond", claimController.UserApproveClaim)
			authenticated.POST("/claims/:id/complete", claimController.UserConfirmCompletion)

			// --- User Features (Permission: item:create) ---
			authenticated.POST("/items",
				middleware.RequirePermission("item:create"),
				itemController.CreateItem)

			authenticated.GET("/user/items",
				middleware.RequirePermission("item:read"),
				itemController.GetItemsByReporter)

			// --- Lost Items (Permission: item:create) ---
			// Asumsi: Hak akses lapor kehilangan sama dengan lapor temuan
			authenticated.POST("/lost-items",
				middleware.RequirePermission("item:create"),
				lostItemController.CreateLostItem)

			authenticated.GET("/user/lost-items", lostItemController.GetLostItemsByUser)
			authenticated.GET("/lost-items", lostItemController.GetAllLostItems)
			authenticated.GET("/lost-items/:id", lostItemController.GetLostItemByID)
			authenticated.PUT("/lost-items/:id", lostItemController.UpdateLostItem)
			authenticated.PATCH("/lost-items/:id/status", lostItemController.UpdateLostItemStatus)
			
			// ✅ FIX: Delete Lost Item menggunakan controller yang benar
			authenticated.DELETE("/lost-items/:id", 
				middleware.RequirePermission("lost_item:delete"), // Permission baru
				lostItemController.DeleteLostItem)

			// --- Claims (Permission: claim:create) ---
			authenticated.POST("/claims",
				middleware.RequirePermission("claim:create"),
				middleware.IdempotencyMiddleware(), // Prevent double submit
				claimController.CreateClaim)

			authenticated.GET("/user/claims",
				middleware.RequirePermission("claim:read"),
				claimController.GetClaimsByUser)
			
			// ✅ FIX: Tambahkan endpoint update dan delete claim user
			authenticated.PUT("/claims/:id", 
				middleware.RequirePermission("claim:create"), // User boleh edit claim sendiri
				claimController.UpdateClaim)
				
			authenticated.DELETE("/claims/:id", 
				middleware.RequirePermission("claim:create"), // User boleh delete claim sendiri
				claimController.DeleteClaim)


			// --- Matching ---
			authenticated.GET("/lost-items/:id/matches", matchController.GetMatchesForLostItem)
			authenticated.POST("/lost-items/:id/find-similar", matchController.FindSimilarItems)
			// --- Notifications ---
			authenticated.GET("/notifications", notificationController.GetUserNotifications)
            authenticated.PATCH("/notifications/:id/read", notificationController.MarkAsRead)
            authenticated.PATCH("/notifications/read-all", notificationController.MarkAllAsRead)

						authenticated.POST("/user/claims/:id/respond", claimController.UserApproveClaim)
						authenticated.POST("/user/claims/:id/complete", claimController.UserConfirmCompletion)

			// --- Uploads ---
			upload := authenticated.Group("/upload")
			{
				upload.POST("/item-image", uploadController.UploadItemImage)
				upload.POST("/claim-proof", uploadController.UploadClaimProof)
				upload.POST("/multiple", uploadController.UploadMultipleImages)
				upload.DELETE("/delete", uploadController.DeleteImage)
				upload.GET("/info", uploadController.GetImageInfo)
			}
		}

		// ==========================================
		// 3. Protected Management Routes (Permission Based)
		// ==========================================
		// Area ini menggantikan Group Manager/Admin yang lama.
		// Sekarang dikelompokkan berdasarkan FITUR, bukan ROLE.
		management := api.Group("")
		management.Use(middleware.JWTMiddleware(db))
		{
			// --- ITEM MANAGEMENT (Permission: item:update, item:delete) ---
			management.PUT("/items/:id",
				middleware.RequirePermission("item:update"),
				itemController.UpdateItem)

			management.PATCH("/items/:id/status",
				middleware.RequirePermission("item:update"),
				itemController.UpdateItemStatus)

			management.DELETE("/items/:id",
				middleware.RequirePermission("item:delete"),
				itemController.DeleteItem)

			management.GET("/items/:id/revisions",
				middleware.RequirePermission("item:verify"),
				itemController.GetItemRevisionHistory)

			management.GET("/items/:id/matches",
				middleware.RequirePermission("item:verify"),
				matchController.GetMatchesForItem)

			// --- CLAIM VERIFICATION (Permission: claim:approve, claim:reject) ---
			management.GET("/claims",
				middleware.RequirePermission("claim:read"), // Manager view all claims
				claimController.GetAllClaims)

			management.GET("/claims/:id",
				middleware.RequirePermission("claim:read"),
				claimController.GetClaimByID)

			management.POST("/claims/:id/verify",
				middleware.RequirePermission("claim:approve"),
				middleware.IdempotencyMiddleware(),
				claimController.VerifyClaim)

			management.GET("/claims/:id/verification",
				middleware.RequirePermission("claim:read"),
				claimController.GetClaimVerification)

			// ✅ FIX: Ganti endpoint CloseClaim -> CloseCase
			management.POST("/claims/:id/close",
				middleware.RequirePermission("claim:approve"),
				claimController.CloseCase)

			// ✅ FIX: Ganti endpoint ReopenClaim -> ReopenCase
			management.POST("/claims/:id/reopen",
				middleware.RequirePermission("claim:approve"),
				claimController.ReopenCase)

			// ✅ FIX: Ganti endpoint CancelApproval -> CancelClaimApproval
			management.POST("/claims/:id/cancel-approval",
				middleware.RequirePermission("claim:approve"),
				claimController.CancelClaimApproval)

			// --- ARCHIVES (Permission: item:read - for historical data) ---
			management.GET("/archives",
				middleware.RequirePermission("item:read"),
				archiveController.GetAllArchives)

			management.GET("/archives/:id",
				middleware.RequirePermission("item:read"),
				archiveController.GetArchiveByID)

			management.GET("/archives/stats",
				middleware.RequirePermission("item:read"),
				archiveController.GetArchiveStats)

			// --- REPORTS (Permission: report:export) ---
			management.POST("/reports/export",
				middleware.RequirePermission("report:export"),
				reportController.ExportReport)

			// --- DASHBOARD (Permission: user:read - as proxy for dashboard access) ---
			management.GET("/manager/dashboard",
				middleware.RequirePermission("item:verify"),
				managerController.GetDashboardStats)

			management.GET("/admin/dashboard",
				middleware.RequirePermission("user:read"),
				adminController.GetDashboardStats)

			// --- USER MANAGEMENT (Permission: user:read, user:update, user:block) ---
			// Biasa dilakukan oleh Admin
			management.GET("/admin/users",
				middleware.RequirePermission("user:read"),
				userController.GetAllUsers)

			management.GET("/admin/users/:id",
				middleware.RequirePermission("user:read"),
				userController.GetUserByID)

			management.PATCH("/admin/users/:id/role",
				middleware.RequirePermission("user:update"),
				userController.UpdateUserRole)

			management.POST("/admin/users/:id/block",
				middleware.RequirePermission("user:block"),
				userController.BlockUser)

			management.POST("/admin/users/:id/unblock",
				middleware.RequirePermission("user:block"),
				userController.UnblockUser)

			management.DELETE("/admin/users/:id",
				middleware.RequirePermission("user:block"), // Menggunakan permission block untuk delete
				userController.DeleteUser)

			// --- AUDIT LOGS (Permission: user:read - biasanya Admin) ---
			management.GET("/admin/audit-logs",
				middleware.RequirePermission("user:read"),
				adminController.GetAuditLogs)

			// --- CATEGORY MANAGEMENT (Permission: item:update - Admin Only usually) ---
			// Note: Anda mungkin perlu menambahkan permission 'category:create' di seed.sql
			// Untuk sekarang kita gunakan 'item:update' atau 'user:update' sebagai proxy
			management.POST("/categories",
				middleware.RequirePermission("user:update"),
				categoryController.CreateCategory)

			management.PUT("/categories/:id",
				middleware.RequirePermission("user:update"),
				categoryController.UpdateCategory)

			management.DELETE("/categories/:id",
				middleware.RequirePermission("user:update"),
				categoryController.DeleteCategory)

			// ✅ Endpoint baru untuk test Procedure SQL
			management.POST("/admin/archive/trigger",
				middleware.RequireRole("admin"), // Hanya admin
				adminController.TriggerAutoArchive)

			management.GET("/admin/dashboard/fast",
				middleware.RequireRole("admin", "manager"),
				adminController.GetFastDashboardStats)

			management.GET("/admin/roles", middleware.RequireRole("admin"), roleController.GetRoles)
			management.GET("/admin/permissions", middleware.RequireRole("admin"), roleController.GetPermissions)
			management.POST("/admin/roles", middleware.RequireRole("admin"), roleController.CreateRole)
			management.PUT("/admin/roles/:id", middleware.RequireRole("admin"), roleController.UpdateRole)
			management.DELETE("/admin/roles/:id", middleware.RequireRole("admin"), roleController.DeleteRole)
		}
	}
}
