package handler

import (
	"context"
	"net/http"

	"eslogad-be/internal/contract"

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

type MasterService interface {
	CreateLabel(ctx context.Context, req *contract.CreateLabelRequest) (*contract.LabelResponse, error)
	UpdateLabel(ctx context.Context, id uuid.UUID, req *contract.UpdateLabelRequest) (*contract.LabelResponse, error)
	DeleteLabel(ctx context.Context, id uuid.UUID) error
	ListLabels(ctx context.Context) (*contract.ListLabelsResponse, error)

	CreatePriority(ctx context.Context, req *contract.CreatePriorityRequest) (*contract.PriorityResponse, error)
	UpdatePriority(ctx context.Context, id uuid.UUID, req *contract.UpdatePriorityRequest) (*contract.PriorityResponse, error)
	DeletePriority(ctx context.Context, id uuid.UUID) error
	ListPriorities(ctx context.Context) (*contract.ListPrioritiesResponse, error)

	CreateInstitution(ctx context.Context, req *contract.CreateInstitutionRequest) (*contract.InstitutionResponse, error)
	UpdateInstitution(ctx context.Context, id uuid.UUID, req *contract.UpdateInstitutionRequest) (*contract.InstitutionResponse, error)
	DeleteInstitution(ctx context.Context, id uuid.UUID) error
	ListInstitutions(ctx context.Context, req *contract.ListInstitutionsRequest) (*contract.ListInstitutionsResponse, error)

	CreateDispositionAction(ctx context.Context, req *contract.CreateDispositionActionRequest) (*contract.DispositionActionResponse, error)
	UpdateDispositionAction(ctx context.Context, id uuid.UUID, req *contract.UpdateDispositionActionRequest) (*contract.DispositionActionResponse, error)
	DeleteDispositionAction(ctx context.Context, id uuid.UUID) error
	ListDispositionActions(ctx context.Context) (*contract.ListDispositionActionsResponse, error)
}

type MasterHandler struct{ svc MasterService }

func NewMasterHandler(svc MasterService) *MasterHandler { return &MasterHandler{svc: svc} }

func (h *MasterHandler) CreateLabel(c *gin.Context) {
	var req contract.CreateLabelRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid body", Code: 400})
		return
	}
	resp, err := h.svc.CreateLabel(c.Request.Context(), &req)
	if err != nil {
		c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: 500})
		return
	}
	c.JSON(http.StatusCreated, contract.BuildSuccessResponse(resp))
}

func (h *MasterHandler) UpdateLabel(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(400, &contract.ErrorResponse{Error: "invalid id", Code: 400})
		return
	}
	var req contract.UpdateLabelRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(400, &contract.ErrorResponse{Error: "invalid body", Code: 400})
		return
	}
	resp, err := h.svc.UpdateLabel(c.Request.Context(), id, &req)
	if err != nil {
		c.JSON(500, &contract.ErrorResponse{Error: err.Error(), Code: 500})
		return
	}
	c.JSON(200, contract.BuildSuccessResponse(resp))
}
func (h *MasterHandler) DeleteLabel(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(400, &contract.ErrorResponse{Error: "invalid id", Code: 400})
		return
	}
	if err := h.svc.DeleteLabel(c.Request.Context(), id); err != nil {
		c.JSON(500, &contract.ErrorResponse{Error: err.Error(), Code: 500})
		return
	}
	c.JSON(200, &contract.SuccessResponse{Message: "deleted"})
}
func (h *MasterHandler) ListLabels(c *gin.Context) {
	resp, err := h.svc.ListLabels(c.Request.Context())
	if err != nil {
		c.JSON(500, &contract.ErrorResponse{Error: err.Error(), Code: 500})
		return
	}
	c.JSON(200, contract.BuildSuccessResponse(resp))
}

// Priorities
func (h *MasterHandler) CreatePriority(c *gin.Context) {
	var req contract.CreatePriorityRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(400, &contract.ErrorResponse{Error: "invalid body", Code: 400})
		return
	}
	resp, err := h.svc.CreatePriority(c.Request.Context(), &req)
	if err != nil {
		c.JSON(500, &contract.ErrorResponse{Error: err.Error(), Code: 500})
		return
	}
	c.JSON(201, contract.BuildSuccessResponse(resp))
}
func (h *MasterHandler) UpdatePriority(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(400, &contract.ErrorResponse{Error: "invalid id", Code: 400})
		return
	}
	var req contract.UpdatePriorityRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(400, &contract.ErrorResponse{Error: "invalid body", Code: 400})
		return
	}
	resp, err := h.svc.UpdatePriority(c.Request.Context(), id, &req)
	if err != nil {
		c.JSON(500, &contract.ErrorResponse{Error: err.Error(), Code: 500})
		return
	}
	c.JSON(200, contract.BuildSuccessResponse(resp))
}
func (h *MasterHandler) DeletePriority(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(400, &contract.ErrorResponse{Error: "invalid id", Code: 400})
		return
	}
	if err := h.svc.DeletePriority(c.Request.Context(), id); err != nil {
		c.JSON(500, &contract.ErrorResponse{Error: err.Error(), Code: 500})
		return
	}
	c.JSON(200, &contract.SuccessResponse{Message: "deleted"})
}
func (h *MasterHandler) ListPriorities(c *gin.Context) {
	resp, err := h.svc.ListPriorities(c.Request.Context())
	if err != nil {
		c.JSON(500, &contract.ErrorResponse{Error: err.Error(), Code: 500})
		return
	}
	c.JSON(200, contract.BuildSuccessResponse(resp))
}

// Institutions
func (h *MasterHandler) CreateInstitution(c *gin.Context) {
	var req contract.CreateInstitutionRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(400, &contract.ErrorResponse{Error: "invalid body", Code: 400})
		return
	}
	resp, err := h.svc.CreateInstitution(c.Request.Context(), &req)
	if err != nil {
		c.JSON(500, &contract.ErrorResponse{Error: err.Error(), Code: 500})
		return
	}
	c.JSON(201, contract.BuildSuccessResponse(resp))
}

func (h *MasterHandler) UpdateInstitution(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(400, &contract.ErrorResponse{Error: "invalid id", Code: 400})
		return
	}
	var req contract.UpdateInstitutionRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(400, &contract.ErrorResponse{Error: "invalid body", Code: 400})
		return
	}
	resp, err := h.svc.UpdateInstitution(c.Request.Context(), id, &req)
	if err != nil {
		c.JSON(500, &contract.ErrorResponse{Error: err.Error(), Code: 500})
		return
	}
	c.JSON(200, contract.BuildSuccessResponse(resp))
}

func (h *MasterHandler) DeleteInstitution(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(400, &contract.ErrorResponse{Error: "invalid id", Code: 400})
		return
	}
	if err := h.svc.DeleteInstitution(c.Request.Context(), id); err != nil {
		c.JSON(500, &contract.ErrorResponse{Error: err.Error(), Code: 500})
		return
	}
	c.JSON(200, &contract.SuccessResponse{Message: "deleted"})
}

func (h *MasterHandler) ListInstitutions(c *gin.Context) {
	var req contract.ListInstitutionsRequest

	if search := c.Query("search"); search != "" {
		req.Search = &search
	}

	resp, err := h.svc.ListInstitutions(c.Request.Context(), &req)
	if err != nil {
		c.JSON(500, &contract.ErrorResponse{Error: err.Error(), Code: 500})
		return
	}
	c.JSON(200, contract.BuildSuccessResponse(resp))
}

// Disposition Actions
func (h *MasterHandler) CreateDispositionAction(c *gin.Context) {
	var req contract.CreateDispositionActionRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(400, &contract.ErrorResponse{Error: "invalid body", Code: 400})
		return
	}
	resp, err := h.svc.CreateDispositionAction(c.Request.Context(), &req)
	if err != nil {
		c.JSON(500, &contract.ErrorResponse{Error: err.Error(), Code: 500})
		return
	}
	c.JSON(201, contract.BuildSuccessResponse(resp))
}
func (h *MasterHandler) UpdateDispositionAction(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(400, &contract.ErrorResponse{Error: "invalid id", Code: 400})
		return
	}
	var req contract.UpdateDispositionActionRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(400, &contract.ErrorResponse{Error: "invalid body", Code: 400})
		return
	}
	resp, err := h.svc.UpdateDispositionAction(c.Request.Context(), id, &req)
	if err != nil {
		c.JSON(500, &contract.ErrorResponse{Error: err.Error(), Code: 500})
		return
	}
	c.JSON(200, contract.BuildSuccessResponse(resp))
}
func (h *MasterHandler) DeleteDispositionAction(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(400, &contract.ErrorResponse{Error: "invalid id", Code: 400})
		return
	}
	if err := h.svc.DeleteDispositionAction(c.Request.Context(), id); err != nil {
		c.JSON(500, &contract.ErrorResponse{Error: err.Error(), Code: 500})
		return
	}
	c.JSON(200, &contract.SuccessResponse{Message: "deleted"})
}
func (h *MasterHandler) ListDispositionActions(c *gin.Context) {
	resp, err := h.svc.ListDispositionActions(c.Request.Context())
	if err != nil {
		c.JSON(500, &contract.ErrorResponse{Error: err.Error(), Code: 500})
		return
	}
	c.JSON(200, contract.BuildSuccessResponse(resp))
}
