<?php

namespace App\Console\Commands;

use App\Jobs\ArchiveInvoice;
use App\Models\Invoice;
use App\Models\ExportTarget;
use Illuminate\Console\Command;

/**
 * The sweep behind the copy-on-issue.
 *
 * Copying at issue is right and it is not enough. An invoice issued while the
 * office connection was down never reaches the archive, the queue eventually
 * gives up, and nothing about the invoice tells anybody — nobody opens an
 * archive to check whether last Tuesday is in it. This picks up whatever is
 * still missing, however long ago it was issued.
 *
 * Deliberately re-queues rather than writing here: the job already knows how to
 * write one, and two code paths that both write an invoice into an archive is
 * one more than the number that can be kept correct.
 */
class ArchiveUnexportedInvoices extends Command
{
    protected $signature = 'clupilot:archive-invoices {--limit=200}';

    protected $description = 'Queue a copy of every invoice that is not on the archive yet';

    public function handle(): int
    {
        $targets = ExportTarget::query()->where('active', true)->get();

        if ($targets->isEmpty()) {
            $this->line('No export target configured — nothing to do.');

            return self::SUCCESS;
        }

        $queued = 0;

        foreach ($targets as $target) {
            // Per destination, because "arrived" is a fact about a pair. An
            // invoice on the office NAS and not on the off-site box is exactly
            // the case this exists to catch.
            $pending = Invoice::query()
                ->whereDoesntHave('exports', fn ($q) => $q
                    ->where('export_target_id', $target->id)
                    ->whereNotNull('exported_at'))
                ->orderBy('id')
                ->limit((int) $this->option('limit'))
                ->get();

            foreach ($pending as $invoice) {
                ArchiveInvoice::dispatch($invoice, $target);
                $queued++;
            }
        }

        $this->line("Queued {$queued} copy/copies for {$targets->count()} destination(s).");

        return self::SUCCESS;
    }
}
