<?php

declare(strict_types=1);

namespace App\Services\Billing;

use App\Models\Service;
use App\Models\User;
use Illuminate\Support\Facades\Log;
use Laravel\Cashier\Subscription;

class DunningService
{
    /**
     * Suspend services for subscriptions that are past due beyond the grace period.
     */
    public function suspendOverdueSubscriptions(): int
    {
        $graceDays = config('billing.suspension.days_past_due_to_suspend');
        $cutoff = now()->subDays($graceDays);

        $subscriptions = Subscription::query()
            ->where('stripe_status', 'past_due')
            ->where('updated_at', '<=', $cutoff)
            ->get();

        $count = 0;

        foreach ($subscriptions as $subscription) {
            $this->suspendServicesForSubscription($subscription);
            $count++;
        }

        if ($count > 0) {
            Log::info("Dunning: suspended services for {$count} overdue subscriptions.");
        }

        return $count;
    }

    /**
     * Terminate services for subscriptions that have been suspended too long.
     */
    public function terminateLongSuspendedSubscriptions(): int
    {
        $terminateDays = config('billing.suspension.days_suspended_to_terminate');
        $cutoff = now()->subDays($terminateDays);

        $services = Service::query()
            ->where('status', 'suspended')
            ->where('suspended_at', '<=', $cutoff)
            ->get();

        $count = 0;

        foreach ($services as $service) {
            $service->update([
                'status' => 'terminated',
                'terminated_at' => now(),
                'auto_renew' => false,
            ]);
            $count++;

            Log::info("Dunning: terminated service #{$service->id} for user #{$service->user_id}.");
        }

        return $count;
    }

    /**
     * Suspend all services tied to a specific subscription.
     */
    public function suspendServicesForSubscription(Subscription $subscription): void
    {
        Service::query()
            ->where('subscription_id', $subscription->id)
            ->where('status', 'active')
            ->update([
                'status' => 'suspended',
                'suspended_at' => now(),
            ]);
    }

    /**
     * Reactivate services when a past-due subscription becomes active again.
     */
    public function reactivateServicesForSubscription(Subscription $subscription): void
    {
        Service::query()
            ->where('subscription_id', $subscription->id)
            ->where('status', 'suspended')
            ->update([
                'status' => 'active',
                'suspended_at' => null,
            ]);
    }

    /**
     * Suspend a user's account entirely.
     */
    public function suspendUser(User $user, string $reason = 'overdue'): void
    {
        $user->update(['status' => 'suspended']);

        Log::info("Dunning: suspended user #{$user->id} for reason: {$reason}.");
    }
}
