package iom

import (
	"errors"
	"fmt"
	"system-altrak/internal/domain"
	"system-altrak/internal/dto"
	"system-altrak/internal/middleware"
	"system-altrak/pkg/utils"

	"github.com/gofiber/fiber/v2"
	"gorm.io/gorm"
)

type Handler struct {
	service IOMService
}

func NewHandler(s IOMService) *Handler {
	return &Handler{service: s}
}

func (h *Handler) CreateMemorandum(c *fiber.Ctx) error {
	var req dto.IomRequest
	if err := c.BodyParser(&req); err != nil {
		return utils.ErrorResponse(c, fiber.StatusBadRequest, "Invalid data structure format")
	}

	middleware.SanitizeStruct(&req)

	// Use new detailed validation
	result := utils.ValidateStructDetailed(req)
	if !result.IsValid {
		return utils.ValidationErrorResponse(c, "Intelligence validation failure", result.Errors)
	}

	userID := uint(0)
	if v := c.Locals("user_id"); v != nil {
		userID = v.(uint)
	}

	branchID, _ := c.Locals("current_branch_id").(uint)
	memo := &domain.Memorandum{
		ToDepartment:   req.ToDepartment,
		FromDepartment: req.FromDepartment,
		Subject:        req.Subject,
		Body:           req.Body,
		SignedBy:       req.SignedBy,
		CreatedBy:      &userID,
		BranchID:       branchID,
	}

	if err := h.service.CreateMemorandum(memo); err != nil {
		return utils.InternalErrorResponse(c, err.Error())
	}

	return utils.SuccessResponse(c, "Memorandum intelligence node synchronized successfully", memo)
}

func (h *Handler) GetMemorandum(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)
	memo, err := h.service.GetMemorandumByID(id, branchID, role)
	if err != nil {
		return utils.NotFoundResponse(c, "Memorandum")
	}
	return utils.SuccessResponse(c, "Memorandum data localized successfully", memo)
}

func (h *Handler) ListMemorandums(c *fiber.Ctx) error {
	branchID, _ := c.Locals("current_branch_id").(uint)
	role, _ := c.Locals("role").(string)
	memos, err := h.service.ListMemorandums(branchID, role)
	if err != nil {
		return utils.InternalErrorResponse(c, "Failed to load memorandum registry")
	}
	return utils.SuccessResponse(c, "Memorandum registry retrieved", memos)
}

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, filename, err := h.service.SynthesizePdf(id, branchID, role)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return utils.NotFoundResponse(c, "Memorandum")
		}
		return utils.InternalErrorResponse(c, err.Error())
	}

	c.Set("Content-Type", "application/pdf")
	c.Set("Content-Disposition", fmt.Sprintf("attachment; filename=MEMORANDUM-%s.pdf", filename))
	return c.Send(buf)
}

func (h *Handler) ExportExcel(c *fiber.Ctx) error {
	branchID, _ := c.Locals("current_branch_id").(uint)
	role, _ := c.Locals("role").(string)
	buf, err := h.service.ExportMemorandumsExcel(branchID, role)
	if err != nil {
		return utils.InternalErrorResponse(c, "Failed to compile memorandum excel")
	}

	c.Set("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
	c.Set("Content-Disposition", `attachment; filename="IOM-General.xlsx"`)
	return c.Send(buf)
}

func (h *Handler) DeleteMemorandum(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.DeleteMemorandum(id, branchID, role); err != nil {
		return utils.InternalErrorResponse(c, "Failed to purge memorandum")
	}
	return utils.SuccessResponse(c, "Memorandum purged successfully", nil)
}
