package controller

import (
	"math"
	"strconv"

	"gitlab.com/mbugroup/lti-api.git/internal/modules/production/project-flock-kandangs/dto"
	service "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project-flock-kandangs/services"
	validation "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project-flock-kandangs/validations"
	"gitlab.com/mbugroup/lti-api.git/internal/response"

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

type ProjectFlockKandangController struct {
	ProjectFlockKandangService service.ProjectFlockKandangService
}

func NewProjectFlockKandangController(projectFlockKandangService service.ProjectFlockKandangService) *ProjectFlockKandangController {
	return &ProjectFlockKandangController{
		ProjectFlockKandangService: projectFlockKandangService,
	}
}

func (u *ProjectFlockKandangController) GetAll(c *fiber.Ctx) error {
	query := &validation.Query{
		Page:            c.QueryInt("page", 1),
		Limit:           c.QueryInt("limit", 10),
		Search:          c.Query("search", ""),
		NameWithPeriode: c.QueryBool("name_with_periode", false),
		ProjectFlockId:  uint(c.QueryInt("project_flock_id", 0)),
		KandangId:       uint(c.QueryInt("kandang_id", 0)),
		Category:        c.Query("category", ""),
		AreaId:          uint(c.QueryInt("area_id", 0)),
		LocationId:      uint(c.QueryInt("location_id", 0)),
		SortBy:          c.Query("sort_by", ""),
		SortOrder:       c.Query("sort_order", ""),
		StepName:        c.Query("step_name", ""),
	}

	if query.Page < 1 || query.Limit < 1 {
		return fiber.NewError(fiber.StatusBadRequest, "page and limit must be greater than 0")
	}

	if query.NameWithPeriode {
		results, totalResults, err := u.ProjectFlockKandangService.GetAllNameWithPeriode(c, query)
		if err != nil {
			return err
		}

		data := make([]dto.ProjectFlockKandangNameWithPeriodDTO, 0, len(results))
		for _, result := range results {
			data = append(data, dto.ToProjectFlockKandangNameWithPeriodDTOValues(result.Id, result.KandangName, result.Period))
		}

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

	results, totalResults, err := u.ProjectFlockKandangService.GetAll(c, query)
	if err != nil {
		return err
	}

	data := make([]dto.ProjectFlockKandangListDTO, 0, len(results))
	for _, result := range results {
		data = append(data, dto.ToProjectFlockKandangListDTO(result))
	}

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

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

	result, availableQtys, productWarehouses, err := u.ProjectFlockKandangService.GetOne(c, uint(id))
	if err != nil {
		return err
	}

	return c.Status(fiber.StatusOK).
		JSON(response.Success{
			Code:    fiber.StatusOK,
			Status:  "success",
			Message: "Get projectFlockKandang successfully",
			Data:    dto.ToProjectFlockKandangDetailDTOWithAvailableQty(*result, availableQtys, productWarehouses),
		})
}

func (u *ProjectFlockKandangController) Closing(c *fiber.Ctx) error {
	id, err := strconv.Atoi(c.Params("id"))
	if err != nil || id <= 0 {
		return fiber.NewError(fiber.StatusBadRequest, "Invalid Id")
	}

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

	result, err := u.ProjectFlockKandangService.Closing(c, uint(id), req)
	if err != nil {
		return err
	}

	detail, availableQtys, productWarehouses, err := u.ProjectFlockKandangService.GetOne(c, result.Id)
	if err != nil {
		return err
	}

	detailDTO := dto.ToProjectFlockKandangDetailDTOWithAvailableQty(*detail, availableQtys, productWarehouses)

	return c.Status(fiber.StatusOK).
		JSON(response.Success{
			Code:    fiber.StatusOK,
			Status:  "success",
			Message: "Status closing kandang diperbarui",
			Data: fiber.Map{
				"detail":   detailDTO,
				"approval": detailDTO.Approval,
			},
		})
}

func (u *ProjectFlockKandangController) CheckClosing(c *fiber.Ctx) error {
	id, err := strconv.Atoi(c.Params("id"))
	if err != nil || id <= 0 {
		return fiber.NewError(fiber.StatusBadRequest, "Invalid Id")
	}

	result, err := u.ProjectFlockKandangService.CheckClosing(c, uint(id))
	if err != nil {
		return err
	}

	return c.Status(fiber.StatusOK).JSON(response.Success{
		Code:    fiber.StatusOK,
		Status:  "success",
		Message: "Cek persyaratan closing kandang",
		Data:    result,
	})
}
