<?php

declare(strict_types=1);

namespace ImovelZapAi\Billing\Application\Actions;

use ImovelZapAi\Billing\Application\Services\CouponCalculator;
use ImovelZapAi\Billing\Domain\Enums\BillingCycle;
use ImovelZapAi\Billing\Infrastructure\Persistence\Eloquent\BillingCouponRedemptionModel;
use ImovelZapAi\Organizations\Infrastructure\Persistence\Eloquent\OrganizationSubscriptionModel;

final class ApplyCouponAction
{
    public function __construct(
        private readonly CouponCalculator $coupons,
    ) {}

    /**
     * @return array{discount_cents: int, amount_cents: int, coupon_code: string}
     */
    public function execute(string $tenantId, string $couponCode): array
    {
        $subscription = OrganizationSubscriptionModel::query()
            ->with('plan')
            ->where('tenant_id', $tenantId)
            ->firstOrFail();

        $plan = $subscription->plan;
        $cycle = BillingCycle::tryFrom((string) ($subscription->billing_cycle ?? 'monthly'))
            ?? BillingCycle::Monthly;

        $coupon = $this->coupons->findValid($couponCode);
        $this->coupons->assertApplicable($coupon, $plan);

        $discount = $this->coupons->discountCents($coupon, $plan, $cycle);
        $amount = $this->coupons->amountAfterDiscount($plan, $cycle, $coupon);

        $subscription->forceFill(['coupon_code' => $coupon->code])->save();

        BillingCouponRedemptionModel::query()->updateOrCreate(
            [
                'billing_coupon_id' => $coupon->id,
                'tenant_id' => $tenantId,
            ],
            [
                'organization_subscription_id' => $subscription->id,
                'discount_cents' => $discount,
            ],
        );

        return [
            'discount_cents' => $discount,
            'amount_cents' => $amount,
            'coupon_code' => (string) $coupon->code,
        ];
    }
}
