package handlers

import (
	"net/http"

	"github.com/labstack/echo/v4"

	"github.com/treytartt/honeydue-api/internal/config"
	"github.com/treytartt/honeydue-api/internal/middleware"
	"github.com/treytartt/honeydue-api/internal/models"
	"github.com/treytartt/honeydue-api/internal/repositories"
)

// AdminAuthHandler handles admin authentication endpoints
type AdminAuthHandler struct {
	adminRepo *repositories.AdminRepository
	cfg       *config.Config
}

// NewAdminAuthHandler creates a new admin auth handler
func NewAdminAuthHandler(adminRepo *repositories.AdminRepository, cfg *config.Config) *AdminAuthHandler {
	return &AdminAuthHandler{
		adminRepo: adminRepo,
		cfg:       cfg,
	}
}

// LoginRequest represents the admin login request
type LoginRequest struct {
	Email    string `json:"email" validate:"required,email"`
	Password string `json:"password" validate:"required"`
}

// LoginResponse represents the admin login response
type LoginResponse struct {
	Token string              `json:"token"`
	Admin AdminUserResponse   `json:"admin"`
}

// AdminUserResponse represents an admin user in API responses
type AdminUserResponse struct {
	ID        uint              `json:"id"`
	Email     string            `json:"email"`
	FirstName string            `json:"first_name"`
	LastName  string            `json:"last_name"`
	Role      models.AdminRole  `json:"role"`
	IsActive  bool              `json:"is_active"`
	LastLogin *string           `json:"last_login,omitempty"`
	CreatedAt string            `json:"created_at"`
}

// NewAdminUserResponse creates an AdminUserResponse from an AdminUser model
func NewAdminUserResponse(admin *models.AdminUser) AdminUserResponse {
	resp := AdminUserResponse{
		ID:        admin.ID,
		Email:     admin.Email,
		FirstName: admin.FirstName,
		LastName:  admin.LastName,
		Role:      admin.Role,
		IsActive:  admin.IsActive,
		CreatedAt: admin.CreatedAt.Format("2006-01-02T15:04:05Z"),
	}
	if admin.LastLogin != nil {
		lastLogin := admin.LastLogin.Format("2006-01-02T15:04:05Z")
		resp.LastLogin = &lastLogin
	}
	return resp
}

// Login handles POST /api/admin/auth/login
func (h *AdminAuthHandler) Login(c echo.Context) error {
	var req LoginRequest
	if err := c.Bind(&req); err != nil {
		return c.JSON(http.StatusBadRequest, map[string]interface{}{"error": "Invalid request body"})
	}
	if err := c.Validate(&req); err != nil {
		return err
	}

	// Find admin by email
	admin, err := h.adminRepo.FindByEmail(req.Email)
	if err != nil {
		return c.JSON(http.StatusUnauthorized, map[string]interface{}{"error": "Invalid email or password"})
	}

	// Check password
	if !admin.CheckPassword(req.Password) {
		return c.JSON(http.StatusUnauthorized, map[string]interface{}{"error": "Invalid email or password"})
	}

	// Check if admin is active
	if !admin.IsActive {
		return c.JSON(http.StatusUnauthorized, map[string]interface{}{"error": "Account is disabled"})
	}

	// Generate JWT token
	token, err := middleware.GenerateAdminToken(admin, h.cfg)
	if err != nil {
		return c.JSON(http.StatusInternalServerError, map[string]interface{}{"error": "Failed to generate token"})
	}

	// Update last login
	_ = h.adminRepo.UpdateLastLogin(admin.ID)

	// Refresh admin data after updating last login
	admin, err = h.adminRepo.FindByID(admin.ID)
	if err != nil {
		return c.JSON(http.StatusInternalServerError, map[string]interface{}{"error": "Failed to refresh admin data"})
	}

	return c.JSON(http.StatusOK, LoginResponse{
		Token: token,
		Admin: NewAdminUserResponse(admin),
	})
}

// Logout handles POST /api/admin/auth/logout
// Note: JWT tokens are stateless, so logout is handled client-side by removing the token
func (h *AdminAuthHandler) Logout(c echo.Context) error {
	return c.JSON(http.StatusOK, map[string]interface{}{"message": "Logged out successfully"})
}

// Me handles GET /api/admin/auth/me
func (h *AdminAuthHandler) Me(c echo.Context) error {
	admin := c.Get(middleware.AdminUserKey).(*models.AdminUser)
	return c.JSON(http.StatusOK, NewAdminUserResponse(admin))
}

// RefreshToken handles POST /api/admin/auth/refresh
func (h *AdminAuthHandler) RefreshToken(c echo.Context) error {
	admin := c.Get(middleware.AdminUserKey).(*models.AdminUser)

	// Generate new token
	token, err := middleware.GenerateAdminToken(admin, h.cfg)
	if err != nil {
		return c.JSON(http.StatusInternalServerError, map[string]interface{}{"error": "Failed to generate token"})
	}

	return c.JSON(http.StatusOK, map[string]interface{}{"token": token})
}
