<?php

namespace App\Modules\Admin\Tenancy\Repositories;

use App\Modules\Admin\Tenancy\Models\Subscription;
use App\Modules\Admin\Tenancy\Models\Tenant;
use Closure;
use Illuminate\Support\Collection;

class SubscriptionRepository
{
    public function create(array $data): Subscription
    {
        return Subscription::query()->create($data);
    }

    public function cancelActiveFor(Tenant $tenant): void
    {
        Subscription::query()
            ->where('tenant_id', $tenant->id)
            ->whereIn('status', [
                Subscription::STATUS_TRIAL,
                Subscription::STATUS_ACTIVE,
                Subscription::STATUS_GRACE_PERIOD,
            ])
            ->update([
                'status' => Subscription::STATUS_CANCELLED,
                'ends_at' => now(),
            ]);
    }

    public function activeFor(Tenant $tenant): ?Subscription
    {
        return Subscription::query()
            ->with('plan')
            ->where('tenant_id', $tenant->id)
            ->active()
            ->latest('id')
            ->first();
    }

    public function latestFor(Tenant $tenant): ?Subscription
    {
        return Subscription::query()
            ->where('tenant_id', $tenant->id)
            ->latest('id')
            ->first();
    }

    public function updateModel(Subscription $subscription, array $data): void
    {
        $subscription->update($data);
    }

    public function trialEndedChunked(Closure $each): void
    {
        Subscription::query()
            ->where('status', Subscription::STATUS_TRIAL)
            ->whereNotNull('trial_ends_at')
            ->where('trial_ends_at', '<=', now())
            ->chunkById(100, function (Collection $chunk) use ($each): void {
                $chunk->each($each);
            });
    }

    public function activePaidEndedChunked(Closure $each): void
    {
        Subscription::query()
            ->where('status', Subscription::STATUS_ACTIVE)
            ->whereNotNull('ends_at')
            ->where('ends_at', '<=', now())
            ->chunkById(100, function (Collection $chunk) use ($each): void {
                $chunk->each($each);
            });
    }

    public function graceEndedChunked(Closure $each): void
    {
        Subscription::query()
            ->where('status', Subscription::STATUS_GRACE_PERIOD)
            ->whereNotNull('grace_ends_at')
            ->where('grace_ends_at', '<=', now())
            ->chunkById(100, function (Collection $chunk) use ($each): void {
                $chunk->each($each);
            });
    }

    /**
     * Paid (or trial with end) subscriptions whose period ends in the given window (renewal reminders).
     *
     * @return Collection<int, Subscription>
     */
    public function renewingActiveBetween(\DateTimeInterface $from, \DateTimeInterface $to): Collection
    {
        return Subscription::query()
            ->with(['tenant', 'plan'])
            ->where('status', Subscription::STATUS_ACTIVE)
            ->whereNotNull('ends_at')
            ->whereBetween('ends_at', [$from, $to])
            ->orderBy('ends_at')
            ->get();
    }
}
