<?php

namespace Database\Factories;

use App\Models\Customer;
use App\Models\Subscription;
use App\Services\Billing\WithdrawalRight;
use Illuminate\Database\Eloquent\Factories\Factory;

class SubscriptionFactory extends Factory
{
    public function definition(): array
    {
        $start = now()->startOfMonth();

        return array_merge(Subscription::snapshotFrom('team'), [
            'customer_id' => Customer::factory(),
            'started_at' => $start,
            'current_period_start' => $start,
            'current_period_end' => $start->copy()->addMonth(),
            // Every contract opened for real gets one (OpenSubscription), so a
            // factory contract without it would behave differently from the
            // thing it stands in for — and every test about the withdrawal
            // window would have to remember to set it.
            'withdrawal_ends_at' => $start->copy()->addDays(WithdrawalRight::WINDOW_DAYS),
            'status' => 'active',
        ]);
    }

    /**
     * The consumer expressly asked for the service to begin at once, and was
     * told they would owe the pro-rata share if they withdrew (FAGG §16).
     *
     * A state rather than the default, because the absence of this consent is
     * what makes a withdrawal refund EVERYTHING — and that is the case a test
     * has to be able to reach without fighting the factory.
     */
    public function startedImmediately(): static
    {
        return $this->state(fn (array $attributes) => [
            'immediate_start_consent_at' => $attributes['started_at'] ?? now(),
        ]);
    }

    public function plan(string $plan, string $term = Subscription::TERM_MONTHLY): static
    {
        return $this->state(function () use ($plan, $term) {
            $start = now()->startOfMonth();

            return array_merge(Subscription::snapshotFrom($plan, $term), [
                'started_at' => $start,
                'current_period_start' => $start,
                'current_period_end' => $term === Subscription::TERM_YEARLY
                    ? $start->copy()->addYear()
                    : $start->copy()->addMonth(),
                'withdrawal_ends_at' => $start->copy()->addDays(WithdrawalRight::WINDOW_DAYS),
            ]);
        });
    }
}
