package sjr

import (
	"errors"
	"fmt"
	"strings"
	"system-altrak/internal/dto"
	"system-altrak/internal/middleware"
	"system-altrak/pkg/utils"

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

type Handler struct {
	service SJRService
}

func NewHandler(s SJRService) *Handler {
	return &Handler{service: s}
}

func (h *Handler) Create(c *fiber.Ctx) error {
	var req dto.ServiceJobRequestDTO
	if err := c.BodyParser(&req); err != nil {
		return utils.ErrorResponse(c, fiber.StatusBadRequest, "Invalid request format protocol")
	}

	middleware.SanitizeStruct(&req)

	// Use new detailed validation
	result := utils.ValidateStructDetailed(req)
	if !result.IsValid {
		return utils.ValidationErrorResponse(c, "Validation failed", result.Errors)
	}

	userID, _ := c.Locals("user_id").(uint)
	branchID, _ := c.Locals("current_branch_id").(uint)
	auth, err := h.service.CreateAuthorization(&req, userID, branchID)
	if err != nil {
		return utils.InternalErrorResponse(c, err.Error())
	}
	return utils.SuccessResponse(c, "Service Authorization Node synchronized successfully", auth)
}

func (h *Handler) Update(c *fiber.Ctx) error {
	id, err := utils.ParseParamID(c, "id")
	if err != nil {
		return utils.ErrorResponse(c, fiber.StatusBadRequest, "Invalid ID parameter")
	}

	var req dto.ServiceJobRequestDTO
	if err := c.BodyParser(&req); err != nil {
		return utils.ErrorResponse(c, fiber.StatusBadRequest, "Invalid request format protocol")
	}

	middleware.SanitizeStruct(&req)

	result := utils.ValidateStructDetailed(req)
	if !result.IsValid {
		return utils.ValidationErrorResponse(c, "Validation failed", result.Errors)
	}

	branchID, _ := c.Locals("current_branch_id").(uint)
	role, _ := c.Locals("role").(string)
	auth, err := h.service.UpdateAuthorization(id, &req, branchID, role)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return utils.NotFoundResponse(c, "Service Authorization Node")
		}
		return utils.InternalErrorResponse(c, err.Error())
	}
	return utils.SuccessResponse(c, "Service Authorization Node updated successfully", auth)
}

func (h *Handler) GetOne(c *fiber.Ctx) error {
	id, err := utils.ParseParamID(c, "id")
	if err != nil {
		return utils.ErrorResponse(c, fiber.StatusBadRequest, "Invalid ID parameter")
	}
	branchID, _ := c.Locals("current_branch_id").(uint)
	role, _ := c.Locals("role").(string)
	auth, err := h.service.GetAuthorizationByID(id, branchID, role)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return utils.NotFoundResponse(c, "Service Authorization Node")
		}
		return utils.NotFoundResponse(c, "Service Authorization Node")
	}
	return utils.SuccessResponse(c, "Service Authorization Node retrieved successfully", auth)
}

func (h *Handler) List(c *fiber.Ctx) error {
	branchID, _ := c.Locals("current_branch_id").(uint)
	role, _ := c.Locals("role").(string)
	list, err := h.service.ListAuthorizations(branchID, role)
	if err != nil {
		return utils.InternalErrorResponse(c, "Failed to aggregate Service Authorization registry")
	}
	return utils.SuccessResponse(c, "Authorization Matrix Retrieval: Successful", list)
}

func (h *Handler) DownloadPDF(c *fiber.Ctx) error {
	id, err := utils.ParseParamID(c, "id")
	if err != nil {
		return utils.ErrorResponse(c, fiber.StatusBadRequest, "Invalid ID parameter")
	}
	branchID, _ := c.Locals("current_branch_id").(uint)
	role, _ := c.Locals("role").(string)
	buf, ref, err := h.service.SynthesizePDF(id, branchID, role)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return utils.NotFoundResponse(c, "Service Authorization Node")
		}
		return utils.InternalErrorResponse(c, err.Error())
	}
	c.Set("Content-Type", "application/pdf")
	c.Set("Content-Disposition", fmt.Sprintf("attachment; filename=AUTH-%s.pdf", ref))
	return c.Send(buf)
}

func (h *Handler) DownloadExcel(c *fiber.Ctx) error {
	branchID, _ := c.Locals("current_branch_id").(uint)
	role, _ := c.Locals("role").(string)

	requestType := strings.ToLower(strings.TrimSpace(c.Query("type", "")))
	if requestType != "" && requestType != "repair" && requestType != "calibration" {
		return utils.ErrorResponse(c, fiber.StatusBadRequest, "Invalid export type. Allowed values: repair, calibration")
	}

	buf, err := h.service.ExportExcel(branchID, role, requestType)
	if err != nil {
		return utils.InternalErrorResponse(c, err.Error())
	}

	c.Set("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
	c.Set("Content-Disposition", "attachment; filename=Service-Authorization-Registry.xlsx")
	return c.Send(buf)
}
func (h *Handler) Delete(c *fiber.Ctx) error {
	id, err := utils.ParseParamID(c, "id")
	if err != nil {
		return utils.ErrorResponse(c, fiber.StatusBadRequest, "Invalid ID parameter")
	}
	branchID, _ := c.Locals("current_branch_id").(uint)
	role, _ := c.Locals("role").(string)
	if err := h.service.Delete(id, branchID, role); err != nil {
		return utils.InternalErrorResponse(c, err.Error())
	}
	return utils.SuccessResponse(c, "Service Authorization Node expunged successfully", nil)
}
