package router

import (
	"bytes"
	"context"
	"log"
	"net/http"
	"time"

	"bookhoard/internal/config"
	"bookhoard/internal/database"
	"bookhoard/internal/handlers"
	"bookhoard/internal/services"
	"bookhoard/internal/utils"
	"bookhoard/templates"

	"github.com/golang-jwt/jwt/v5"
	"github.com/jackc/pgx/v5/pgtype"
	"github.com/labstack/echo/v5"

	"github.com/google/uuid"
)

func renderErrorPage(c *echo.Context, message string, errorType string) error {
	var buf bytes.Buffer
	err := templates.ErrorPage(message, errorType).Render(c.Request().Context(), &buf)
	if err != nil {
		log.Printf("renderErrorPage failed to render template: %v", err)
		return c.HTML(http.StatusInternalServerError, "Internal server error")
	}
	return c.HTML(http.StatusInternalServerError, buf.String())
}

func registerFrontendRoutes(cfg *Config) {
	e := cfg.Echo

	// ============================================================================
	// FRONTEND ROUTES - DO NOT DELETE
	// These routes serve Server-Side Rendered (SSR) HTML pages for the web UI.
	// They are NOT API endpoints and should NOT be removed during refactors.
	// All authenticated frontend routes use the jwtMiddleware to validate tokens.
	// ============================================================================

	// Use existing JWT middleware (sets database user object in context)
	jwtMiddleware := createJWTMiddleware(cfg)

	// Protected route group for API routes
	protected := e.Group("/api", jwtMiddleware)

	// ============================================================================
	// PUBLIC FRONTEND ROUTES (No authentication required)
	// ============================================================================

	// Public routes for login and registration pages
	e.GET("/login", func(c *echo.Context) error {
		var buf bytes.Buffer
		sessionExpired := c.QueryParam("session") == "expired"
		deleted := c.QueryParam("deleted") == "true"
		err := templates.Login(sessionExpired, deleted).Render(c.Request().Context(), &buf)
		if err != nil {
			return err
		}
		return c.HTML(http.StatusOK, buf.String())
	})

	e.GET("/register", func(c *echo.Context) error {
		var buf bytes.Buffer
		err := templates.Register().Render(c.Request().Context(), &buf)
		if err != nil {
			return err
		}
		return c.HTML(http.StatusOK, buf.String())
	})

	// Root route - landing page with smart login detection
	e.GET("/", func(c *echo.Context) error {
		var buf bytes.Buffer
		var err error

		tokenString := c.Request().Header.Get("Authorization")
		if tokenString != "" && len(tokenString) > 7 && tokenString[:7] == "Bearer " {
			tokenString = tokenString[7:]
		} else {
			cookie, err := c.Cookie("token")
			if err == nil {
				tokenString = cookie.Value
			}
		}

		loggedIn := false
		if tokenString != "" {
			token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
				return []byte(cfg.Cfg.JWTSecret), nil
			})
			loggedIn = err == nil && token.Valid
		}

		err = templates.Index(loggedIn).Render(c.Request().Context(), &buf)
		if err != nil {
			return err
		}
		return c.HTML(http.StatusOK, buf.String())
	})

	// ============================================================================
	// PROTECTED FRONTEND ROUTES (Authentication required)
	// ============================================================================

	// Protected frontend routes (no /api prefix)
	frontendProtected := e.Group("", jwtMiddleware, ensureUserExistsMiddleware(cfg))

	// Helper to extract text from pgtype.Text
	getText := func(t pgtype.Text) string {
		if t.Valid {
			return t.String
		}
		return ""
	}

	// Dashboard page
	frontendProtected.GET("/dashboard", func(c *echo.Context) error {
		user, err := getTemplateUserWithTheme(c, cfg)
		if err != nil {
			return renderErrorPage(c, "Error loading user", "user_load_error")
		}

		var errorMsg string

		libraryID := c.QueryParam("library_id")
		if libraryID == "" {
			userUUID, _ := uuid.Parse(user.ID)
			libraries, err := cfg.Queries.GetUserVisibleLibraries(c.Request().Context(), uuidToPGType(userUUID))
			if err == nil && len(libraries) > 0 {
				libUUID, _ := uuid.FromBytes(libraries[0].ID.Bytes[0:16])
				libraryID = libUUID.String()
			}
		}

		libUUID, _ := uuid.Parse(libraryID)
		userUUID, _ := uuid.Parse(user.ID)

		prefs, err := cfg.DashboardService.GetDashboardPreferences(c.Request().Context(), userUUID, libUUID)
		if err != nil {
			log.Printf("GetDashboardPreferences failed: %v", err)
			prefs = database.UserDashboardPreferences{
				HiddenCollections: []string{},
				CollectionOrder:   []string{},
				ItemsPerSection:   pgtype.Int4{Int32: 20, Valid: true},
			}
		}
		limit := 20
		if prefs.ItemsPerSection.Int32 > 0 {
			limit = int(prefs.ItemsPerSection.Int32)
		}

		// Get ALL sections (unfiltered) for the modal
		allSections, err := cfg.DashboardService.GetDashboardSections(
			c.Request().Context(),
			userUUID,
			libUUID,
			limit,
			prefs.CollectionOrder,
			[]string{}, // No filtering - get all sections
		)
		if err != nil {
			log.Printf("Dashboard sections query failed: %v", err)
			allSections = []services.DashboardSection{}
			errorMsg = "Error loading dashboard"
		}

		// Get only visible sections for the dashboard display
		visibleSections := cfg.DashboardService.FilterHiddenCollections(allSections, prefs.HiddenCollections)

		userUUID2, _ := uuid.Parse(user.ID)
		libraries, err := cfg.Queries.GetUserVisibleLibraries(c.Request().Context(), uuidToPGType(userUUID2))
		if err != nil {
			log.Printf("GetUserVisibleLibraries failed: %v", err)
			libraries = []database.GetUserVisibleLibrariesRow{}
			if errorMsg == "" {
				errorMsg = "Error loading libraries"
			}
		}

		libData := make([]templates.LibraryData, len(libraries))
		for i, lib := range libraries {
			libUUID, _ := uuid.FromBytes(lib.ID.Bytes[0:16])
			libData[i] = templates.LibraryData{
				ID:          libUUID.String(),
				Name:        lib.Name,
				Description: getText(lib.Description),
				TypeName:    lib.TypeName,
			}
		}

		sectionData := handlers.BuildSections(visibleSections, libraryID)
		allSectionsData := handlers.BuildSections(allSections, libraryID)

		var buf bytes.Buffer
		err = templates.Dashboard(user, sectionData, allSectionsData, libData, libraryID, prefs.HiddenCollections, limit, errorMsg).Render(c.Request().Context(), &buf)
		if err != nil {
			return err
		}
		return c.HTML(http.StatusOK, buf.String())
	})

	// Collections page
	frontendProtected.GET("/collections", func(c *echo.Context) error {
		user, err := getTemplateUserWithTheme(c, cfg)
		if err != nil {
			return renderErrorPage(c, "Error loading user", "user_load_error")
		}

		var errorMsg string
		var collections []database.Collections

		collections, err = cfg.CollectionHandler.GetCollectionsData(c)
		if err != nil {
			log.Printf("GetCollectionsData failed: %v", err)
			collections = []database.Collections{}
			errorMsg = "Error loading collections"
		}

		colData := make([]templates.CollectionData, len(collections))
		for i, col := range collections {
			colData[i] = templates.CollectionData{
				ID:          uuid.UUID(col.ID.Bytes).String(),
				Name:        col.Name,
				Description: getText(col.Description),
				Color:       getText(col.Color),
				Icon:        getText(col.Icon),
			}
		}

		var buf bytes.Buffer
		err = templates.Collection(user, colData, errorMsg).Render(c.Request().Context(), &buf)
		if err != nil {
			return err
		}
		return c.HTML(http.StatusOK, buf.String())
	})

	// Collection create modal
	frontendProtected.GET("/collections/create-modal", func(c *echo.Context) error {
		var buf bytes.Buffer
		err := templates.CollectionModal(templates.CollectionData{}).Render(c.Request().Context(), &buf)
		if err != nil {
			return err
		}
		return c.HTML(http.StatusOK, buf.String())
	})

	// Collection edit modal
	frontendProtected.GET("/collections/:id/edit-modal", func(c *echo.Context) error {
		// Parse collection ID
		collectionID := c.Param("id")
		collUUID, err := uuid.Parse(collectionID)
		if err != nil {
			return c.HTML(http.StatusBadRequest, "<div>Invalid collection ID</div>")
		}

		// Fetch collection data
		collection, err := cfg.Queries.GetCollection(c.Request().Context(), pgtype.UUID{Bytes: collUUID, Valid: true})
		if err != nil {
			return c.HTML(http.StatusNotFound, "<div>Collection not found</div>")
		}

		// Convert to template type
		colData := templates.CollectionData{
			ID:          uuid.UUID(collection.ID.Bytes).String(),
			Name:        collection.Name,
			Description: getText(collection.Description),
			Color:       getText(collection.Color),
			Icon:        getText(collection.Icon),
		}

		// Ensure default color if empty
		if colData.Color == "" {
			colData.Color = "blue"
		}

		var buf bytes.Buffer
		err = templates.CollectionModal(colData).Render(c.Request().Context(), &buf)
		if err != nil {
			return err
		}
		return c.HTML(http.StatusOK, buf.String())
	})

	// Restore system collection modal
	frontendProtected.GET("/collections/restore-modal", func(c *echo.Context) error {
		var buf bytes.Buffer
		err := templates.RestoreSystemCollectionModal().Render(c.Request().Context(), &buf)
		if err != nil {
			return err
		}
		return c.HTML(http.StatusOK, buf.String())
	})

	// Collection detail page (works for both system and user collections)
	frontendProtected.GET("/collections/:id", func(c *echo.Context) error {
		user, err := getTemplateUserWithTheme(c, cfg)
		if err != nil {
			return renderErrorPage(c, "Error loading user", "user_load_error")
		}
		// Parse collection ID from URL
		collectionID := c.Param("id")
		collUUID, err := uuid.Parse(collectionID)
		if err != nil {
			return renderErrorPage(c, "Invalid collection ID", "invalid_id")
		}
		// Fetch collection details
		collection, err := cfg.Queries.GetCollection(c.Request().Context(), pgtype.UUID{Bytes: collUUID, Valid: true})
		if err != nil {
			if err.Error() == "no rows in result set" {
				return renderErrorPage(c, "Collection not found", "not_found")
			}
			return renderErrorPage(c, "Error loading collection", "collection_load_error")
		}
		// Fetch books in collection
		userUUID, _ := uuid.Parse(user.ID)
		var books []handlers.BookInfo

		if collection.QueryType.Valid && collection.QueryType.String != "" {
			// System collection - use query type
			// System collection - need library_id for system collections
			// Get library_id from query param or default to user's first library
			libraryID := c.QueryParam("library_id")
			if libraryID == "" {
				libraries, err := cfg.Queries.GetUserVisibleLibraries(c.Request().Context(), uuidToPGType(userUUID))
				if err == nil && len(libraries) > 0 {
					libUUID, _ := uuid.FromBytes(libraries[0].ID.Bytes[0:16])
					libraryID = libUUID.String()
				}
			}

			libUUID, _ := uuid.Parse(libraryID)
			dashboardSvc := services.NewDashboardService(cfg.Queries)
			sections, err := dashboardSvc.GetDashboardSections(c.Request().Context(), userUUID, libUUID, 1000, []string{}, []string{})
			if err != nil {
				return renderErrorPage(c, "Error loading books", "books_load_error")
			}

			// Find the matching section and convert items
			for _, section := range sections {
				if section.CollectionID.String() == collectionID {
					// Convert []database.MediaItems to []handlers.BookInfo
					bookCards := make([]handlers.BookInfo, len(section.Items))
					for i, item := range section.Items {
						itemUUID, _ := uuid.FromBytes(item.ID.Bytes[0:16])
						bookCards[i] = handlers.BookInfo{
							MediaItemID:    itemUUID.String(),
							Title:          item.Title,
							Author:         getText(item.Author),
							CoverImagePath: utils.ResolveMediaURL(item.LibraryID, item.CoverImagePath),
						}
					}
					books = bookCards
					break
				}
			}
		} else {
			// User collection - check if library_id filter is present
			libraryID := c.QueryParam("library_id")

			if libraryID != "" {
				// Filter by library - reuse dashboard query
				libUUID, err := uuid.Parse(libraryID)
				if err != nil {
					return renderErrorPage(c, "Invalid library ID", "invalid_library_id")
				}

				// Use GetCollectionItemsForDashboard for library-filtered results
				collItems, err := cfg.Queries.GetCollectionItemsForDashboard(c.Request().Context(),
					database.GetCollectionItemsForDashboardParams{
						CollectionID: pgtype.UUID{Bytes: collUUID, Valid: true},
						LibraryID:    pgtype.UUID{Bytes: libUUID, Valid: true},
						Limit:        1000,
					})
				if err != nil {
					books = []handlers.BookInfo{}
				} else {
					// Convert to BookInfo format (non-excluded only)
					var validItems []database.GetCollectionItemsForDashboardRow
					for _, item := range collItems {
						if !item.Excluded.Valid || !item.Excluded.Bool {
							validItems = append(validItems, item)
						}
					}

					bookCards := make([]handlers.BookInfo, len(validItems))
					for i, item := range validItems {
						itemUUID, _ := uuid.FromBytes(item.ID.Bytes[0:16])
						bookCards[i] = handlers.BookInfo{
							MediaItemID:    itemUUID.String(),
							Title:          item.Title,
							Author:         getText(item.Author),
							CoverImagePath: utils.ResolveMediaURL(item.LibraryID, item.CoverImagePath),
						}
					}
					books = bookCards
				}
			} else {
				// No library filter - show all books in collection
				collItems, err := cfg.Queries.GetCollectionItems(c.Request().Context(), pgtype.UUID{Bytes: collUUID, Valid: true})
				if err != nil {
					books = []handlers.BookInfo{}
				}

				// Convert to BookInfo format
				bookCards := make([]handlers.BookInfo, len(collItems))
				for i, item := range collItems {
					itemUUID, _ := uuid.FromBytes(item.MediaItemID.Bytes[0:16])
					bookCards[i] = handlers.BookInfo{
						MediaItemID:    itemUUID.String(),
						Title:          item.Title,
						Author:         getText(item.Author),
						CoverImagePath: utils.ResolveMediaURL(item.LibraryID, item.CoverImagePath),
					}
				}
				books = bookCards
			}
		}
		// Build collection data
		colData := templates.CollectionData{
			ID:          collectionID,
			Name:        collection.Name,
			Description: collection.Description.String,
			Color:       collection.Color.String,
			Icon:        collection.Icon.String,
		}

		// Get library_id from query params for template
		libraryID := c.QueryParam("library_id")
		// Render the CollectionDetail template
		var buf bytes.Buffer
		err = templates.CollectionDetail(user, colData, books, libraryID).Render(c.Request().Context(), &buf)
		if err != nil {
			return err
		}
		return c.HTML(http.StatusOK, buf.String())
	})

	// Custom Section Builder page
	frontendProtected.GET("/custom-section", func(c *echo.Context) error {
		user, err := getTemplateUserWithTheme(c, cfg)
		if err != nil {
			return renderErrorPage(c, "Error loading user", "user_load_error")
		}

		var errorMsg string
		var libraries []database.GetUserVisibleLibrariesRow

		userUUID, _ := uuid.Parse(user.ID)
		libraries, err = cfg.Queries.GetUserVisibleLibraries(c.Request().Context(), uuidToPGType(userUUID))
		if err != nil {
			log.Printf("GetUserVisibleLibraries failed: %v", err)
			libraries = []database.GetUserVisibleLibrariesRow{}
			errorMsg = "Error loading libraries"
		}

		libData := make([]templates.LibraryData, len(libraries))
		for i, lib := range libraries {
			libUUID, _ := uuid.FromBytes(lib.ID.Bytes[0:16])
			libData[i] = templates.LibraryData{
				ID:          libUUID.String(),
				Name:        lib.Name,
				Description: getText(lib.Description),
				TypeName:    lib.TypeName,
			}
		}

		var buf bytes.Buffer
		err = templates.CustomSectionBuilder(user, libData, errorMsg).Render(c.Request().Context(), &buf)
		if err != nil {
			return err
		}
		return c.HTML(http.StatusOK, buf.String())
	})

	// Progress page
	frontendProtected.GET("/progress", func(c *echo.Context) error {
		user, err := getTemplateUserWithTheme(c, cfg)
		if err != nil {
			return renderErrorPage(c, "Error loading user", "user_load_error")
		}

		var errorMsg string
		var progressData []handlers.ProgressWithMedia

		progressData, err = cfg.ScannerHandler.GetAllProgressData(c)
		if err != nil {
			log.Printf("GetAllProgressData failed: %v", err)
			progressData = []handlers.ProgressWithMedia{}
			errorMsg = "Error loading progress"
		}

		var buf bytes.Buffer
		err = templates.Progress(user, progressData, errorMsg).Render(c.Request().Context(), &buf)
		if err != nil {
			return err
		}
		return c.HTML(http.StatusOK, buf.String())
	})

	// Devices page
	frontendProtected.GET("/devices", func(c *echo.Context) error {
		user, err := getTemplateUserWithTheme(c, cfg)
		if err != nil {
			return renderErrorPage(c, "Error loading user", "user_load_error")
		}

		var errorMsg string
		var devices []handlers.DeviceInfo
		var pendingList []templates.PendingRegistrationData

		devices, err = cfg.DeviceHandler.GetDevicesData(c)
		if err != nil {
			log.Printf("GetDevicesData failed: %v", err)
			devices = []handlers.DeviceInfo{}
			errorMsg = "Error loading devices"
		}

		pendingMaps, err := cfg.DeviceHandler.GetPendingRegistrationsData(c)
		if err != nil {
			log.Printf("GetPendingRegistrationsData failed: %v", err)
			pendingList = []templates.PendingRegistrationData{}
			if errorMsg == "" {
				errorMsg = "Error loading pending registrations"
			}
		} else {
			pendingList = convertPending(pendingMaps)
		}

		// Get base URL from database config with fallback to config/env var
		baseURL := config.GetBaseURL(c.Request().Context(), cfg.Queries)
		if baseURL == "" {
			baseURL = cfg.Cfg.BaseURL
		}

		var buf bytes.Buffer
		err = templates.Devices(user, devices, pendingList, errorMsg, baseURL).Render(c.Request().Context(), &buf)
		if err != nil {
			return err
		}
		return c.HTML(http.StatusOK, buf.String())
	})

	// Conflicts page
	frontendProtected.GET("/conflicts", func(c *echo.Context) error {
		user, err := getTemplateUserWithTheme(c, cfg)
		if err != nil {
			return renderErrorPage(c, "Error loading user", "user_load_error")
		}

		var errorMsg string
		var conflictsData []handlers.ConflictDetailResponse
		var total, unresolved int

		conflictsData, total, unresolved, err = cfg.ConflictHandler.GetConflictsData(c)
		if err != nil {
			log.Printf("GetConflictsData failed: %v", err)
			conflictsData = []handlers.ConflictDetailResponse{}
			total = 0
			unresolved = 0
			errorMsg = "Error loading conflicts"
		}

		var buf bytes.Buffer
		err = templates.Conflicts(user, conflictsData, total, unresolved, errorMsg).Render(c.Request().Context(), &buf)
		if err != nil {
			return err
		}
		return c.HTML(http.StatusOK, buf.String())
	})

	// Analytics page
	frontendProtected.GET("/analytics", func(c *echo.Context) error {
		user, err := getTemplateUserWithTheme(c, cfg)
		if err != nil {
			return renderErrorPage(c, "Error loading user", "user_load_error")
		}
		var buf bytes.Buffer
		err = templates.Analytics(user).Render(c.Request().Context(), &buf)
		if err != nil {
			return err
		}
		return c.HTML(http.StatusOK, buf.String())
	})

	// Profile page (all users)
	frontendProtected.GET("/profile", func(c *echo.Context) error {
		user, err := getTemplateUserWithTheme(c, cfg)
		if err != nil {
			return renderErrorPage(c, "Error loading user", "user_load_error")
		}

		var buf bytes.Buffer
		err = templates.Profile(user).Render(c.Request().Context(), &buf)
		if err != nil {
			return err
		}
		return c.HTML(http.StatusOK, buf.String())
	})

	// ============================================================================
	// ADMIN FRONTEND ROUTES
	// ============================================================================

	// Admin routes
	frontendProtected.GET("/admin", handlers.AdminMiddleware(func(c *echo.Context) error {
		user, err := getTemplateUserWithTheme(c, cfg)
		if err != nil {
			return renderErrorPage(c, "Error loading user", "user_load_error")
		}
		var buf bytes.Buffer
		err = templates.Admin(user).Render(c.Request().Context(), &buf)
		if err != nil {
			return err
		}
		return c.HTML(http.StatusOK, buf.String())
	}))

	frontendProtected.GET("/admin/", handlers.AdminMiddleware(func(c *echo.Context) error {
		user, err := getTemplateUserWithTheme(c, cfg)
		if err != nil {
			return renderErrorPage(c, "Error loading user", "user_load_error")
		}
		var buf bytes.Buffer
		err = templates.Admin(user).Render(c.Request().Context(), &buf)
		if err != nil {
			return err
		}
		return c.HTML(http.StatusOK, buf.String())
	}))

	frontendProtected.GET("/admin/library", handlers.AdminMiddleware(func(c *echo.Context) error {
		user, err := getTemplateUserWithTheme(c, cfg)
		if err != nil {
			return renderErrorPage(c, "Error loading user", "user_load_error")
		}

		// Fetch all libraries (admin-only)
		libraries, err := cfg.LibraryHandler.ListLibrariesData(c.Request().Context())
		if err != nil {
			log.Printf("ListLibrariesData failed: %v", err)
			libraries = []database.ListLibrariesRow{}
		}

		// Convert to template LibraryData
		libData := make([]templates.LibraryData, len(libraries))
		for i, lib := range libraries {
			libUUID, _ := uuid.FromBytes(lib.ID.Bytes[0:16])
			libData[i] = templates.LibraryData{
				ID:          libUUID.String(),
				Name:        lib.Name,
				Description: getText(lib.Description),
				TypeName:    lib.TypeName,
			}
		}

		// Fetch all users for visibility management
		users, err := cfg.Queries.ListUsers(c.Request().Context())
		if err != nil {
			log.Printf("ListUsers failed: %v", err)
			users = []database.ListUsersRow{}
		}

		// Convert to template User types
		userData := make([]templates.User, len(users))
		for i, u := range users {
			userUUID, _ := uuid.FromBytes(u.ID.Bytes[0:16])
			userData[i] = templates.User{
				ID:       userUUID.String(),
				Username: u.Username,
				Email:    u.Email,
				Role:     u.Role,
			}
		}

		var buf bytes.Buffer
		err = templates.AdminLibrary(user, libData, userData).Render(c.Request().Context(), &buf)
		if err != nil {
			return err
		}
		return c.HTML(http.StatusOK, buf.String())
	}))

	// Admin users page
	frontendProtected.GET("/admin/users", handlers.AdminMiddleware(func(c *echo.Context) error {
		user, err := getTemplateUserWithTheme(c, cfg)
		if err != nil {
			return renderErrorPage(c, "Error loading user", "user_load_error")
		}

		// Fetch all users
		users, err := cfg.Queries.ListUsers(c.Request().Context())
		if err != nil {
			return renderErrorPage(c, "Error loading users", "users_load_error")
		}

		// Count admins for UI protection
		adminCount := 0
		for _, u := range users {
			if u.Role == "admin" {
				adminCount++
			}
		}

		// Convert to template users
		templateUsers := make([]templates.User, len(users))
		for i, u := range users {
			templateUsers[i] = templates.User{
				ID:        uuid.UUID(u.ID.Bytes).String(),
				Username:  u.Username,
				Email:     u.Email,
				Role:      u.Role,
				Theme:     getText(u.Theme),
				FirstName: getText(u.FirstName),
				LastName:  getText(u.LastName),
				CreatedAt: u.CreatedAt.Time,
			}
		}

		var buf bytes.Buffer
		err = templates.AdminUsers(user, templateUsers, adminCount).Render(c.Request().Context(), &buf)
		if err != nil {
			return err
		}
		return c.HTML(http.StatusOK, buf.String())
	}))

	// Admin: Get profile modal for editing user
	frontendProtected.GET("/admin/settings", handlers.AdminMiddleware(func(c *echo.Context) error {
		user, err := getTemplateUserWithTheme(c, cfg)
		if err != nil {
			return renderErrorPage(c, "Error loading user", "user_load_error")
		}

		// Fetch current system configuration - just base_url
		baseURL := config.GetBaseURL(c.Request().Context(), cfg.Queries)
		if baseURL == "" {
			baseURL = cfg.Cfg.BaseURL
		}

		systemConfig := map[string]string{
			"base_url": baseURL,
		}

		var buf bytes.Buffer
		err = templates.AdminSettings(user, systemConfig, "").Render(c.Request().Context(), &buf)
		if err != nil {
			return err
		}
		return c.HTML(http.StatusOK, buf.String())
	}))

	frontendProtected.GET("/admin/users/:id/profile-modal", handlers.AdminMiddleware(func(c *echo.Context) error {
		// Get target user ID from URL
		targetUserID := c.Param("id")
		parsedUUID, err := uuid.Parse(targetUserID)
		if err != nil {
			return c.HTML(http.StatusBadRequest, "<div>Invalid user ID</div>")
		}

		// Fetch target user
		targetUser, err := cfg.Queries.GetUser(c.Request().Context(), uuidToPGType(parsedUUID))
		if err != nil {
			return c.HTML(http.StatusNotFound, "<div>User not found</div>")
		}

		// Convert to template user
		templateUser := templates.User{
			ID:        uuid.UUID(targetUser.ID.Bytes).String(),
			Username:  targetUser.Username,
			Email:     targetUser.Email,
			Role:      targetUser.Role,
			Theme:     getText(targetUser.Theme),
			FirstName: getText(targetUser.FirstName),
			LastName:  getText(targetUser.LastName),
			CreatedAt: targetUser.CreatedAt.Time,
		}

		// Render modal
		var buf bytes.Buffer
		err = templates.ProfileModal(templateUser).Render(c.Request().Context(), &buf)
		if err != nil {
			return err
		}
		return c.HTML(http.StatusOK, buf.String())
	}))

	// ============================================================================
	// LEGACY API ROUTES (for backward compatibility)
	// ============================================================================

	// Keep legacy routes under /api for existing API consumers
	protected.GET("/devices-page", func(c *echo.Context) error {
		user, err := getTemplateUserWithTheme(c, cfg)
		if err != nil {
			return renderErrorPage(c, "Error loading user", "user_load_error")
		}
		var errorMsg string
		var devices []handlers.DeviceInfo
		var pendingList []templates.PendingRegistrationData

		devices, err = cfg.DeviceHandler.GetDevicesData(c)
		if err != nil {
			log.Printf("GetDevicesData failed: %v", err)
			devices = []handlers.DeviceInfo{}
			errorMsg = "Error loading devices"
		}

		pendingMaps, err := cfg.DeviceHandler.GetPendingRegistrationsData(c)
		if err != nil {
			log.Printf("GetPendingRegistrationsData failed: %v", err)
			pendingList = []templates.PendingRegistrationData{}
			if errorMsg == "" {
				errorMsg = "Error loading pending registrations"
			}
		} else {
			pendingList = convertPending(pendingMaps)
		}

		// Get base URL from database config with fallback to config/env var
		baseURL := config.GetBaseURL(c.Request().Context(), cfg.Queries)
		if baseURL == "" {
			baseURL = cfg.Cfg.BaseURL
		}

		var buf bytes.Buffer
		err = templates.Devices(user, devices, pendingList, errorMsg, baseURL).Render(c.Request().Context(), &buf)
		if err != nil {
			return err
		}
		return c.HTML(http.StatusOK, buf.String())
	})

	protected.GET("/conflicts-page", func(c *echo.Context) error {
		user, err := getTemplateUserWithTheme(c, cfg)
		if err != nil {
			return renderErrorPage(c, "Error loading user", "user_load_error")
		}

		var errorMsg string
		var conflictsData []handlers.ConflictDetailResponse
		var total, unresolved int

		conflictsData, total, unresolved, err = cfg.ConflictHandler.GetConflictsData(c)
		if err != nil {
			log.Printf("GetConflictsData failed: %v", err)
			conflictsData = []handlers.ConflictDetailResponse{}
			total = 0
			unresolved = 0
			errorMsg = "Error loading conflicts"
		}

		var buf bytes.Buffer
		err = templates.Conflicts(user, conflictsData, total, unresolved, errorMsg).Render(c.Request().Context(), &buf)
		if err != nil {
			return err
		}
		return c.HTML(http.StatusOK, buf.String())
	})

	e.GET("/health", cfg.GetHealth)
}

// ============================================================================
// HEALTH CHECK
// ============================================================================

// Health check
func (cfg *Config) GetHealth(c *echo.Context) error {
	ctx, cancel := context.WithTimeout(c.Request().Context(), 2*time.Second)
	defer cancel()
	if err := pingDB(cfg, ctx); err != nil {
		return c.JSON(http.StatusServiceUnavailable, map[string]string{
			"status": "unhealthy",
			"error":  err.Error(),
		})
	}

	return c.JSON(http.StatusOK, map[string]interface{}{
		"status":   "healthy",
		"database": "connected",
		"scan": map[string]interface{}{
			"scan_in_progress": cfg.Worker.HasActiveScans(),
			"active_jobs":      cfg.Worker.GetActiveJobCount(),
		},
	})
}
