<?php

declare(strict_types=1);

namespace Database\Factories;

use App\Models\Company;
use App\Models\Plan;
use App\Models\Subscription;
use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends Factory<Subscription>
 */
class SubscriptionFactory extends Factory
{
    protected $model = Subscription::class;

    public function definition(): array
    {
        return [
            'company_id' => Company::factory(),
            'plan_id' => Plan::factory(),
            'billing_cycle' => Subscription::BILLING_MONTHLY,
            'starts_at' => now()->subMonth(),
            'ends_at' => now()->addMonth(),
            'status' => Subscription::STATUS_ACTIVE,
            'trial_ends_at' => null,
            'grace_period_ends_at' => null,
            'amount_paid' => $this->faker->randomElement([50000, 100000, 200000]),
            'payment_reference' => 'REF-'.$this->faker->unique()->numberBetween(10000, 99999),
            'custom_limits' => null,
            'is_active' => true,
            'canceled_at' => null,
            'cancellation_reason' => null,
            'canceled_by_user_id' => null,
            'notes' => null,
        ];
    }

    /**
     * Active subscription.
     */
    public function active(): static
    {
        return $this->state(fn (array $attributes) => [
            'status' => Subscription::STATUS_ACTIVE,
            'is_active' => true,
        ]);
    }

    /**
     * Trial subscription.
     */
    public function trial(): static
    {
        return $this->state(fn (array $attributes) => [
            'status' => Subscription::STATUS_TRIAL,
            'trial_ends_at' => now()->addDays(14),
            'ends_at' => now()->addDays(14),
            'amount_paid' => 0,
            'is_active' => true,
        ]);
    }

    /**
     * Grace period subscription.
     */
    public function grace(): static
    {
        return $this->state(fn (array $attributes) => [
            'status' => Subscription::STATUS_GRACE,
            'ends_at' => now()->subDay(),
            'grace_period_ends_at' => now()->addDays(7),
            'is_active' => true,
        ]);
    }

    /**
     * Expired subscription.
     */
    public function expired(): static
    {
        return $this->state(fn (array $attributes) => [
            'status' => Subscription::STATUS_EXPIRED,
            'ends_at' => now()->subWeek(),
            'grace_period_ends_at' => now()->subDay(),
            'is_active' => false,
        ]);
    }

    /**
     * Canceled subscription.
     */
    public function canceled(): static
    {
        return $this->state(fn (array $attributes) => [
            'status' => Subscription::STATUS_CANCELED,
            'canceled_at' => now(),
            'cancellation_reason' => 'User requested cancellation',
            'is_active' => false,
        ]);
    }

    /**
     * Suspended subscription.
     */
    public function suspended(): static
    {
        return $this->state(fn (array $attributes) => [
            'status' => Subscription::STATUS_SUSPENDED,
            'is_active' => false,
            'notes' => 'Suspended due to payment issues',
        ]);
    }

    /**
     * Monthly billing cycle.
     */
    public function monthly(): static
    {
        return $this->state(fn (array $attributes) => [
            'billing_cycle' => Subscription::BILLING_MONTHLY,
        ]);
    }

    /**
     * Annual billing cycle.
     */
    public function annual(): static
    {
        return $this->state(fn (array $attributes) => [
            'billing_cycle' => Subscription::BILLING_ANNUAL,
            'ends_at' => now()->addYear(),
        ]);
    }

    /**
     * Quarterly billing cycle.
     */
    public function quarterly(): static
    {
        return $this->state(fn (array $attributes) => [
            'billing_cycle' => Subscription::BILLING_QUARTERLY,
            'ends_at' => now()->addMonths(3),
        ]);
    }

    /**
     * With custom limits override.
     */
    public function withCustomLimits(array $limits): static
    {
        return $this->state(fn (array $attributes) => [
            'custom_limits' => $limits,
        ]);
    }
}
