package handlers

import (
	"log"
	"fmt"
	"sno/internal/models"
	"sno/internal/service"
	"strconv"

	"github.com/gofiber/fiber/v2"
)

// AdminHandler handles HTTP requests for admin operations.
type AdminHandler struct {
	adminService service.AdminService
	qrService    service.QRService
}

// NewAdminHandler creates a new instance of an admin handler.
func NewAdminHandler(adminSvc service.AdminService, qrSvc service.QRService) *AdminHandler {
	return &AdminHandler{
		adminService: adminSvc,
		qrService:    qrSvc,
	}
}

// GrantStars handles the request to manually grant stars to a user.
// @Summary Grant stars to user
// @Description Manually grants stars to a user (admin only)
// @Tags admin
// @Accept json
// @Produce json
// @Param request body models.GrantStarsRequest true "Grant stars request"
// @Success 200 {object} object{success=bool,message=string}
// @Failure 400 {object} object{success=bool,message=string}
// @Failure 500 {object} object{success=bool,message=string}
// @Router /api/admin/users/grant-stars [post]
// @Security ApiKeyAuth
func (h *AdminHandler) GrantStars(c *fiber.Ctx) error {
	var req models.GrantStarsRequest
	if err := c.BodyParser(&req); err != nil {
		return c.Status(fiber.StatusBadRequest).JSON(Response{
			Success: false,
			Message: "Cannot parse JSON",
		})
	}

	if err := h.adminService.GrantStars(c.Context(), req.UserID, req.Amount); err != nil {
		log.Printf("ERROR: Failed to grant stars: %v", err)
		return c.Status(fiber.StatusInternalServerError).JSON(Response{
			Success: false,
			Message: err.Error(),
		})
	}

	return c.Status(fiber.StatusOK).JSON(Response{
		Success: true,
		Message: "Stars granted successfully",
	})
}

// GenerateQRCodes handles the request to generate unique QR codes.
// @Summary Generate QR codes
// @Description Generates unique QR codes for rewards, quizzes, or shop items (admin/operator only)
// @Tags admin
// @Accept json
// @Produce json
// @Param request body models.GenerateQRCodesRequest true "QR codes generation request"
// @Success 201 {object} object{success=bool,message=string,data=models.GenerateQRCodesResponse}
// @Failure 400 {object} object{success=bool,message=string}
// @Failure 500 {object} object{success=bool,message=string}
// @Router /api/admin/qrcodes [post]
// @Security ApiKeyAuth
func (h *AdminHandler) GenerateQRCodes(c *fiber.Ctx) error {
	var req models.GenerateQRCodesRequest
	if err := c.BodyParser(&req); err != nil {
		return c.Status(fiber.StatusBadRequest).JSON(Response{
			Success: false,
			Message: "Cannot parse JSON",
		})
	}

	// Validate request
	if req.Type == "" {
		return c.Status(fiber.StatusBadRequest).JSON(Response{
			Success: false,
			Message: "Type cannot be empty",
		})
	}

	if req.Value == "" {
		return c.Status(fiber.StatusBadRequest).JSON(Response{
			Success: false,
			Message: "Value cannot be empty",
		})
	}

	if req.Count <= 0 || req.Count > 100 {
		return c.Status(fiber.StatusBadRequest).JSON(Response{
			Success: false,
			Message: "Count must be between 1 and 100",
		})
	}

	// Validate type
	validTypes := map[string]bool{
		"reward": true,
		"quiz":   true,
		"shop":   true,
	}
	if !validTypes[req.Type] {
		return c.Status(fiber.StatusBadRequest).JSON(Response{
			Success: false,
			Message: "Invalid type. Must be 'reward', 'quiz', or 'shop'",
		})
	}

	tokens := make([]string, 0, req.Count)
	for i := 0; i < req.Count; i++ {
		token, err := h.qrService.GenerateUniqueToken(c.Context(), req.Type, req.Value)
		if err != nil {
			log.Printf("ERROR: Failed to generate QR token: %v", err)
			return c.Status(fiber.StatusInternalServerError).JSON(Response{
				Success: false,
				Message: "Failed to generate QR codes",
			})
		}
		tokens = append(tokens, token)
	}

	return c.Status(fiber.StatusCreated).JSON(Response{
		Success: true,
		Message: fmt.Sprintf("%d unique QR codes generated successfully", len(tokens)),
		Data: models.GenerateQRCodesResponse{
			Tokens: tokens,
		},
	})
}

// CreateOperator handles the request to create a new operator
// @Summary Create operator
// @Description Creates a new operator account (admin only)
// @Tags admin
// @Accept json
// @Produce json
// @Param request body models.CreateOperatorRequest true "Create operator request"
// @Success 201 {object} object{success=bool,message=string}
// @Failure 400 {object} object{success=bool,message=string}
// @Failure 500 {object} object{success=bool,message=string}
// @Router /api/admin/operators [post]
// @Security ApiKeyAuth
func (h *AdminHandler) CreateOperator(c *fiber.Ctx) error {
	var req models.CreateOperatorRequest
	if err := c.BodyParser(&req); err != nil {
		return c.Status(fiber.StatusBadRequest).JSON(Response{
			Success: false,
			Message: "Cannot parse JSON",
		})
	}

	// Validate request
	if req.TelegramID == 0 {
		return c.Status(fiber.StatusBadRequest).JSON(Response{
			Success: false,
			Message: "Telegram ID cannot be empty",
		})
	}

	if req.Name == "" {
		return c.Status(fiber.StatusBadRequest).JSON(Response{
			Success: false,
			Message: "Name cannot be empty",
		})
	}

	if err := h.adminService.CreateOperator(c.Context(), req.TelegramID, req.Name); err != nil {
		log.Printf("ERROR: Failed to create operator: %v", err)
		return c.Status(fiber.StatusInternalServerError).JSON(Response{
			Success: false,
			Message: err.Error(),
		})
	}

	return c.Status(fiber.StatusCreated).JSON(Response{
		Success: true,
		Message: "Operator created successfully",
	})
}

// DeleteOperator handles the request to delete an operator
// @Summary Delete operator
// @Description Deletes an operator account (admin only)
// @Tags admin
// @Accept json
// @Produce json
// @Param id path int true "Operator Telegram ID"
// @Success 200 {object} object{success=bool,message=string}
// @Failure 400 {object} object{success=bool,message=string}
// @Failure 500 {object} object{success=bool,message=string}
// @Router /api/admin/operators/{id} [delete]
// @Security ApiKeyAuth
func (h *AdminHandler) DeleteOperator(c *fiber.Ctx) error {
	telegramID, err := strconv.ParseInt(c.Params("id"), 10, 64)
	if err != nil {
		return c.Status(fiber.StatusBadRequest).JSON(Response{
			Success: false,
			Message: "Invalid Telegram ID",
		})
	}

	if err := h.adminService.DeleteOperator(c.Context(), telegramID); err != nil {
		log.Printf("ERROR: Failed to delete operator: %v", err)
		return c.Status(fiber.StatusInternalServerError).JSON(Response{
			Success: false,
			Message: err.Error(),
		})
	}

	return c.Status(fiber.StatusOK).JSON(Response{
		Success: true,
		Message: "Operator deleted successfully",
	})
}

// GetAnalytics handles the request to get analytics data
// @Summary Get analytics data
// @Description Returns analytics data including user statistics, rewards, and quiz performance (admin/operator only)
// @Tags admin
// @Accept json
// @Produce json
// @Success 200 {object} object{success=bool,message=string,data=object}
// @Failure 500 {object} object{success=bool,message=string}
// @Router /api/admin/analytics [get]
// @Security ApiKeyAuth
func (h *AdminHandler) GetAnalytics(c *fiber.Ctx) error {
	analytics, err := h.adminService.GetAnalytics(c.Context())
	if err != nil {
		log.Printf("ERROR: Failed to get analytics: %v", err)
		return c.Status(fiber.StatusInternalServerError).JSON(Response{
			Success: false,
			Message: "Failed to retrieve analytics",
		})
	}

	return c.Status(fiber.StatusOK).JSON(Response{
		Success: true,
		Message: "Analytics retrieved successfully",
		Data:    analytics,
	})
}
