package payments

import (
	"context"
	"fmt"

	"github.com/google/uuid"
)

// CanPurchase reports whether an account may open a purchase order on rail, combining the account's
// per-account override with the rail's operational switch (PurchaseGate). It is the operational
// availability layer only — the caller still enforces the security gates (trusted platform, the D36
// email anchor, the VK-iOS spend freeze, the min client version). On a block, reason is localized to
// lang for the user; err is only a store failure.
func (s *Service) CanPurchase(ctx context.Context, accountID uuid.UUID, rail, lang string) (ok bool, reason string, err error) {
	ov, err := s.store.purchaseOverride(ctx, accountID)
	if err != nil {
		return false, "", err
	}
	avail, err := s.store.railAvailability(ctx, rail)
	if err != nil {
		return false, "", err
	}
	ok, reason = PurchaseGate(ov, avail, lang)
	return ok, reason, nil
}

// RailStatuses returns every known rail's operational status for the admin editor, filling a rail
// with no stored row with the fail-open enabled default so the editor always shows one row per rail.
func (s *Service) RailStatuses(ctx context.Context) (map[string]RailAvailability, error) {
	stored, err := s.store.allRailStatus(ctx)
	if err != nil {
		return nil, err
	}
	out := make(map[string]RailAvailability, len(KnownRails))
	for _, rail := range KnownRails {
		if a, ok := stored[rail]; ok {
			out[rail] = a
		} else {
			out[rail] = RailAvailability{Enabled: true}
		}
	}
	return out, nil
}

// SetRailStatus upserts a rail's operational status from the admin editor. It rejects an unknown rail
// key so a typo cannot create a dead row.
func (s *Service) SetRailStatus(ctx context.Context, rail string, a RailAvailability) error {
	if !isKnownRail(rail) {
		return fmt.Errorf("payments: unknown rail %q", rail)
	}
	return s.store.setRailStatus(ctx, rail, a, s.clock())
}

// PurchaseOverrideFor returns an account's purchase override (OverrideDefault when none is set).
func (s *Service) PurchaseOverrideFor(ctx context.Context, accountID uuid.UUID) (PurchaseOverride, error) {
	return s.store.purchaseOverride(ctx, accountID)
}

// SetPurchaseOverride sets or clears an account's purchase override (OverrideDefault deletes the row).
func (s *Service) SetPurchaseOverride(ctx context.Context, accountID uuid.UUID, ov PurchaseOverride) error {
	return s.store.setPurchaseOverride(ctx, accountID, ov, s.clock())
}
