package handlers

import (
	"bookhoard/internal/config"
	"bookhoard/internal/database"
	"crypto/rand"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"net/http"
	"time"

	"github.com/google/uuid"
	"github.com/jackc/pgx/v5/pgtype"
	"github.com/labstack/echo/v5"
	"github.com/skip2/go-qrcode"
	"golang.org/x/crypto/bcrypt"
)

type DeviceHandler struct {
	db     *database.Queries
	jwtKey []byte
	cfg    *config.Config
}

func NewDeviceHandler(db *database.Queries, jwtSecret string, cfg *config.Config) *DeviceHandler {
	return &DeviceHandler{
		db:     db,
		jwtKey: []byte(jwtSecret),
		cfg:    cfg,
	}
}

type DeviceRegistrationRequest struct {
	DeviceName       string `json:"device_name" validate:"required,min=1,max=100"`
	DeviceType       string `json:"device_type" validate:"required,oneof=koreader kobo web mobile"`
	DeviceIdentifier string `json:"device_identifier" validate:"required,min=1,max=255"`
}

type DeviceRegistrationResponse struct {
	DeviceID          uuid.UUID         `json:"device_id"`
	RegistrationID    string            `json:"registration_id"`
	AuthURL           string            `json:"auth_url"`
	QRCode            string            `json:"qr_code"`
	ExpiresIn         int               `json:"expires_in"`
	PollInterval      int               `json:"poll_interval"`
	SetupInstructions map[string]string `json:"setup_instructions"`
}

type DeviceAuthStatusRequest struct {
	RegistrationID string `json:"registration_id" validate:"required"`
}

type DeviceAuthStatusResponse struct {
	Status        string            `json:"status"`
	AuthToken     string            `json:"auth_token,omitempty"`
	DeviceID      uuid.UUID         `json:"device_id,omitempty"`
	SyncEndpoints map[string]string `json:"sync_endpoints,omitempty"`
	Message       string            `json:"message,omitempty"`
	ExpiresIn     int               `json:"expires_in,omitempty"`
}

type DeviceListResponse struct {
	Devices []DeviceInfo `json:"devices"`
	Total   int          `json:"total"`
}

type DeviceInfo struct {
	ID             uuid.UUID       `json:"id"`
	DeviceName     string          `json:"device_name"`
	DeviceType     string          `json:"device_type"`
	LastSync       *time.Time      `json:"last_sync"`
	LastSeen       *time.Time      `json:"last_seen"`
	SyncEnabled    bool            `json:"sync_enabled"`
	AutoSync       bool            `json:"auto_sync"`
	SyncFrequency  int32           `json:"sync_frequency_minutes"`
	CreatedAt      time.Time       `json:"created_at"`
	DeviceMetadata json.RawMessage `json:"device_metadata,omitempty"`
	AuthToken      string          `json:"auth_token"`
}

type DeviceUpdateRequest struct {
	DeviceName           string          `json:"device_name,omitempty" validate:"omitempty,min=1,max=100"`
	SyncEnabled          *bool           `json:"sync_enabled,omitempty"`
	AutoSync             *bool           `json:"auto_sync,omitempty"`
	SyncFrequencyMinutes *int32          `json:"sync_frequency_minutes,omitempty" validate:"omitempty,min=1,max=1440"`
	DeviceMetadata       json.RawMessage `json:"device_metadata,omitempty"`
}

type DeviceApprovalRequest struct {
	RegistrationID string `json:"registration_id" validate:"required"`
	Approve        bool   `json:"approve"`
}

type PendingRegistration struct {
	RegistrationID   string
	DeviceName       string
	DeviceType       string
	DeviceIdentifier string
	UserID           uuid.UUID
	ExpiresAt        time.Time
	CreatedAt        time.Time
	Approved         bool
	AuthToken        string
	DeviceID         [16]byte
	SyncEndpoints    map[string]string
}

var pendingRegistrations = make(map[string]*PendingRegistration)

func (h *DeviceHandler) InitiateRegistration(c *echo.Context) error {
	req := DeviceRegistrationRequest{}
	if err := c.Bind(&req); err != nil {
		return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid request format"})
	}

	if err := c.Validate(&req); err != nil {
		return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
	}

	registrationID := uuid.New().String()
	expiresAt := time.Now().Add(5 * time.Minute)

	registration := &PendingRegistration{
		RegistrationID:   registrationID,
		DeviceName:       req.DeviceName,
		DeviceType:       req.DeviceType,
		DeviceIdentifier: req.DeviceIdentifier,
		ExpiresAt:        expiresAt,
		CreatedAt:        time.Now(),
	}

	pendingRegistrations[registrationID] = registration

	authURL := fmt.Sprintf("%s/devices/approve/%s", h.cfg.BaseURL, registrationID)

	qrCode, err := qrcode.Encode(authURL, qrcode.Medium, 256)
	if err != nil {
		return c.JSON(http.StatusInternalServerError, map[string]string{"error": "failed to generate QR code"})
	}

	qrCodeBase64 := base64.StdEncoding.EncodeToString(qrCode)

	setupInstructions := map[string]string{}
	switch req.DeviceType {
	case "koreader":
		setupInstructions["koreader"] = fmt.Sprintf("Calibre URL: %s/api/sync/koreader", h.cfg.BaseURL)
	case "kobo":
		setupInstructions["kobo"] = fmt.Sprintf("Sync URL: %s/api/sync/kobo", h.cfg.BaseURL)
	}

	response := DeviceRegistrationResponse{
		RegistrationID:    registrationID,
		AuthURL:           authURL,
		QRCode:            "data:image/png;base64," + qrCodeBase64,
		ExpiresIn:         300,
		PollInterval:      3,
		SetupInstructions: setupInstructions,
	}

	return c.JSON(http.StatusCreated, response)
}

func (h *DeviceHandler) CheckRegistrationStatus(c *echo.Context) error {
	req := DeviceAuthStatusRequest{}
	if err := c.Bind(&req); err != nil {
		return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid request format"})
	}

	registration, exists := pendingRegistrations[req.RegistrationID]
	if !exists {
		return c.JSON(http.StatusNotFound, map[string]string{"error": "registration not found"})
	}

	if time.Now().After(registration.ExpiresAt) {
		delete(pendingRegistrations, req.RegistrationID)
		return c.JSON(http.StatusGone, map[string]string{"error": "registration expired"})
	}

	if registration.Approved {
		delete(pendingRegistrations, req.RegistrationID)

		return c.JSON(http.StatusOK, DeviceAuthStatusResponse{
			Status:        "approved",
			AuthToken:     registration.AuthToken,
			DeviceID:      registration.DeviceID,
			SyncEndpoints: registration.SyncEndpoints,
		})
	}

	return c.JSON(http.StatusOK, DeviceAuthStatusResponse{
		Status:    "pending",
		Message:   "awaiting user approval",
		ExpiresIn: int(time.Until(registration.ExpiresAt).Seconds()),
	})
}

func (h *DeviceHandler) ListDevices(c *echo.Context) error {
	userID := c.Get("user_id").(string)
	userUUID, err := uuid.Parse(userID)
	if err != nil {
		return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid user ID"})
	}

	pgUserID := pgtype.UUID{Bytes: [16]byte(userUUID), Valid: true}

	devices, err := h.db.ListDevicesByUser(c.Request().Context(), pgUserID)
	if err != nil {
		return c.JSON(http.StatusInternalServerError, map[string]string{"error": "failed to list devices"})
	}

	deviceList := make([]DeviceInfo, 0, len(devices))
	for _, device := range devices {
		syncEnabled := device.SyncEnabled.Bool && device.SyncEnabled.Valid
		autoSync := device.AutoSync.Bool && device.AutoSync.Valid
		syncFreq := int32(0)
		if device.SyncFrequencyMinutes.Valid {
			syncFreq = device.SyncFrequencyMinutes.Int32
		}

		deviceList = append(deviceList, DeviceInfo{
			ID:             device.ID.Bytes,
			DeviceName:     device.DeviceName,
			DeviceType:     device.DeviceType,
			LastSync:       &device.LastSync.Time,
			LastSeen:       &device.LastSeen.Time,
			SyncEnabled:    syncEnabled,
			AutoSync:       autoSync,
			SyncFrequency:  syncFreq,
			CreatedAt:      device.CreatedAt.Time,
			DeviceMetadata: device.DeviceMetadata,
			AuthToken:      device.AuthToken,
		})
	}

	return c.JSON(http.StatusOK, DeviceListResponse{
		Devices: deviceList,
		Total:   len(deviceList),
	})
}

func (h *DeviceHandler) GetDevicesData(c *echo.Context) ([]DeviceInfo, error) {
	userID := c.Get("user_id").(string)
	userUUID, err := uuid.Parse(userID)
	if err != nil {
		return nil, err
	}

	pgUserID := pgtype.UUID{Bytes: [16]byte(userUUID), Valid: true}

	devices, err := h.db.ListDevicesByUser(c.Request().Context(), pgUserID)
	if err != nil {
		return nil, err
	}

	deviceList := make([]DeviceInfo, 0, len(devices))
	for _, device := range devices {
		syncEnabled := device.SyncEnabled.Bool && device.SyncEnabled.Valid
		autoSync := device.AutoSync.Bool && device.AutoSync.Valid
		syncFreq := int32(0)
		if device.SyncFrequencyMinutes.Valid {
			syncFreq = device.SyncFrequencyMinutes.Int32
		}

		deviceList = append(deviceList, DeviceInfo{
			ID:             device.ID.Bytes,
			DeviceName:     device.DeviceName,
			DeviceType:     device.DeviceType,
			LastSync:       &device.LastSync.Time,
			LastSeen:       &device.LastSeen.Time,
			SyncEnabled:    syncEnabled,
			AutoSync:       autoSync,
			SyncFrequency:  syncFreq,
			CreatedAt:      device.CreatedAt.Time,
			DeviceMetadata: device.DeviceMetadata,
			AuthToken:      device.AuthToken,
		})
	}

	return deviceList, nil
}

func (h *DeviceHandler) GetDevice(c *echo.Context) error {
	userID := c.Get("user_id")
	if userID == nil {
		return c.JSON(http.StatusUnauthorized, map[string]string{"error": "unauthorized"})
	}

	userUUID, err := uuid.Parse(userID.(string))
	if err != nil {
		return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid user ID"})
	}

	deviceID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid device ID"})
	}

	pgDeviceID := pgtype.UUID{Bytes: [16]byte(deviceID), Valid: true}

	device, err := h.db.GetDevice(c.Request().Context(), pgDeviceID)
	if err != nil {
		return c.JSON(http.StatusNotFound, map[string]string{"error": "device not found"})
	}

	if device.UserID.Bytes != userUUID {
		return c.JSON(http.StatusForbidden, map[string]string{"error": "access denied"})
	}

	syncEnabled := device.SyncEnabled.Bool && device.SyncEnabled.Valid
	autoSync := device.AutoSync.Bool && device.AutoSync.Valid
	syncFreq := int32(0)
	if device.SyncFrequencyMinutes.Valid {
		syncFreq = device.SyncFrequencyMinutes.Int32
	}

	return c.JSON(http.StatusOK, DeviceInfo{
		ID:             device.ID.Bytes,
		DeviceName:     device.DeviceName,
		DeviceType:     device.DeviceType,
		LastSync:       &device.LastSync.Time,
		LastSeen:       &device.LastSeen.Time,
		SyncEnabled:    syncEnabled,
		AutoSync:       autoSync,
		SyncFrequency:  syncFreq,
		CreatedAt:      device.CreatedAt.Time,
		DeviceMetadata: device.DeviceMetadata,
	})
}

func (h *DeviceHandler) UpdateDevice(c *echo.Context) error {
	userID := c.Get("user_id").(string)
	userUUID, err := uuid.Parse(userID)
	if err != nil {
		return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid user ID"})
	}

	deviceID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid device ID"})
	}

	pgDeviceID := pgtype.UUID{Bytes: [16]byte(deviceID), Valid: true}

	device, err := h.db.GetDevice(c.Request().Context(), pgDeviceID)
	if err != nil {
		return c.JSON(http.StatusNotFound, map[string]string{"error": "device not found"})
	}

	if device.UserID.Bytes != userUUID {
		return c.JSON(http.StatusForbidden, map[string]string{"error": "access denied"})
	}

	req := DeviceUpdateRequest{}
	if err := c.Bind(&req); err != nil {
		return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid request format"})
	}

	if err := c.Validate(&req); err != nil {
		return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
	}

	updateParams := database.UpdateDeviceParams{
		ID: pgDeviceID,
	}

	if req.DeviceName != "" {
		updateParams.DeviceName = req.DeviceName
	} else {
		updateParams.DeviceName = device.DeviceName
	}

	if req.SyncEnabled != nil {
		updateParams.SyncEnabled = pgtype.Bool{Bool: *req.SyncEnabled, Valid: true}
	} else {
		updateParams.SyncEnabled = device.SyncEnabled
	}

	if req.AutoSync != nil {
		updateParams.AutoSync = pgtype.Bool{Bool: *req.AutoSync, Valid: true}
	} else {
		updateParams.AutoSync = device.AutoSync
	}

	if req.SyncFrequencyMinutes != nil {
		updateParams.SyncFrequencyMinutes = pgtype.Int4{Int32: *req.SyncFrequencyMinutes, Valid: true}
	} else {
		updateParams.SyncFrequencyMinutes = device.SyncFrequencyMinutes
	}

	if req.DeviceMetadata != nil {
		updateParams.DeviceMetadata = req.DeviceMetadata
	} else {
		updateParams.DeviceMetadata = device.DeviceMetadata
	}

	updatedDevice, err := h.db.UpdateDevice(c.Request().Context(), updateParams)
	if err != nil {
		return c.JSON(http.StatusInternalServerError, map[string]string{"error": "failed to update device"})
	}

	syncEnabled := updatedDevice.SyncEnabled.Bool && updatedDevice.SyncEnabled.Valid
	autoSync := updatedDevice.AutoSync.Bool && updatedDevice.AutoSync.Valid
	syncFreq := int32(0)
	if updatedDevice.SyncFrequencyMinutes.Valid {
		syncFreq = updatedDevice.SyncFrequencyMinutes.Int32 // Fixed: Use actual updated value
	}

	return c.JSON(http.StatusOK, map[string]interface{}{
		"device_updated": true,
		"device": DeviceInfo{
			ID:             updatedDevice.ID.Bytes,
			DeviceName:     updatedDevice.DeviceName,
			DeviceType:     updatedDevice.DeviceType,
			LastSync:       &updatedDevice.LastSync.Time,
			LastSeen:       &updatedDevice.LastSeen.Time,
			SyncEnabled:    syncEnabled,
			AutoSync:       autoSync,
			SyncFrequency:  syncFreq, // Now correctly returns the updated value
			CreatedAt:      updatedDevice.CreatedAt.Time,
			DeviceMetadata: updatedDevice.DeviceMetadata,
		},
	})
}

func (h *DeviceHandler) DeleteDevice(c *echo.Context) error {
	userID := c.Get("user_id").(string)
	userUUID, err := uuid.Parse(userID)
	if err != nil {
		return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid user ID"})
	}

	deviceID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid device ID"})
	}

	pgDeviceID := pgtype.UUID{Bytes: [16]byte(deviceID), Valid: true}

	device, err := h.db.GetDevice(c.Request().Context(), pgDeviceID)
	if err != nil {
		return c.JSON(http.StatusNotFound, map[string]string{"error": "device not found"})
	}

	if device.UserID.Bytes != userUUID {
		return c.JSON(http.StatusForbidden, map[string]string{"error": "access denied"})
	}

	if err := h.db.DeleteDevice(c.Request().Context(), pgDeviceID); err != nil {
		return c.JSON(http.StatusInternalServerError, map[string]string{"error": "failed to delete device"})
	}

	return c.NoContent(http.StatusNoContent)
}

func (h *DeviceHandler) RegenerateDeviceToken(c *echo.Context) error {
	// Verify JWT authentication
	userID := c.Get("user_id").(string)
	userUUID, err := uuid.Parse(userID)
	if err != nil {
		return c.JSON(http.StatusUnauthorized, map[string]string{"error": "invalid user ID"})
	}

	// Parse device ID from URL parameter
	deviceID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid device ID"})
	}

	pgDeviceID := pgtype.UUID{Bytes: [16]byte(deviceID), Valid: true}

	// Verify device exists and belongs to user
	device, err := h.db.GetDevice(c.Request().Context(), pgDeviceID)
	if err != nil {
		return c.JSON(http.StatusNotFound, map[string]string{"error": "device not found"})
	}

	if device.UserID.Bytes != userUUID {
		return c.JSON(http.StatusForbidden, map[string]string{"error": "access denied"})
	}

	// Generate new auth token
	newToken, err := generateDeviceToken()
	if err != nil {
		return c.JSON(http.StatusInternalServerError, map[string]string{"error": "failed to generate token"})
	}

	// Update device with new token
	updatedDevice, err := h.db.UpdateDeviceAuthToken(c.Request().Context(), database.UpdateDeviceAuthTokenParams{
		ID:        pgDeviceID,
		AuthToken: newToken,
	})

	if err != nil {
		return c.JSON(http.StatusInternalServerError, map[string]string{"error": "failed to update token"})
	}

	// Return new token with device info
	syncEnabled := updatedDevice.SyncEnabled.Bool && updatedDevice.SyncEnabled.Valid
	autoSync := updatedDevice.AutoSync.Bool && updatedDevice.AutoSync.Valid
	syncFreq := int32(0)
	if updatedDevice.SyncFrequencyMinutes.Valid {
		syncFreq = updatedDevice.SyncFrequencyMinutes.Int32
	}

	// Build sync URLs with new token
	syncURLs := map[string]string{}
	baseURL := h.cfg.BaseURL

	switch updatedDevice.DeviceType {
	case "kobo":
		syncURLs["sync_url"] = fmt.Sprintf("%s/api/sync/kobo/%s", baseURL, newToken)
		syncURLs["markup"] = fmt.Sprintf("%s/api/sync/kobo/%s/markup", baseURL, newToken)
		syncURLs["bookmark"] = fmt.Sprintf("%s/api/sync/kobo/%s/bookmark", baseURL, newToken)
		syncURLs["init"] = fmt.Sprintf("%s/api/sync/kobo/%s/v1/initialization", baseURL, newToken)
	case "koreader":
		syncURLs["progress"] = fmt.Sprintf("%s/api/sync/koreader/progress", baseURL)
		syncURLs["metadata"] = fmt.Sprintf("%s/api/sync/koreader/metadata", baseURL)
		syncURLs["bookmarks"] = fmt.Sprintf("%s/api/sync/koreader/bookmarks", baseURL)
	}

	// Handle HTMX requests - return HTML with page reload script
	if c.Request().Header.Get("HX-Request") == "true" {
		html := `<div class="text-green-500">Token regenerated! Reloading ... </div><script>window.location.reload();`
		return c.HTML(http.StatusOK, html)
	}
	return c.JSON(http.StatusOK, map[string]interface{}{
		"message":    "Token regenerated successfully",
		"auth_token": newToken,
		"device": DeviceInfo{
			ID:             updatedDevice.ID.Bytes,
			DeviceName:     updatedDevice.DeviceName,
			DeviceType:     updatedDevice.DeviceType,
			LastSync:       &updatedDevice.LastSync.Time,
			LastSeen:       &updatedDevice.LastSeen.Time,
			SyncEnabled:    syncEnabled,
			AutoSync:       autoSync,
			SyncFrequency:  syncFreq,
			CreatedAt:      updatedDevice.CreatedAt.Time,
			DeviceMetadata: updatedDevice.DeviceMetadata,
		},
		"sync_urls": syncURLs,
	})
}

func (h *DeviceHandler) ApproveDevice(c *echo.Context) error {
	userID := c.Get("user_id").(string)
	userUUID, err := uuid.Parse(userID)
	if err != nil {
		return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid user ID"})
	}

	registrationID := c.Param("registration_id")

	registration, exists := pendingRegistrations[registrationID]
	if !exists {
		return c.JSON(http.StatusNotFound, map[string]string{"error": "registration not found"})
	}

	if time.Now().After(registration.ExpiresAt) {
		delete(pendingRegistrations, registrationID)
		return c.JSON(http.StatusGone, map[string]string{"error": "registration expired"})
	}

	if registration.Approved {
		return c.JSON(http.StatusOK, map[string]interface{}{
			"message":     "device already approved",
			"device_name": registration.DeviceName,
			"device_type": registration.DeviceType,
			"approved":    true,
		})
	}

	authToken, err := generateDeviceToken()
	if err != nil {
		return c.JSON(http.StatusInternalServerError, map[string]string{"error": "failed to generate auth token"})
	}

	pgUserID := pgtype.UUID{Bytes: [16]byte(userUUID), Valid: true}
	syncEnabled := pgtype.Bool{Bool: true, Valid: true}
	autoSync := pgtype.Bool{Bool: true, Valid: true}
	syncFreq := pgtype.Int4{Int32: 5, Valid: true}

	device, err := h.db.CreateDevice(c.Request().Context(), database.CreateDeviceParams{
		UserID:               pgUserID,
		DeviceName:           registration.DeviceName,
		DeviceType:           registration.DeviceType,
		DeviceIdentifier:     registration.DeviceIdentifier,
		AuthToken:            authToken,
		SyncEnabled:          syncEnabled,
		AutoSync:             autoSync,
		SyncFrequencyMinutes: syncFreq,
		DeviceMetadata:       []byte("{}"),
	})
	if err != nil {
		return c.JSON(http.StatusInternalServerError, map[string]string{"error": "failed to create device"})
	}

	syncEndpoints := map[string]string{}
	switch registration.DeviceType {
	case "koreader":
		syncEndpoints["progress"] = fmt.Sprintf("%s/api/sync/koreader/progress", h.cfg.BaseURL)
		syncEndpoints["metadata"] = fmt.Sprintf("%s/api/sync/koreader/metadata", h.cfg.BaseURL)
		syncEndpoints["bookmarks"] = fmt.Sprintf("%s/api/sync/koreader/bookmarks", h.cfg.BaseURL)
	case "kobo":
		syncEndpoints["markup"] = fmt.Sprintf("%s/api/sync/kobo/markup", h.cfg.BaseURL)
		syncEndpoints["library"] = fmt.Sprintf("%s/api/sync/kobo/library", h.cfg.BaseURL)
	}

	registration.UserID = userUUID
	registration.Approved = true
	registration.AuthToken = authToken
	registration.DeviceID = device.ID.Bytes
	registration.SyncEndpoints = syncEndpoints

	return c.JSON(http.StatusOK, map[string]interface{}{
		"message":         "device approved successfully",
		"device_name":     registration.DeviceName,
		"device_type":     registration.DeviceType,
		"registration_id": registrationID,
		"approved":        true,
	})
}

func (h *DeviceHandler) RejectDevice(c *echo.Context) error {
	registrationID := c.Param("registration_id")

	_, exists := pendingRegistrations[registrationID]
	if !exists {
		return c.JSON(http.StatusNotFound, map[string]string{"error": "registration not found"})
	}

	delete(pendingRegistrations, registrationID)

	return c.JSON(http.StatusOK, map[string]string{
		"message": "device registration rejected",
	})
}

func (h *DeviceHandler) GetPendingRegistrationsData(c *echo.Context) ([]map[string]interface{}, error) {
	registrations := []map[string]interface{}{}
	for _, reg := range pendingRegistrations {
		if reg.UserID == (uuid.UUID{}) {
			registrations = append(registrations, map[string]interface{}{
				"registration_id":   reg.RegistrationID,
				"device_name":       reg.DeviceName,
				"device_type":       reg.DeviceType,
				"device_identifier": reg.DeviceIdentifier,
				"expires_at":        reg.ExpiresAt,
				"created_at":        reg.CreatedAt,
				"is_approved":       false,
			})
		}
	}

	return registrations, nil
}

func (h *DeviceHandler) ListPendingRegistrations(c *echo.Context) error {
	userID := c.Get("user_id").(string)
	userUUID, err := uuid.Parse(userID)
	if err != nil {
		return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid user ID"})
	}

	registrations := []map[string]interface{}{}
	for _, reg := range pendingRegistrations {
		if reg.UserID == userUUID || reg.UserID == (uuid.UUID{}) {
			registrations = append(registrations, map[string]interface{}{
				"registration_id":   reg.RegistrationID,
				"device_name":       reg.DeviceName,
				"device_type":       reg.DeviceType,
				"device_identifier": reg.DeviceIdentifier,
				"expires_at":        reg.ExpiresAt,
				"created_at":        reg.CreatedAt,
				"is_approved":       reg.UserID != (uuid.UUID{}),
			})
		}
	}

	return c.JSON(http.StatusOK, map[string]interface{}{
		"registrations":         registrations,
		"pending_registrations": registrations, // Fixed: Add for test compatibility and API clarity
		"total":                 len(registrations),
	})
}

func generateDeviceToken() (string, error) {
	bytes := make([]byte, 32)
	if _, err := rand.Read(bytes); err != nil {
		return "", err
	}

	hashedToken, err := bcrypt.GenerateFromPassword(bytes, bcrypt.DefaultCost)
	if err != nil {
		return "", err
	}

	token := base64.StdEncoding.EncodeToString(hashedToken)

	return fmt.Sprintf("dev_%s", token), nil
}

func ValidateDeviceToken(hashedToken string, plainToken string) bool {
	err := bcrypt.CompareHashAndPassword([]byte(hashedToken), []byte(plainToken))
	return err == nil
}
