<?php

namespace App\Modules\Admin\Tenancy\Services;

use App\Modules\Admin\Tenancy\Events\TenantSubscriptionAffected;
use App\Modules\Admin\Tenancy\Models\Plan;
use App\Modules\Admin\Tenancy\Models\Subscription;
use App\Modules\Admin\Tenancy\Models\Tenant;
use App\Modules\Admin\Tenancy\Repositories\SubscriptionRepository;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Event;

class SubscriptionService
{
    public function __construct(
        private readonly SubscriptionRepository $repository,
    ) {}

    public function startFor(Tenant $tenant, Plan $plan): Subscription
    {
        $this->repository->cancelActiveFor($tenant);

        $isTrial = $plan->is_trial || $plan->trial_days > 0;
        $now = Carbon::now();

        $subscription = $this->repository->create([
            'tenant_id' => $tenant->id,
            'plan_id' => $plan->id,
            'status' => $isTrial ? Subscription::STATUS_TRIAL : Subscription::STATUS_ACTIVE,
            'starts_at' => $now,
            'ends_at' => $this->paidPeriodEnd($plan, $now),
            'trial_ends_at' => $isTrial && $plan->trial_days > 0
                ? $now->copy()->addDays($plan->trial_days)
                : null,
            'grace_ends_at' => null,
        ]);

        Event::dispatch(new TenantSubscriptionAffected($tenant));

        return $subscription;
    }

    private function paidPeriodEnd(Plan $plan, Carbon $from): ?Carbon
    {
        if ($plan->is_trial || $plan->trial_days > 0) {
            return null;
        }

        return match ($plan->billing_cycle) {
            'monthly' => $from->copy()->addMonth(),
            'yearly' => $from->copy()->addYear(),
            default => null,
        };
    }

    public function activeFor(Tenant $tenant): ?Subscription
    {
        return $this->repository->activeFor($tenant);
    }
}
