package controller

import (
	"math"
	"strconv"

	"gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/adjustments/dto"
	service "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/adjustments/services"
	validation "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/adjustments/validations"
	"gitlab.com/mbugroup/lti-api.git/internal/response"

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

type AdjustmentController struct {
	AdjustmentService service.AdjustmentService
}

func NewAdjustmentController(adjustmentService service.AdjustmentService) *AdjustmentController {
	return &AdjustmentController{
		AdjustmentService: adjustmentService,
	}
}

func (u *AdjustmentController) Adjustment(c *fiber.Ctx) error {
	req := new(validation.Create)

	if err := c.BodyParser(req); err != nil {
		return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
	}

	stockLog, err := u.AdjustmentService.Adjustment(c, req)
	if err != nil {
		return err
	}

	adjustmentDTO := dto.ToAdjustmentDetailDTO(stockLog)

	return c.Status(fiber.StatusCreated).
		JSON(response.Success{
			Code:    fiber.StatusCreated,
			Status:  "success",
			Message: "Create adjustment successfully",
			Data:    adjustmentDTO,
		})
}

func (u *AdjustmentController) AdjustmentHistory(c *fiber.Ctx) error {
	query := &validation.Query{
		Page:               c.QueryInt("page", 1),
		Limit:              c.QueryInt("limit", 10),
		ProductID:          uint(c.QueryInt("product_id", 0)),
		WarehouseID:        uint(c.QueryInt("warehouse_id", 0)),
		TransactionType:    c.Query("transaction_type", ""),
		TransactionSubtype: c.Query("transaction_subtype", ""),
		FunctionCode:       c.Query("function_code", ""),
	}

	result, totalResults, err := u.AdjustmentService.AdjustmentHistory(c, query)
	if err != nil {
		return err
	}

	// Convert to DTOs
	adjustmentDTOs := make([]dto.AdjustmentDetailDTO, len(result))
	for i, stockLog := range result {
		adjustmentDTOs[i] = dto.ToAdjustmentDetailDTO(stockLog)
	}

	return c.Status(fiber.StatusOK).
		JSON(response.SuccessWithPaginate[dto.AdjustmentDetailDTO]{
			Code:    fiber.StatusOK,
			Status:  "success",
			Message: "Get adjustment history successfully",
			Meta: response.Meta{
				Page:         query.Page,
				Limit:        query.Limit,
				TotalPages:   int64(math.Ceil(float64(totalResults) / float64(query.Limit))),
				TotalResults: totalResults,
			},
			Data: adjustmentDTOs,
		})
}

func (u *AdjustmentController) GetOne(c *fiber.Ctx) error {
	param := c.Params("id")

	id, err := strconv.Atoi(param)
	if err != nil {
		return fiber.NewError(fiber.StatusBadRequest, "Invalid Id")
	}

	stockLog, err := u.AdjustmentService.GetOne(c, uint(id))
	if err != nil {
		return err
	}
	// Use DTO for response
	return c.Status(fiber.StatusOK).
		JSON(response.Success{
			Code:    fiber.StatusOK,
			Status:  "success",
			Message: "Get adjustment successfully",
			Data:    dto.ToAdjustmentDetailDTO(stockLog),
		})
}

func (u *AdjustmentController) DeleteOne(c *fiber.Ctx) error {
	param := c.Params("id")
	id, err := strconv.Atoi(param)
	if err != nil {
		return fiber.NewError(fiber.StatusBadRequest, "Invalid Id")
	}

	if err := u.AdjustmentService.DeleteOne(c, uint(id)); err != nil {
		return err
	}

	return c.Status(fiber.StatusOK).
		JSON(response.Common{
			Code:    fiber.StatusOK,
			Status:  "success",
			Message: "Delete adjustment successfully",
		})
}
