package handlers

import (
	"net/http"
	"strconv"

	"github.com/labstack/echo/v4"
	"gorm.io/gorm"

	"github.com/treytartt/honeydue-api/internal/admin/dto"
	"github.com/treytartt/honeydue-api/internal/models"
)

// AdminAppleSocialAuthHandler handles admin Apple social auth management endpoints
type AdminAppleSocialAuthHandler struct {
	db *gorm.DB
}

// NewAdminAppleSocialAuthHandler creates a new admin Apple social auth handler
func NewAdminAppleSocialAuthHandler(db *gorm.DB) *AdminAppleSocialAuthHandler {
	return &AdminAppleSocialAuthHandler{db: db}
}

// AppleSocialAuthResponse represents the response for an Apple social auth entry
type AppleSocialAuthResponse struct {
	ID             uint   `json:"id"`
	UserID         uint   `json:"user_id"`
	Username       string `json:"username"`
	UserEmail      string `json:"user_email"`
	AppleID        string `json:"apple_id"`
	Email          string `json:"email"`
	IsPrivateEmail bool   `json:"is_private_email"`
	CreatedAt      string `json:"created_at"`
	UpdatedAt      string `json:"updated_at"`
}

// UpdateAppleSocialAuthRequest represents the request to update an Apple social auth entry
type UpdateAppleSocialAuthRequest struct {
	Email          *string `json:"email"`
	IsPrivateEmail *bool   `json:"is_private_email"`
}

// List handles GET /api/admin/apple-social-auth
func (h *AdminAppleSocialAuthHandler) List(c echo.Context) error {
	var filters dto.PaginationParams
	if err := c.Bind(&filters); err != nil {
		return c.JSON(http.StatusBadRequest, map[string]interface{}{"error": "Invalid request body"})
	}

	var entries []models.AppleSocialAuth
	var total int64

	query := h.db.Model(&models.AppleSocialAuth{}).Preload("User")

	// Apply search
	if filters.Search != "" {
		search := "%" + filters.Search + "%"
		query = query.Joins("JOIN auth_user ON auth_user.id = user_applesocialauth.user_id").
			Where("user_applesocialauth.apple_id ILIKE ? OR user_applesocialauth.email ILIKE ? OR auth_user.username ILIKE ? OR auth_user.email ILIKE ?",
				search, search, search, search)
	}

	// Get total count
	query.Count(&total)

	// Apply sorting (allowlist prevents SQL injection via sort_by parameter)
	sortBy := filters.GetSafeSortBy([]string{
		"id", "user_id", "apple_id", "email", "is_private_email",
		"created_at", "updated_at",
	}, "created_at")
	query = query.Order(sortBy + " " + filters.GetSortDir())

	// Apply pagination
	query = query.Offset(filters.GetOffset()).Limit(filters.GetPerPage())

	if err := query.Find(&entries).Error; err != nil {
		return c.JSON(http.StatusInternalServerError, map[string]interface{}{"error": "Failed to fetch Apple social auth entries"})
	}

	// Build response
	responses := make([]AppleSocialAuthResponse, len(entries))
	for i, entry := range entries {
		responses[i] = h.toResponse(&entry)
	}

	return c.JSON(http.StatusOK, dto.NewPaginatedResponse(responses, total, filters.GetPage(), filters.GetPerPage()))
}

// Get handles GET /api/admin/apple-social-auth/:id
func (h *AdminAppleSocialAuthHandler) Get(c echo.Context) error {
	id, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		return c.JSON(http.StatusBadRequest, map[string]interface{}{"error": "Invalid ID"})
	}

	var entry models.AppleSocialAuth
	if err := h.db.Preload("User").First(&entry, id).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			return c.JSON(http.StatusNotFound, map[string]interface{}{"error": "Apple social auth entry not found"})
		}
		return c.JSON(http.StatusInternalServerError, map[string]interface{}{"error": "Failed to fetch Apple social auth entry"})
	}

	return c.JSON(http.StatusOK, h.toResponse(&entry))
}

// GetByUser handles GET /api/admin/apple-social-auth/user/:user_id
func (h *AdminAppleSocialAuthHandler) GetByUser(c echo.Context) error {
	userID, err := strconv.ParseUint(c.Param("user_id"), 10, 32)
	if err != nil {
		return c.JSON(http.StatusBadRequest, map[string]interface{}{"error": "Invalid user ID"})
	}

	var entry models.AppleSocialAuth
	if err := h.db.Preload("User").Where("user_id = ?", userID).First(&entry).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			return c.JSON(http.StatusNotFound, map[string]interface{}{"error": "Apple social auth entry not found for user"})
		}
		return c.JSON(http.StatusInternalServerError, map[string]interface{}{"error": "Failed to fetch Apple social auth entry"})
	}

	return c.JSON(http.StatusOK, h.toResponse(&entry))
}

// Update handles PUT /api/admin/apple-social-auth/:id
func (h *AdminAppleSocialAuthHandler) Update(c echo.Context) error {
	id, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		return c.JSON(http.StatusBadRequest, map[string]interface{}{"error": "Invalid ID"})
	}

	var entry models.AppleSocialAuth
	if err := h.db.First(&entry, id).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			return c.JSON(http.StatusNotFound, map[string]interface{}{"error": "Apple social auth entry not found"})
		}
		return c.JSON(http.StatusInternalServerError, map[string]interface{}{"error": "Failed to fetch Apple social auth entry"})
	}

	var req UpdateAppleSocialAuthRequest
	if err := c.Bind(&req); err != nil {
		return c.JSON(http.StatusBadRequest, map[string]interface{}{"error": "Invalid request body"})
	}

	if req.Email != nil {
		entry.Email = *req.Email
	}
	if req.IsPrivateEmail != nil {
		entry.IsPrivateEmail = *req.IsPrivateEmail
	}

	if err := h.db.Save(&entry).Error; err != nil {
		return c.JSON(http.StatusInternalServerError, map[string]interface{}{"error": "Failed to update Apple social auth entry"})
	}

	h.db.Preload("User").First(&entry, id)
	return c.JSON(http.StatusOK, h.toResponse(&entry))
}

// Delete handles DELETE /api/admin/apple-social-auth/:id
func (h *AdminAppleSocialAuthHandler) Delete(c echo.Context) error {
	id, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		return c.JSON(http.StatusBadRequest, map[string]interface{}{"error": "Invalid ID"})
	}

	var entry models.AppleSocialAuth
	if err := h.db.First(&entry, id).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			return c.JSON(http.StatusNotFound, map[string]interface{}{"error": "Apple social auth entry not found"})
		}
		return c.JSON(http.StatusInternalServerError, map[string]interface{}{"error": "Failed to fetch Apple social auth entry"})
	}

	if err := h.db.Delete(&entry).Error; err != nil {
		return c.JSON(http.StatusInternalServerError, map[string]interface{}{"error": "Failed to delete Apple social auth entry"})
	}

	return c.JSON(http.StatusOK, map[string]interface{}{"message": "Apple social auth entry deleted successfully"})
}

// BulkDelete handles DELETE /api/admin/apple-social-auth/bulk
func (h *AdminAppleSocialAuthHandler) BulkDelete(c echo.Context) error {
	var req dto.BulkDeleteRequest
	if err := c.Bind(&req); err != nil {
		return c.JSON(http.StatusBadRequest, map[string]interface{}{"error": "Invalid request body"})
	}

	result := h.db.Where("id IN ?", req.IDs).Delete(&models.AppleSocialAuth{})
	if result.Error != nil {
		return c.JSON(http.StatusInternalServerError, map[string]interface{}{"error": "Failed to delete Apple social auth entries"})
	}

	return c.JSON(http.StatusOK, map[string]interface{}{"message": "Apple social auth entries deleted successfully", "count": result.RowsAffected})
}

// toResponse converts an AppleSocialAuth model to AppleSocialAuthResponse
func (h *AdminAppleSocialAuthHandler) toResponse(entry *models.AppleSocialAuth) AppleSocialAuthResponse {
	response := AppleSocialAuthResponse{
		ID:             entry.ID,
		UserID:         entry.UserID,
		AppleID:        entry.AppleID,
		Email:          entry.Email,
		IsPrivateEmail: entry.IsPrivateEmail,
		CreatedAt:      entry.CreatedAt.Format("2006-01-02T15:04:05Z"),
		UpdatedAt:      entry.UpdatedAt.Format("2006-01-02T15:04:05Z"),
	}

	if entry.User.ID != 0 {
		response.Username = entry.User.Username
		response.UserEmail = entry.User.Email
	}

	return response
}
