<?php

namespace App\Console\Commands;

use App\Models\Central\Company;
use App\Models\Tenant\ServiceReminderSent;
use App\Models\Tenant\TireSet;
use App\Services\NotificationDispatcher;
use App\Tenancy\TenantManager;
use Illuminate\Console\Command;
use Illuminate\Support\Carbon;

/**
 * Twice-a-year window reminder for clients to swap seasonal tires.
 *  - Around March 1 (Feb 15 – Mar 15): notify clients with WINTER sets still
 *    in storage (time to swap to summer).
 *  - Around October 1 (Sep 15 – Oct 15): notify clients with SUMMER sets still
 *    in storage (time to swap to winter).
 *
 * Dedup via service_reminders_sent (type='tire_swap', per client+set, 60-day
 * cooldown — effectively once per window).
 */
class SendTireSeasonalRemindersCommand extends Command
{
    protected $signature = 'tires:remind-seasonal
                            {--slug= : Only one tenant by slug}
                            {--force : Send even outside the swap window}
                            {--dry-run : Show candidates without sending}';

    protected $description = 'Send seasonal tire-swap reminders during Feb-Mar / Sep-Oct windows.';

    public function handle(NotificationDispatcher $dispatcher): int
    {
        $window = $this->windowFor(today());
        $force = (bool) $this->option('force');
        $dry = (bool) $this->option('dry-run');

        if (! $window && ! $force) {
            $this->info('Outside swap window. Use --force to run anyway. Today: ' . today()->toDateString());
            return self::SUCCESS;
        }

        $targetSeason = $window['season'] ?? 'winter';   // season of stored sets we want to notify

        $query = Company::query()->where('status', '!=', 'archived');
        if ($slug = $this->option('slug')) $query->where('slug', $slug);
        $companies = $query->get();

        $totalSent = 0;
        $cooldown = today()->subDays(60);

        foreach ($companies as $company) {
            app(TenantManager::class)->setCurrent($company);

            // Sets currently in storage whose season matches the window target.
            $sets = TireSet::with(['client', 'vehicle', 'storage'])
                ->where('season', $targetSeason)
                ->whereHas('storage', fn ($s) => $s->where('status', 'stored'))
                ->get()
                ->filter(fn (TireSet $s) => $s->client && $s->client->status === 'active');

            $sentThisTenant = 0;
            foreach ($sets as $set) {
                $recent = ServiceReminderSent::where('type', 'tire_swap')
                    ->where('client_id', $set->client_id)
                    ->where('sent_at', '>=', $cooldown)
                    ->exists();
                if ($recent) continue;

                if ($dry) {
                    $this->line(sprintf('  - [%s] set #%d %s · client %s · loc %s',
                        $company->slug, $set->id, $set->sizeLabel(),
                        $set->client?->name ?? '—',
                        $set->currentStorage()?->location ?? '—'));
                    continue;
                }

                $ok = $dispatcher->tireSeasonalSwap($set);
                if ($ok) {
                    ServiceReminderSent::create([
                        'company_id' => $company->id,
                        'vehicle_id' => $set->vehicle_id,
                        'client_id' => $set->client_id,
                        'channel' => $set->client?->telegram_chat_id ? 'telegram' : 'email',
                        'type' => 'tire_swap',
                        'sent_at' => now(),
                    ]);
                    $sentThisTenant++;
                }
            }
            $this->info(sprintf('[%s] tire-swap reminders sent: %d', $company->slug, $sentThisTenant));
            $totalSent += $sentThisTenant;
        }

        $this->info("Total tire-swap reminders sent: {$totalSent}" . ($dry ? ' (dry run)' : ''));
        return self::SUCCESS;
    }

    /** Returns ['season' => 'winter'|'summer'] if today is in a swap window, else null. */
    private function windowFor(Carbon $today): ?array
    {
        // Feb 15 – Mar 15 → notify WINTER sets (swap to summer).
        $springStart = Carbon::create($today->year, 2, 15);
        $springEnd = Carbon::create($today->year, 3, 15);
        if ($today->between($springStart, $springEnd)) return ['season' => 'winter'];

        // Sep 15 – Oct 15 → notify SUMMER sets (swap to winter).
        $autumnStart = Carbon::create($today->year, 9, 15);
        $autumnEnd = Carbon::create($today->year, 10, 15);
        if ($today->between($autumnStart, $autumnEnd)) return ['season' => 'summer'];

        return null;
    }
}
