// internal/controllers/category_controller.go
package controllers

import (
	"lost-and-found/internal/models"
	"lost-and-found/internal/services"
	"lost-and-found/internal/utils"
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

type CategoryController struct {
	categoryService *services.CategoryService
}

func NewCategoryController(db *gorm.DB) *CategoryController {
	return &CategoryController{
		categoryService: services.NewCategoryService(db),
	}
}

// GetAllCategories gets all categories
// GET /api/categories
func (c *CategoryController) GetAllCategories(ctx *gin.Context) {
	categories, err := c.categoryService.GetAllCategories()
	if err != nil {
		utils.ErrorResponse(ctx, http.StatusInternalServerError, "Failed to get categories", err.Error())
		return
	}

	utils.SuccessResponse(ctx, http.StatusOK, "Categories retrieved", categories)
}

// GetCategoryByID gets category by ID
// GET /api/categories/:id
func (c *CategoryController) GetCategoryByID(ctx *gin.Context) {
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid category ID", err.Error())
		return
	}

	category, err := c.categoryService.GetCategoryByID(uint(id))
	if err != nil {
		utils.ErrorResponse(ctx, http.StatusNotFound, "Category not found", err.Error())
		return
	}

	utils.SuccessResponse(ctx, http.StatusOK, "Category retrieved", category.ToResponse())
}

// CreateCategory creates a new category (admin only)
// POST /api/categories
func (c *CategoryController) CreateCategory(ctx *gin.Context) {
	adminObj, _ := ctx.Get("user")
	admin := adminObj.(*models.User)

	var req services.CreateCategoryRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid request data", err.Error())
		return
	}

	ipAddress := ctx.ClientIP()
	userAgent := ctx.Request.UserAgent()

	category, err := c.categoryService.CreateCategory(admin.ID, req, ipAddress, userAgent)
	if err != nil {
		utils.ErrorResponse(ctx, http.StatusBadRequest, "Failed to create category", err.Error())
		return
	}

	utils.SuccessResponse(ctx, http.StatusCreated, "Category created", category.ToResponse())
}

// UpdateCategory updates a category (admin only)
// PUT /api/categories/:id
func (c *CategoryController) UpdateCategory(ctx *gin.Context) {
	adminObj, _ := ctx.Get("user")
	admin := adminObj.(*models.User)

	categoryID, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid category ID", err.Error())
		return
	}

	var req services.UpdateCategoryRequest
	if err := ctx.ShouldBindJSON(&req); err != nil {
		utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid request data", err.Error())
		return
	}

	ipAddress := ctx.ClientIP()
	userAgent := ctx.Request.UserAgent()

	category, err := c.categoryService.UpdateCategory(admin.ID, uint(categoryID), req, ipAddress, userAgent)
	if err != nil {
		utils.ErrorResponse(ctx, http.StatusBadRequest, "Failed to update category", err.Error())
		return
	}

	utils.SuccessResponse(ctx, http.StatusOK, "Category updated", category.ToResponse())
}

// DeleteCategory deletes a category (admin only)
// DELETE /api/categories/:id
func (c *CategoryController) DeleteCategory(ctx *gin.Context) {
	adminObj, _ := ctx.Get("user")
	admin := adminObj.(*models.User)

	categoryID, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid category ID", err.Error())
		return
	}

	ipAddress := ctx.ClientIP()
	userAgent := ctx.Request.UserAgent()

	if err := c.categoryService.DeleteCategory(admin.ID, uint(categoryID), ipAddress, userAgent); err != nil {
		utils.ErrorResponse(ctx, http.StatusBadRequest, "Failed to delete category", err.Error())
		return
	}

	utils.SuccessResponse(ctx, http.StatusOK, "Category deleted", nil)
}