package handler

import (
	"apskel-pos-be/internal/contract"
	"apskel-pos-be/internal/util"
	"apskel-pos-be/internal/validator"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

type ChartOfAccountHandler struct {
	service   contract.ChartOfAccountContract
	validator validator.ChartOfAccountValidator
}

func NewChartOfAccountHandler(service contract.ChartOfAccountContract, validator validator.ChartOfAccountValidator) *ChartOfAccountHandler {
	return &ChartOfAccountHandler{
		service:   service,
		validator: validator,
	}
}

func (h *ChartOfAccountHandler) CreateChartOfAccount(c *gin.Context) {
	var req contract.CreateChartOfAccountRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{{Cause: err.Error()}}), "ChartOfAccountHandler")
		return
	}

	response, err := h.service.CreateChartOfAccount(c, &req)
	if err != nil {
		util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{{Cause: err.Error()}}), "ChartOfAccountHandler")
		return
	}

	util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(response), "ChartOfAccountHandler")
}

func (h *ChartOfAccountHandler) GetChartOfAccountByID(c *gin.Context) {
	idStr := c.Param("id")
	id, err := uuid.Parse(idStr)
	if err != nil {
		util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{{Cause: "Invalid ID format"}}), "ChartOfAccountHandler")
		return
	}

	response, err := h.service.GetChartOfAccountByID(c, id)
	if err != nil {
		util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{{Cause: err.Error()}}), "ChartOfAccountHandler")
		return
	}

	util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(response), "ChartOfAccountHandler")
}

func (h *ChartOfAccountHandler) UpdateChartOfAccount(c *gin.Context) {
	idStr := c.Param("id")
	id, err := uuid.Parse(idStr)
	if err != nil {
		util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{{Cause: "Invalid ID format"}}), "ChartOfAccountHandler")
		return
	}

	var req contract.UpdateChartOfAccountRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{{Cause: err.Error()}}), "ChartOfAccountHandler")
		return
	}

	response, err := h.service.UpdateChartOfAccount(c, id, &req)
	if err != nil {
		util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{{Cause: err.Error()}}), "ChartOfAccountHandler")
		return
	}

	util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(response), "ChartOfAccountHandler")
}

func (h *ChartOfAccountHandler) DeleteChartOfAccount(c *gin.Context) {
	idStr := c.Param("id")
	id, err := uuid.Parse(idStr)
	if err != nil {
		util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{{Cause: "Invalid ID format"}}), "ChartOfAccountHandler")
		return
	}

	err = h.service.DeleteChartOfAccount(c, id)
	if err != nil {
		util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{{Cause: err.Error()}}), "ChartOfAccountHandler")
		return
	}

	util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(gin.H{"message": "Chart of account deleted successfully"}), "ChartOfAccountHandler")
}

func (h *ChartOfAccountHandler) ListChartOfAccounts(c *gin.Context) {
	var req contract.ListChartOfAccountsRequest
	if err := c.ShouldBindQuery(&req); err != nil {
		util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{{Cause: err.Error()}}), "ChartOfAccountHandler")
		return
	}

	response, total, err := h.service.ListChartOfAccounts(c, &req)
	if err != nil {
		util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{{Cause: err.Error()}}), "ChartOfAccountHandler")
		return
	}

	util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(gin.H{
		"data":  response,
		"total": total,
		"page":  req.Page,
		"limit": req.Limit,
	}), "ChartOfAccountHandler")
}

func (h *ChartOfAccountHandler) GetChartOfAccountsByOrganization(c *gin.Context) {
	organizationIDStr := c.Param("organization_id")
	organizationID, err := uuid.Parse(organizationIDStr)
	if err != nil {
		util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{{Cause: "Invalid organization ID format"}}), "ChartOfAccountHandler")
		return
	}

	var outletID *uuid.UUID
	if outletIDStr := c.Query("outlet_id"); outletIDStr != "" {
		if parsedOutletID, err := uuid.Parse(outletIDStr); err == nil {
			outletID = &parsedOutletID
		}
	}

	response, err := h.service.GetChartOfAccountsByOrganization(c, organizationID, outletID)
	if err != nil {
		util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{{Cause: err.Error()}}), "ChartOfAccountHandler")
		return
	}

	util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(response), "ChartOfAccountHandler")
}

func (h *ChartOfAccountHandler) GetChartOfAccountsByType(c *gin.Context) {
	organizationIDStr := c.Param("organization_id")
	organizationID, err := uuid.Parse(organizationIDStr)
	if err != nil {
		util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{{Cause: "Invalid organization ID format"}}), "ChartOfAccountHandler")
		return
	}

	typeIDStr := c.Param("type_id")
	typeID, err := uuid.Parse(typeIDStr)
	if err != nil {
		util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{{Cause: "Invalid type ID format"}}), "ChartOfAccountHandler")
		return
	}

	var outletID *uuid.UUID
	if outletIDStr := c.Query("outlet_id"); outletIDStr != "" {
		if parsedOutletID, err := uuid.Parse(outletIDStr); err == nil {
			outletID = &parsedOutletID
		}
	}

	response, err := h.service.GetChartOfAccountsByType(c, organizationID, typeID, outletID)
	if err != nil {
		util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{{Cause: err.Error()}}), "ChartOfAccountHandler")
		return
	}

	util.HandleResponse(c.Writer, c.Request, contract.BuildSuccessResponse(response), "ChartOfAccountHandler")
}
