package httpserver

import (
	"Yimaru-Backend/internal/domain"
	"Yimaru-Backend/internal/web_server/handlers"
	"context"
	"fmt"
	"strconv"

	"github.com/gofiber/fiber/v2"
	fiberSwagger "github.com/swaggo/fiber-swagger"
)

func (a *App) initAppRoutes() {
	h := handlers.New(
		a.assessmentSvc,
		a.courseSvc,
		a.questionsSvc,
		a.subscriptionsSvc,
		a.arifpaySvc,
		a.logger,
		a.settingSvc,
		a.NotidicationStore,
		a.validator,
		a.recommendationSvc,
		a.userSvc,
		a.transactionSvc,
		a.authSvc,
		a.vimeoSvc,
		a.teamSvc,
		a.activityLogSvc,
		a.issueReportingSvc,
		a.JwtConfig,
		a.cfg,
		a.mongoLoggerSvc,
		a.analyticsDB,
	)

	a.fiber.Get("/", func(c *fiber.Ctx) error {
		return c.JSON(fiber.Map{
			"message": "Welcome to Yimaru Backend API",
			"version": a.cfg.APP_VERSION,
		})
	})

	a.fiber.Get("/routes", func(c *fiber.Ctx) error {
		return c.JSON(a.fiber.Stack()) // prints all registered routes
	})

	// Groups
	groupV1 := a.fiber.Group("/api/v1")
	// tenant := groupV1.Group("/tenant/:tenant_slug", a.TenantMiddleware)
	// groupV1.Get("/test", a.authMiddleware, a.authMiddleware, func(c *fiber.Ctx) error {
	// 	fmt.Printf("\nTest Route %v\n", c.Route().Path)
	// 	companyID := c.Locals("company_id").(domain.ValidInt64)
	// 	if !companyID.Valid {
	// 		h.BadRequestLogger().Error("invalid company id")
	// 		return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
	// 	}

	// 	fmt.Printf("In the tenant auth test \n")
	// 	return c.JSON(fiber.Map{
	// 		"message": "Is is fine",
	// 	})
	// })
	// groupV1.Get("/", func(c *fiber.Ctx) error {
	// 	fmt.Printf("\nTenant Route %v\n", c.Route().Path)
	// 	companyID := c.Locals("company_id").(domain.ValidInt64)
	// 	if !companyID.Valid {
	// 		h.BadRequestLogger().Error("invalid company id")
	// 		return fiber.NewError(fiber.StatusBadRequest, "invalid company id")
	// 	}
	// 	return c.JSON(fiber.Map{
	// 		"message": "Company Tenant Active",
	// 	})
	// })

	// Serve static files (profile pictures, etc.)
	a.fiber.Static("/static", "./static")

	// Get S
	groupV1.Get("/tenant", a.authMiddleware, h.GetTenantSlugByToken)

	// Swagger
	a.fiber.Get("/swagger/*", fiberSwagger.FiberWrapHandler())

	groupV1.Get("/", func(c *fiber.Ctx) error {
		return c.JSON(fiber.Map{
			"message": "Welcome to Yimaru Backend API v1",
			"version": "1.0.1",
		})
	})

	// Assessment questions
	groupV1.Post("/assessment/questions", h.CreateAssessmentQuestion)
	groupV1.Get("/assessment/questions", h.ListAssessmentQuestions)
	groupV1.Get("/assessment/questions/:id", h.GetAssessmentQuestionByID)
	// groupV1.Put("/assessment/questions/:id", h.UpdateAssessmentQuestion)
	// groupV1.Delete("/assessment/questions/:id", h.DeleteAssessmentQuestion)

	// Start a new assessment attempt
	// groupV1.Post(
	// 	"/assessment/attempts",
	// 	h.StartAssessmentAttempt,
	// )

	// // Submit or update an answer
	// groupV1.Post(
	// 	"/assessment/attempts/:attempt_id/answers",
	// 	h.SubmitAssessmentAnswer,
	// )

	// // Final submission (locks answers)
	// groupV1.Post(
	// 	"/assessment/attempts/:attempt_id/submit",
	// 	h.SubmitAssessmentAttempt,
	// )

	// // Get attempt details
	// groupV1.Get(
	// 	"/assessment/attempts/:attempt_id",
	// 	h.GetAssessmentAttemptByID,
	// )

	// Get final result + answers
	// groupV1.Get(
	// 	"/assessment/attempts/:attempt_id/result",
	// 	h.GetAssessmentResult,
	// )

	// // Evaluate attempt (admin / system)
	// groupV1.Post(
	// 	"/assessment/attempts/:attempt_id/evaluate",
	// 	h.EvaluateAssessmentAttempt,
	// )

	// Course Management Routes

	// Course Categories
	groupV1.Post("/course-management/categories", a.authMiddleware, h.CreateCourseCategory)
	groupV1.Get("/course-management/categories", a.authMiddleware, h.GetAllCourseCategories)
	groupV1.Get("/course-management/categories/:id", a.authMiddleware, h.GetCourseCategoryByID)
	groupV1.Put("/course-management/categories/:id", a.authMiddleware, h.UpdateCourseCategory)
	groupV1.Delete("/course-management/categories/:id", a.authMiddleware, h.DeleteCourseCategory)

	// Courses
	groupV1.Post("/course-management/courses", a.authMiddleware, h.CreateCourse)
	groupV1.Get("/course-management/courses/:id", a.authMiddleware, h.GetCourseByID)
	groupV1.Get("/course-management/categories/:categoryId/courses", a.authMiddleware, h.GetCoursesByCategory)
	groupV1.Put("/course-management/courses/:id", a.authMiddleware, h.UpdateCourse)
	groupV1.Delete("/course-management/courses/:id", a.authMiddleware, h.DeleteCourse)

	// Sub-courses
	groupV1.Post("/course-management/sub-courses", a.authMiddleware, h.CreateSubCourse)
	groupV1.Get("/course-management/sub-courses/:id", a.authMiddleware, h.GetSubCourseByID)
	groupV1.Get("/course-management/courses/:courseId/sub-courses", a.authMiddleware, h.GetSubCoursesByCourse)
	groupV1.Get("/course-management/courses/:courseId/sub-courses/list", a.authMiddleware, h.ListSubCoursesByCourse)
	groupV1.Get("/course-management/sub-courses/active", a.authMiddleware, h.ListActiveSubCourses)
	groupV1.Patch("/course-management/sub-courses/:id", a.authMiddleware, h.UpdateSubCourse)
	groupV1.Put("/course-management/sub-courses/:id/deactivate", a.authMiddleware, h.DeactivateSubCourse)
	groupV1.Delete("/course-management/sub-courses/:id", a.authMiddleware, h.DeleteSubCourse)

	// Sub-course Videos
	groupV1.Post("/course-management/videos", a.authMiddleware, h.CreateSubCourseVideo)
	groupV1.Post("/course-management/videos/vimeo", a.authMiddleware, h.CreateSubCourseVideoWithVimeo)
	groupV1.Post("/course-management/videos/upload", a.authMiddleware, h.UploadSubCourseVideo)
	groupV1.Post("/course-management/videos/vimeo/import", a.authMiddleware, h.CreateSubCourseVideoFromVimeoID)
	groupV1.Get("/course-management/videos/:id", a.authMiddleware, h.GetSubCourseVideoByID)
	groupV1.Get("/course-management/sub-courses/:subCourseId/videos", a.authMiddleware, h.GetVideosBySubCourse)
	groupV1.Get("/course-management/sub-courses/:subCourseId/videos/published", a.authMiddleware, h.GetPublishedVideosBySubCourse)
	groupV1.Put("/course-management/videos/:id/publish", a.authMiddleware, h.PublishSubCourseVideo)
	groupV1.Put("/course-management/videos/:id", a.authMiddleware, h.UpdateSubCourseVideo)
	groupV1.Delete("/course-management/videos/:id", a.authMiddleware, h.DeleteSubCourseVideo)

	// Learning Tree
	groupV1.Get("/course-management/learning-tree", a.authMiddleware, h.GetFullLearningTree)

	// Unified Questions System
	// Questions
	groupV1.Post("/questions", a.authMiddleware, h.CreateQuestion)
	groupV1.Get("/questions", a.authMiddleware, h.ListQuestions)
	groupV1.Get("/questions/search", a.authMiddleware, h.SearchQuestions)
	groupV1.Get("/questions/:id", a.authMiddleware, h.GetQuestionByID)
	groupV1.Put("/questions/:id", a.authMiddleware, h.UpdateQuestion)
	groupV1.Delete("/questions/:id", a.authMiddleware, h.DeleteQuestion)

	// Question Sets (replaces Practices for question grouping)
	groupV1.Post("/question-sets", a.authMiddleware, h.CreateQuestionSet)
	groupV1.Get("/question-sets", a.authMiddleware, h.GetQuestionSetsByType)
	groupV1.Get("/question-sets/by-owner", a.authMiddleware, h.GetQuestionSetsByOwner)
	groupV1.Get("/question-sets/:id", a.authMiddleware, h.GetQuestionSetByID)
	groupV1.Put("/question-sets/:id", a.authMiddleware, h.UpdateQuestionSet)
	groupV1.Delete("/question-sets/:id", a.authMiddleware, h.DeleteQuestionSet)

	// Question Set Items (questions within sets)
	groupV1.Post("/question-sets/:setId/questions", a.authMiddleware, h.AddQuestionToSet)
	groupV1.Get("/question-sets/:setId/questions", a.authMiddleware, h.GetQuestionsInSet)
	groupV1.Delete("/question-sets/:setId/questions/:questionId", a.authMiddleware, h.RemoveQuestionFromSet)
	groupV1.Put("/question-sets/:setId/questions/:questionId/order", a.authMiddleware, h.UpdateQuestionOrderInSet)

	// Question Set User Personas (users as personas within practices)
	groupV1.Get("/question-sets/:setId/personas", a.authMiddleware, h.GetUserPersonasByQuestionSet)
	groupV1.Post("/question-sets/:setId/personas", a.authMiddleware, h.AddUserPersonaToQuestionSet)
	groupV1.Delete("/question-sets/:setId/personas/:userId", a.authMiddleware, h.RemoveUserPersonaFromQuestionSet)

	// Subscription Plans (admin)
	groupV1.Post("/subscription-plans", a.authMiddleware, h.CreateSubscriptionPlan)
	groupV1.Get("/subscription-plans", h.ListSubscriptionPlans)
	groupV1.Get("/subscription-plans/:id", h.GetSubscriptionPlan)
	groupV1.Put("/subscription-plans/:id", a.authMiddleware, h.UpdateSubscriptionPlan)
	groupV1.Delete("/subscription-plans/:id", a.authMiddleware, h.DeleteSubscriptionPlan)

	// User Subscriptions
	groupV1.Post("/subscriptions", a.authMiddleware, h.Subscribe)                     // Admin only - creates subscription without payment
	groupV1.Post("/subscriptions/checkout", a.authMiddleware, h.SubscribeWithPayment) // User - initiates payment for subscription
	groupV1.Get("/subscriptions/me", a.authMiddleware, h.GetMySubscription)
	groupV1.Get("/subscriptions/history", a.authMiddleware, h.GetMySubscriptionHistory)
	groupV1.Get("/subscriptions/status", a.authMiddleware, h.CheckSubscriptionStatus)
	groupV1.Post("/subscriptions/:id/cancel", a.authMiddleware, h.CancelSubscription)
	groupV1.Put("/subscriptions/:id/auto-renew", a.authMiddleware, h.SetAutoRenew)

	// Payments (ArifPay Integration)
	groupV1.Post("/payments/subscribe", a.authMiddleware, h.InitiateSubscriptionPayment)
	groupV1.Get("/payments/verify/:session_id", a.authMiddleware, h.VerifyPayment)
	groupV1.Get("/payments", a.authMiddleware, h.GetMyPayments)
	groupV1.Get("/payments/:id", a.authMiddleware, h.GetPaymentByID)
	groupV1.Post("/payments/:id/cancel", a.authMiddleware, h.CancelPayment)
	groupV1.Get("/payments/methods", h.GetArifpayPaymentMethods)
	// Webhook endpoint (no auth - called by ArifPay)
	groupV1.Post("/payments/webhook", h.HandleArifpayWebhook)

	// Direct Payments (OTP-based - Telebirr, CBE, Amole, HelloCash, etc.)
	groupV1.Post("/payments/direct", a.authMiddleware, h.InitiateDirectPayment)
	groupV1.Post("/payments/direct/verify-otp", a.authMiddleware, h.VerifyDirectPaymentOTP)
	groupV1.Get("/payments/direct/methods", h.GetDirectPaymentMethods)

	// Auth Routes
	groupV1.Post("/auth/google/android", h.GoogleAndroidLogin)
	groupV1.Get("/auth/google/login", h.GoogleLogin)
	groupV1.Get("/auth/google/callback", h.GoogleCallback)
	groupV1.Post("/auth/customer-login", h.LoginUser)
	groupV1.Post("/auth/admin-login", h.LoginAdmin)
	groupV1.Post("/auth/super-login", h.LoginSuper)
	groupV1.Post("/auth/refresh", h.RefreshToken)
	// Upload profile picture
	groupV1.Post("/user/:id/profile-picture", a.authMiddleware, h.UploadProfilePicture)
	groupV1.Post("/auth/logout", a.authMiddleware, h.LogOutuser)
	groupV1.Get("/auth/test", a.authMiddleware, func(c *fiber.Ctx) error {
		userID, ok := c.Locals("user_id").(int64)
		if !ok {
			return fiber.NewError(fiber.StatusUnauthorized, "Invalid user ID")
		}
		role, ok := c.Locals("role").(domain.Role)
		if !ok {
			return fiber.NewError(fiber.StatusUnauthorized, "Invalid role")
		}
		refreshToken, ok := c.Locals("refresh_token").(string)
		if !ok {
			return fiber.NewError(fiber.StatusUnauthorized, "Invalid refresh token")
		}
		companyID, err := strconv.ParseInt(c.Get("company_id"), 10, 64)
		if err != nil {
			return fiber.NewError(fiber.StatusBadRequest, "Invalid company_id")
		}

		a.logger.Info("User ID: " + strconv.FormatInt(userID, 10))
		fmt.Printf("User ID: %d\n", userID)
		a.logger.Info("Role: " + string(role))
		a.logger.Info("Refresh Token: " + refreshToken)
		a.logger.Info("Company ID: " + strconv.FormatInt(companyID, 10))
		return c.SendString("Test endpoint")
	})

	//Arifpay
	// groupV1.Post("/arifpay/checkout", a.authMiddleware, h.CreateCheckoutSessionHandler)
	// groupV1.Post("/arifpay/checkout/cancel/:sessionId", a.authMiddleware, h.CancelCheckoutSessionHandler)
	// groupV1.Post("/api/v1/arifpay/c2b-webhook", h.HandleArifpayC2BWebhook)
	// groupV1.Post("/api/v1/arifpay/b2c-webhook", h.HandleArifpayB2CWebhook)
	// groupV1.Post("/arifpay/b2c/transfer", a.authMiddleware, h.ExecuteArifpayB2CTransfer)
	// groupV1.Post("/arifpay/transaction-id/verify-transaction", a.authMiddleware, h.ArifpayVerifyByTransactionIDHandler)
	// groupV1.Get("/arifpay/session-id/verify-transaction/:session_id", a.authMiddleware, h.ArifpayVerifyBySessionIDHandler)
	// groupV1.Get("/arifpay/payment-methods", a.authMiddleware, h.GetArifpayPaymentMethodsHandler

	// User Routes
	groupV1.Get("/user/:user_id/is-profile-completed", a.authMiddleware, h.CheckProfileCompleted)
	groupV1.Get("/users", a.authMiddleware, h.GetAllUsers)
	groupV1.Put("/user", a.authMiddleware, h.UpdateUser)
	groupV1.Put("/user/knowledge-level", h.UpdateUserKnowledgeLevel)
	// groupV1.Get("/user/:user_name/is-unique", h.CheckUserNameUnique)
	groupV1.Get("/user/:user_name/is-pending", h.CheckUserPending)
	groupV1.Post("/user/resetPassword", h.ResetPassword)
	groupV1.Post("/user/sendResetCode", h.SendResetCode)
	groupV1.Post("/user/verify-otp", h.VerifyOtp)
	groupV1.Post("/user/resend-otp", h.ResendOtp)
	groupV1.Post("/user/register", h.RegisterUser)
	groupV1.Post("/user/sendRegisterCode", h.SendRegisterCode)
	groupV1.Post("/user/checkPhoneEmailExist", h.CheckPhoneEmailExist)

	groupV1.Get("/user/admin-profile", a.authMiddleware, h.AdminProfile)

	groupV1.Get("/user/user-profile", a.authMiddleware, h.GetUserProfile)

	groupV1.Get("/user/single/:id", a.authMiddleware, h.GetUserByID)
	groupV1.Delete("/user/delete/:id", a.authMiddleware, h.DeleteUser)
	groupV1.Post("/user/search", a.authMiddleware, h.SearchUserByNameOrPhone)

	groupV1.Get("/admin", a.authMiddleware, a.SuperAdminOnly, h.GetAllAdmins)
	groupV1.Get("/admin/:id", a.authMiddleware, a.SuperAdminOnly, h.GetAdminByID)
	groupV1.Post("/admin", a.authMiddleware, a.SuperAdminOnly, h.CreateAdmin)
	groupV1.Put("/admin/:id", a.authMiddleware, a.SuperAdminOnly, h.UpdateAdmin)

	// groupV1.Get("/t-approver", a.authMiddleware, a.OnlyAdminAndAbove, h.GetAllTransactionApprovers)
	// groupV1.Get("/t-approver/:id", a.authMiddleware, a.OnlyAdminAndAbove, h.GetTransactionApproverByID)
	// groupV1.Post("/t-approver", a.authMiddleware, a.OnlyAdminAndAbove, h.CreateTransactionApprover)
	// groupV1.Put("/t-approver/:id", a.authMiddleware, a.OnlyAdminAndAbove, h.UpdateTransactionApprover)

	//mongoDB logs
	groupV1.Get("/logs", a.authMiddleware, a.OnlyAdminAndAbove, handlers.GetLogsHandler(context.Background()))

	// Activity Logs
	groupV1.Get("/activity-logs", a.authMiddleware, a.OnlyAdminAndAbove, h.GetActivityLogs)
	groupV1.Get("/activity-logs/:id", a.authMiddleware, a.OnlyAdminAndAbove, h.GetActivityLogByID)

	// groupV1.Get("/shop/transaction", a.authMiddleware, a.CompanyOnly, h.GetAllTransactions)
	// groupV1.Get("/shop/transaction/:id", a.authMiddleware, a.CompanyOnly, h.GetTransactionByID)
	// groupV1.Get("/shop/transaction/:id/bet", a.authMiddleware, a.CompanyOnly, h.GetShopBetByTransactionID)
	// groupV1.Put("/shop/transaction/:id", a.authMiddleware, a.CompanyOnly, h.UpdateTransactionVerified)

	// Notification Routes
	groupV1.Post("/sendSMS", h.SendSingleAfroSMS)
	groupV1.Get("/ws/connect", a.WebsocketAuthMiddleware, h.ConnectSocket)
	groupV1.Get("/notifications", a.authMiddleware, h.GetUserNotification)
	groupV1.Get("/notifications/all", a.authMiddleware, h.GetAllNotifications)
	groupV1.Patch("/notifications/:id/read", a.authMiddleware, h.MarkNotificationAsRead)
	groupV1.Post("/notifications/mark-all-read", a.authMiddleware, h.MarkAllNotificationsAsRead)
	groupV1.Patch("/notifications/:id/unread", a.authMiddleware, h.MarkNotificationAsUnread)
	groupV1.Post("/notifications/mark-all-unread", a.authMiddleware, h.MarkAllNotificationsAsUnread)
	groupV1.Delete("/notifications", a.authMiddleware, h.DeleteUserNotifications)
	groupV1.Get("/notifications/unread", a.authMiddleware, h.CountUnreadNotifications)
	groupV1.Post("/notifications/create", a.authMiddleware, h.CreateAndSendNotification)

	// Issue Reporting Routes
	groupV1.Post("/issues", a.authMiddleware, h.CreateIssue)
	groupV1.Get("/issues/me", a.authMiddleware, h.GetMyIssues)
	groupV1.Get("/issues/user/:user_id", a.authMiddleware, a.OnlyAdminAndAbove, h.GetUserIssues)
	groupV1.Get("/issues", a.authMiddleware, a.OnlyAdminAndAbove, h.GetAllIssues)
	groupV1.Get("/issues/:id", a.authMiddleware, a.OnlyAdminAndAbove, h.GetIssueByID)
	groupV1.Patch("/issues/:id/status", a.authMiddleware, a.OnlyAdminAndAbove, h.UpdateIssueStatus)
	groupV1.Delete("/issues/:id", a.authMiddleware, a.OnlyAdminAndAbove, h.DeleteIssue)

	// Device Token Registration
	groupV1.Post("/devices/register", a.authMiddleware, h.RegisterDeviceToken)
	groupV1.Post("/devices/unregister", a.authMiddleware, h.UnregisterDeviceToken)

	// Test Push Notification (for development/testing)
	groupV1.Post("/notifications/test-push", a.authMiddleware, h.SendTestPushNotification)

	// Settings
	groupV1.Get("/settings", a.authMiddleware, a.SuperAdminOnly, h.GetGlobalSettingList)
	groupV1.Get("/settings/:key", a.authMiddleware, a.SuperAdminOnly, h.GetGlobalSettingByKey)
	groupV1.Put("/settings", a.authMiddleware, a.SuperAdminOnly, h.UpdateGlobalSettingList)

	// Analytics Routes
	groupV1.Get("/analytics/dashboard", a.authMiddleware, a.OnlyAdminAndAbove, h.GetAnalyticsDashboard)

	// Vimeo Video Hosting Routes
	vimeoGroup := groupV1.Group("/vimeo")
	vimeoGroup.Get("/videos/:video_id", a.authMiddleware, h.GetVimeoVideo)
	vimeoGroup.Get("/videos/:video_id/embed", a.authMiddleware, h.GetEmbedCode)
	vimeoGroup.Get("/videos/:video_id/status", a.authMiddleware, h.GetTranscodeStatus)
	vimeoGroup.Delete("/videos/:video_id", a.authMiddleware, h.DeleteVimeoVideo)
	vimeoGroup.Post("/uploads/pull", a.authMiddleware, h.CreatePullUpload)
	vimeoGroup.Post("/uploads/tus", a.authMiddleware, h.CreateTusUpload)
	vimeoGroup.Get("/oembed", h.GetOEmbed)

	// Team Management Routes (Internal HR/Team)
	teamGroup := groupV1.Group("/team")
	teamGroup.Post("/login", h.TeamMemberLogin)                                                             // Team member authentication
	teamGroup.Get("/me", a.authMiddleware, h.GetMyTeamProfile)                                              // Get own profile
	teamGroup.Get("/stats", a.authMiddleware, a.OnlyAdminAndAbove, h.GetTeamMemberStats)                    // Team statistics
	teamGroup.Get("/members", a.authMiddleware, a.OnlyAdminAndAbove, h.GetAllTeamMembers)                   // List all team members
	teamGroup.Post("/members", a.authMiddleware, a.OnlyAdminAndAbove, h.CreateTeamMember)                   // Create team member
	teamGroup.Get("/members/:id", a.authMiddleware, h.GetTeamMember)                                        // Get team member by ID
	teamGroup.Put("/members/:id", a.authMiddleware, a.OnlyAdminAndAbove, h.UpdateTeamMember)                // Update team member
	teamGroup.Patch("/members/:id/status", a.authMiddleware, a.OnlyAdminAndAbove, h.UpdateTeamMemberStatus) // Update status
	teamGroup.Delete("/members/:id", a.authMiddleware, a.SuperAdminOnly, h.DeleteTeamMember)                // Delete team member
	teamGroup.Post("/members/:id/change-password", a.authMiddleware, h.ChangeTeamMemberPassword)            // Change password

}
