package validation

import (
	"errors"
	"mime/multipart"
	"strings"

	"gitlab.com/mbugroup/lti-api.git/internal/utils"
	approvalutils "gitlab.com/mbugroup/lti-api.git/internal/utils/approvals"
)

type Create struct {
	PoNumber         string                  `form:"po_number" json:"po_number" validate:"omitempty,max=50"`
	TransactionDate  string                  `form:"transaction_date" json:"transaction_date" validate:"required,datetime=2006-01-02"`
	Category         string                  `form:"category" json:"category" validate:"required,oneof=BOP NON-BOP"`
	SupplierID       uint64                  `form:"supplier_id" json:"supplier_id" validate:"required,gt=0"`
	LocationID       uint64                  `form:"location_id" json:"location_id" validate:"required,gt=0"`
	Documents        []*multipart.FileHeader `form:"documents" json:"documents" validate:"omitempty,dive"`
	ExpenseNonstocks []ExpenseNonstock       `form:"expense_nonstocks" json:"expense_nonstocks" validate:"required,min=1,dive"`
}

type ExpenseNonstock struct {
	KandangID *uint64    `form:"kandang_id" json:"kandang_id" validate:"omitempty"`
	CostItems []CostItem `form:"cost_items" json:"cost_items" validate:"required,min=1,dive"`
}

type CostItem struct {
	NonstockID uint64  `form:"nonstock_id" json:"nonstock_id" validate:"required,gt=0"`
	Quantity   float64 `form:"quantity" json:"quantity" validate:"required,gt=0"`
	Price      float64 `form:"price" json:"price" validate:"required,gt=0"`
	Notes      string  `form:"notes" json:"notes" validate:"omitempty,max=500"`
}

type Update struct {
	TransactionDate  *string                 `form:"transaction_date" json:"transaction_date" validate:"omitempty,datetime=2006-01-02"`
	Category         *string                 `form:"category" json:"category" validate:"omitempty,oneof=BOP NON-BOP"`
	SupplierID       *uint64                 `form:"supplier_id" json:"supplier_id" validate:"omitempty,gt=0"`
	LocationID       *uint64                 `form:"location_id" json:"location_id" validate:"omitempty,gt=0"`
	Notes            *string                 `form:"notes" json:"notes" validate:"omitempty,max=500"`
	Documents        []*multipart.FileHeader `form:"documents" json:"documents" validate:"omitempty,dive"`
	ExpenseNonstocks *[]ExpenseNonstock      `form:"expense_nonstocks" json:"expense_nonstocks" validate:"omitempty,min=1,dive"`
}

type Query struct {
	Page                  int    `query:"page" validate:"omitempty,number,min=1,gt=0"`
	Limit                 int    `query:"limit" validate:"omitempty,number,min=1,max=100,gt=0"`
	Search                string `query:"search" validate:"omitempty,max=100"`
	TransactionDate       string `query:"transaction_date" validate:"omitempty,datetime=2006-01-02"`
	RealizationDate       string `query:"realization_date" validate:"omitempty,datetime=2006-01-02"`
	LocationID            uint64 `query:"location_id" validate:"omitempty,gt=0"`
	VendorID              uint64 `query:"vendor_id" validate:"omitempty,gt=0"`
	Category              string `query:"category" validate:"omitempty,oneof=BOP NON-BOP"`
	ApprovalStatus        string `query:"approval_status" validate:"omitempty,max=100"`
	RealizationStatus     string `query:"realization_status" validate:"omitempty,max=100"`
	ProjectFlockID        uint64 `query:"project_flock_id" validate:"omitempty,gt=0"`
	ProjectFlockKandangID uint64 `query:"project_flock_kandang_id" validate:"omitempty,gt=0"`
}

type CreateRealization struct {
	RealizationDate string                  `form:"realization_date" json:"realization_date" validate:"required,datetime=2006-01-02"`
	Documents       []*multipart.FileHeader `form:"documents" json:"documents" validate:"omitempty,dive"`
	Realizations    []RealizationItem       `form:"realizations" json:"realizations" validate:"required,min=1,dive"`
}

type UpdateRealization struct {
	RealizationDate *string                 `form:"realization_date" json:"realization_date" validate:"omitempty,datetime=2006-01-02"`
	Documents       []*multipart.FileHeader `form:"documents" json:"documents" validate:"omitempty,dive"`
	Realizations    *[]RealizationItem      `form:"realizations" json:"realizations" validate:"omitempty,min=1,dive"`
}

type RealizationItem struct {
	ExpenseNonstockID uint64  `form:"expense_nonstock_id" json:"expense_nonstock_id" validate:"required,gt=0"`
	Qty               float64 `form:"qty" json:"qty" validate:"required,gt=0"`
	Price             float64 `form:"price" json:"price" validate:"required,gt=0"`
	Notes             *string `form:"notes" json:"notes" validate:"omitempty,max=500"`
}

type ApprovalRequest struct {
	Action        string  `json:"action" form:"action" validate:"required,oneof=APPROVED REJECTED"`
	ApprovableIds []uint  `json:"approvable_ids" validate:"required,min=1,dive,gt=0"`
	Notes         *string `json:"notes" form:"notes"`
}

type BulkApprovalRequest struct {
	ApprovableIds []uint  `json:"approvable_ids" validate:"required,min=1,dive,gt=0"`
	Status        string  `json:"status" validate:"required,max=100"`
	Date          string  `json:"date,omitempty" validate:"omitempty,datetime=2006-01-02"`
	Notes         *string `json:"notes,omitempty" validate:"omitempty,max=500"`
}

func (r *BulkApprovalRequest) ResolveTarget() (approvalutils.ApprovalStep, error) {
	status := strings.ToUpper(strings.ReplaceAll(strings.TrimSpace(r.Status), " ", "_"))

	switch status {
	case "HEAD_AREA", "APPROVAL_HEAD_AREA":
		return utils.ExpenseStepHeadArea, nil
	case "UNIT_VICE_PRESIDENT", "APPROVAL_UNIT_VICE_PRESIDENT", "BUSINESS_UNIT_VICE_PRESIDENT", "APPROVAL_BUSINESS_UNIT_VICE_PRESIDENT":
		return utils.ExpenseStepUnitVicePresident, nil
	case "FINANCE", "APPROVAL_FINANCE":
		return utils.ExpenseStepFinance, nil
	case "REALISASI":
		return utils.ExpenseStepRealisasi, nil
	default:
		return 0, errors.New("status must be one of HEAD_AREA, UNIT_VICE_PRESIDENT, FINANCE, or REALISASI")
	}
}

func (r *BulkApprovalRequest) RequiresDate(target approvalutils.ApprovalStep) bool {
	return target == utils.ExpenseStepRealisasi
}
