<?php

namespace App\Contracts;

use App\Models\PricingTier;

/**
 * PricingModelContract
 *
 * Every pricing model — whether built into core or registered by a module —
 * must implement this interface. The registry resolves the correct handler
 * by key and delegates price calculation and cart behaviour to it.
 *
 * Implementing a new model in a module:
 *
 *   class CreditsModel implements PricingModelContract
 *   {
 *       public function key(): string   { return 'credits'; }
 *       public function label(): string { return 'Credits Bundle'; }
 *       // ... implement remaining methods
 *   }
 *
 *   // In your ModuleServiceProvider::boot():
 *   $this->registerPricingModel(new CreditsModel());
 */
interface PricingModelContract
{
    // -------------------------------------------------------------------------
    // Identity
    // -------------------------------------------------------------------------

    /**
     * Unique string identifier stored in pricing_tiers.pricing_model.
     * Use snake_case (e.g. 'fixed', 'per_seat', 'metered').
     */
    public function key(): string;

    // -------------------------------------------------------------------------
    // Cart / pricing logic
    // -------------------------------------------------------------------------

    /**
     * Calculate the total price for a given quantity.
     * Used by PricingTier::calculatePrice().
     */
    public function calculatePrice(PricingTier $tier, int $quantity): float;

    /**
     * Determine the cart line-item quantity.
     * Fixed = 1; per-seat = seatCount; metered = 1.
     */
    public function cartQty(PricingTier $tier, int $requestedQty): int;

    /**
     * Determine the per-unit price stored on the cart item.
     * For trial items pass $trialAvailable = true to return 0.00.
     */
    public function cartUnitPrice(PricingTier $tier, bool $trialAvailable): float;

    /**
     * Build the human-readable price label shown in the cart/checkout UI.
     *
     * @param string|null $billingCycleLabel e.g. "Monthly" — null for one-time plans.
     */
    public function cartPriceLabel(PricingTier $tier, bool $trialAvailable, ?string $billingCycleLabel): string;

    /**
     * Extra options to merge into the cart item's options array.
     * Return an empty array if there is nothing to add.
     */
    public function extraCartOptions(PricingTier $tier, int $qty): array;

    // -------------------------------------------------------------------------
    // Admin product builder UI metadata
    // -------------------------------------------------------------------------

    /**
     * Full descriptive label for the pricing model dropdown in the admin
     * product builder (e.g. "Fixed Price — flat rate per billing cycle").
     */
    public function adminLabel(): string;

    /**
     * Short label shown in the plan table badge for non-fixed models.
     * Return an empty string to suppress the badge (e.g. for 'fixed').
     */
    public function badgeLabel(): string;

    /**
     * True when per_unit_amount is the primary rate field for this model
     * (replaces the flat price field in the admin builder).
     */
    public function usesPerUnitAmount(): bool;

    /**
     * Label for the per_unit_amount input field in the admin builder.
     * e.g. "Price per Seat", "Price per Unit".
     * Ignored when usesPerUnitAmount() returns false.
     */
    public function perUnitLabel(): string;

    /**
     * Short suffix appended after the amount in the admin plan table.
     * e.g. "/seat", "/unit". Empty string for flat-price models.
     */
    public function perUnitSuffix(): string;

    /**
     * Help text shown below the per_unit_amount field in the admin builder.
     * e.g. "Multiplied by the number of seats at checkout."
     * Ignored when usesPerUnitAmount() returns false.
     */
    public function perUnitHelp(): string;

    // -------------------------------------------------------------------------
    // Frontend subscription-box rendering metadata
    // -------------------------------------------------------------------------

    /**
     * True if $0 should be displayed at checkout and "Usage-based" shown
     * instead of a numeric price (e.g. metered billing).
     */
    public function checkoutDisplayZero(): bool;

    /**
     * Suffix appended after the price on the subscription box.
     *
     * @param float       $perUnitAmount    The tier's per_unit_amount value.
     * @param string|null $billingCycleLabel e.g. "Monthly" — null for one-time.
     *
     * Examples:
     *   fixed:    "/Monthly"
     *   per_seat: "/seat/Monthly"
     *   metered:  "· $0.01/unit"  (replaces the billing cycle label entirely)
     */
    public function checkoutSuffix(float $perUnitAmount, ?string $billingCycleLabel): string;
}
