package service

import (
	"context"
	"errors"
	"strings"

	"gorm.io/gorm"
)

type FifoPendingPolicyInput struct {
	Lane          string
	FlagGroupCode string
	FunctionCode  string
	LegacyTypeKey string
}

type FifoPendingPolicyResult struct {
	AllowPending bool
	RuleSource   string
	Found        bool
}

func ResolveFifoPendingPolicy(ctx context.Context, tx *gorm.DB, input FifoPendingPolicyInput) (*FifoPendingPolicyResult, error) {
	if tx == nil {
		return nil, gorm.ErrInvalidDB
	}

	lane := strings.ToUpper(strings.TrimSpace(input.Lane))
	flagGroupCode := strings.ToUpper(strings.TrimSpace(input.FlagGroupCode))
	functionCode := strings.ToUpper(strings.TrimSpace(input.FunctionCode))
	legacyTypeKey := strings.ToUpper(strings.TrimSpace(input.LegacyTypeKey))
	if lane == "" {
		return &FifoPendingPolicyResult{
			AllowPending: false,
			RuleSource:   "SAFE_DEFAULT_BLOCK",
			Found:        false,
		}, nil
	}

	type overconsumeRuleRow struct {
		Allow bool `gorm:"column:allow_overconsume"`
	}
	var overconsume overconsumeRuleRow
	overconsumeErr := tx.WithContext(ctx).
		Table("fifo_stock_v2_overconsume_rules").
		Select("allow_overconsume").
		Where("is_active = TRUE").
		Where("lane = ?", lane).
		Where("(flag_group_code IS NULL OR flag_group_code = ?)", flagGroupCode).
		Where("(function_code IS NULL OR function_code = ?)", functionCode).
		Order("CASE WHEN flag_group_code IS NULL THEN 1 ELSE 0 END ASC").
		Order("CASE WHEN function_code IS NULL THEN 1 ELSE 0 END ASC").
		Order("priority ASC, id ASC").
		Limit(1).
		Take(&overconsume).Error
	if overconsumeErr == nil {
		return &FifoPendingPolicyResult{
			AllowPending: overconsume.Allow,
			RuleSource:   "OVERCONSUME_RULE",
			Found:        true,
		}, nil
	}
	if !errors.Is(overconsumeErr, gorm.ErrRecordNotFound) {
		return nil, overconsumeErr
	}

	type routeRuleRow struct {
		AllowPendingDefault bool `gorm:"column:allow_pending_default"`
	}
	var routeRule routeRuleRow
	routeQuery := tx.WithContext(ctx).
		Table("fifo_stock_v2_route_rules").
		Select("allow_pending_default").
		Where("is_active = TRUE").
		Where("lane = ?", lane).
		Where("flag_group_code = ?", flagGroupCode)
	if legacyTypeKey != "" {
		routeQuery = routeQuery.Where("legacy_type_key = ?", legacyTypeKey)
	}
	if functionCode != "" {
		routeQuery = routeQuery.Where("function_code = ?", functionCode)
	}
	routeErr := routeQuery.
		Order("id ASC").
		Limit(1).
		Take(&routeRule).Error
	if routeErr == nil {
		return &FifoPendingPolicyResult{
			AllowPending: routeRule.AllowPendingDefault,
			RuleSource:   "ROUTE_RULE_DEFAULT",
			Found:        true,
		}, nil
	}
	if !errors.Is(routeErr, gorm.ErrRecordNotFound) {
		return nil, routeErr
	}

	return &FifoPendingPolicyResult{
		AllowPending: false,
		RuleSource:   "SAFE_DEFAULT_BLOCK",
		Found:        false,
	}, nil
}
