<?php

declare(strict_types=1);

namespace App\Console\Commands;

use App\Models\Subscription;
use App\Models\User;
use App\Notifications\SubscriptionExpiringNotification;
use Carbon\Carbon;
use Illuminate\Console\Command;

/**
 * Avisa (in-app, campana del panel) a los admins de cada empresa que su prueba o
 * suscripción está por vencer, a T-3 y T-1 días (#166). Antes no había ningún
 * aviso: el cliente se enteraba de que venció cuando ya estaba bloqueado, lo que
 * mataba la conversión del trial y aceleraba el churn.
 *
 * Se programa a diario (bootstrap/app.php). Empareja por FECHA (no por hora), así
 * que dispara una vez por umbral cuando `ends_at`/`grace_period_ends_at` cae en
 * hoy+3 u hoy+1. Sin SMTP → solo canal `database` (ver la notificación).
 */
class NotifyExpiringSubscriptions extends Command
{
    protected $signature = 'subscriptions:notify-expiring';

    protected $description = 'Avisa a los admins de cada empresa (in-app) que su prueba/suscripción vence en 3 o 1 días.';

    /** Días antes del vencimiento en los que se recuerda. */
    private const THRESHOLDS = [3, 1];

    public function handle(): int
    {
        $today = Carbon::today();
        $notified = 0;

        foreach (self::THRESHOLDS as $days) {
            $target = $today->copy()->addDays($days);

            // Prueba/activa: se mide contra ends_at.
            $ending = Subscription::whereIn('status', [Subscription::STATUS_TRIAL, Subscription::STATUS_ACTIVE])
                ->whereDate('ends_at', $target)
                ->get();

            foreach ($ending as $subscription) {
                $context = $subscription->status === Subscription::STATUS_TRIAL
                    ? SubscriptionExpiringNotification::CONTEXT_TRIAL
                    : SubscriptionExpiringNotification::CONTEXT_RENEWAL;
                $notified += $this->notifyCompanyAdmins($subscription, $days, $context);
            }

            // En gracia: se mide contra grace_period_ends_at (último aviso).
            $grace = Subscription::where('status', Subscription::STATUS_GRACE)
                ->whereDate('grace_period_ends_at', $target)
                ->get();

            foreach ($grace as $subscription) {
                $notified += $this->notifyCompanyAdmins($subscription, $days, SubscriptionExpiringNotification::CONTEXT_GRACE);
            }
        }

        $this->info("Avisos de vencimiento enviados: {$notified}.");

        return self::SUCCESS;
    }

    /**
     * Notifica a los admins de la empresa de la suscripción. Devuelve cuántos.
     */
    private function notifyCompanyAdmins(Subscription $subscription, int $daysLeft, string $context): int
    {
        $admins = User::query()
            ->where('company_id', $subscription->company_id)
            ->whereHas('roles', fn ($q) => $q->where('name', 'admin'))
            ->get();

        foreach ($admins as $admin) {
            $admin->notify(new SubscriptionExpiringNotification($subscription, $daysLeft, $context));
        }

        return $admins->count();
    }
}
