package validator

import (
	"apskel-pos-be/internal/constants"
	"apskel-pos-be/internal/contract"
	"fmt"
	"strings"

	"github.com/go-playground/validator/v10"
	"github.com/google/uuid"
)

type TableValidator struct {
	validate *validator.Validate
}

func NewTableValidator() *TableValidator {
	return &TableValidator{
		validate: validator.New(),
	}
}

func (v *TableValidator) ValidateCreateTableRequest(req contract.CreateTableRequest) error {
	if err := v.validate.Struct(req); err != nil {
		return formatValidationError(err)
	}

	// Additional custom validations
	if req.OutletID == uuid.Nil {
		return fmt.Errorf("outlet_id is required")
	}

	if strings.TrimSpace(req.TableName) == "" {
		return fmt.Errorf("table_name cannot be empty")
	}

	if req.Capacity < 1 || req.Capacity > 20 {
		return fmt.Errorf("capacity must be between 1 and 20")
	}

	return nil
}

func (v *TableValidator) ValidateUpdateTableRequest(req contract.UpdateTableRequest) error {
	if err := v.validate.Struct(req); err != nil {
		return formatValidationError(err)
	}

	// Additional custom validations
	if req.TableName != nil && strings.TrimSpace(*req.TableName) == "" {
		return fmt.Errorf("table_name cannot be empty")
	}

	if req.Capacity != nil && (*req.Capacity < 1 || *req.Capacity > 20) {
		return fmt.Errorf("capacity must be between 1 and 20")
	}

	if req.Status != nil {
		if !isValidTableStatus(*req.Status) {
			return fmt.Errorf("invalid table status: %s", *req.Status)
		}
	}

	return nil
}

func (v *TableValidator) ValidateOccupyTableRequest(req contract.OccupyTableRequest) error {
	if err := v.validate.Struct(req); err != nil {
		return formatValidationError(err)
	}

	// Additional custom validations
	if req.OrderID == uuid.Nil {
		return fmt.Errorf("order_id is required")
	}

	return nil
}

func (v *TableValidator) ValidateReleaseTableRequest(req contract.ReleaseTableRequest) error {
	if err := v.validate.Struct(req); err != nil {
		return formatValidationError(err)
	}

	// Additional custom validations
	if req.PaymentAmount < 0 {
		return fmt.Errorf("payment_amount cannot be negative")
	}

	return nil
}

func (v *TableValidator) ValidateTableID(id string) error {
	if id == "" {
		return fmt.Errorf("table ID is required")
	}

	if _, err := uuid.Parse(id); err != nil {
		return fmt.Errorf("invalid table ID format")
	}

	return nil
}

func (v *TableValidator) ValidateOutletID(id string) error {
	if id == "" {
		return fmt.Errorf("outlet ID is required")
	}

	if _, err := uuid.Parse(id); err != nil {
		return fmt.Errorf("invalid outlet ID format")
	}

	return nil
}

func (v *TableValidator) ValidateListTablesQuery(query contract.ListTablesQuery) error {
	// Validate pagination
	if query.Page < 1 {
		return fmt.Errorf("page must be greater than 0")
	}

	if query.Limit < 1 || query.Limit > 100 {
		return fmt.Errorf("limit must be between 1 and 100")
	}

	// Validate organization_id if provided
	if query.OrganizationID != "" {
		if _, err := uuid.Parse(query.OrganizationID); err != nil {
			return fmt.Errorf("invalid organization_id format")
		}
	}

	// Validate outlet_id if provided
	if query.OutletID != "" {
		if _, err := uuid.Parse(query.OutletID); err != nil {
			return fmt.Errorf("invalid outlet_id format")
		}
	}

	// Validate status if provided
	if query.Status != "" {
		if !isValidTableStatus(query.Status) {
			return fmt.Errorf("invalid table status: %s", query.Status)
		}
	}

	// Validate is_active if provided
	if query.IsActive != "" {
		if query.IsActive != "true" && query.IsActive != "false" {
			return fmt.Errorf("is_active must be 'true' or 'false'")
		}
	}

	return nil
}

func isValidTableStatus(status string) bool {
	validStatuses := []string{
		string(constants.TableStatusAvailable),
		string(constants.TableStatusOccupied),
		string(constants.TableStatusReserved),
		string(constants.TableStatusCleaning),
		string(constants.TableStatusMaintenance),
	}

	for _, validStatus := range validStatuses {
		if status == validStatus {
			return true
		}
	}
	return false
}
