<?php

namespace App\Console\Commands;

use App\Domains\Billing\Actions\CreateTenantBillingInvoiceAction;
use App\Domains\Billing\Actions\SyncTenantLifecycleAction;
use App\Domains\Billing\Models\Subscription;
use App\Domains\Billing\Models\TenantBillingInvoice;
use App\Domains\Tenancy\Models\Tenant;
use Illuminate\Console\Command;

class GenerateTenantRenewalInvoicesCommand extends Command
{
    protected $signature = 'billing:generate-renewal-invoices';

    protected $description = 'Generate renewal invoices for expired tenant subscriptions';

    public function handle(
        CreateTenantBillingInvoiceAction $createInvoice,
        SyncTenantLifecycleAction $syncTenantLifecycle
    ): int {
        $generated = 0;

        Tenant::query()->with('plan')->chunk(100, function ($tenants) use ($createInvoice, $syncTenantLifecycle, &$generated): void {
            foreach ($tenants as $tenant) {
                /** @var Subscription|null $subscription */
                $subscription = Subscription::query()
                    ->where('tenant_id', $tenant->getKey())
                    ->latest('created_at')
                    ->first();

                if (! $subscription || ! $subscription->ends_at || now()->lt($subscription->ends_at)) {
                    continue;
                }

                if (! in_array($subscription->status, ['active', 'paid', 'succeeded', 'past_due'], true)) {
                    continue;
                }

                $billingCycle = $this->resolveBillingCycle($subscription);
                $hasOpenRenewalInvoice = TenantBillingInvoice::query()
                    ->where('tenant_id', $tenant->getKey())
                    ->where('plan_id', $tenant->plan_id)
                    ->where('billing_cycle', $billingCycle)
                    ->whereIn('status', ['draft', 'initiated', 'pending_payment'])
                    ->exists();

                if ($hasOpenRenewalInvoice || ! $tenant->plan) {
                    $syncTenantLifecycle->execute($tenant);
                    continue;
                }

                $actor = $tenant->users()->oldest('id')->first();
                if (! $actor) {
                    continue;
                }

                $createInvoice->execute(
                    tenant: $tenant,
                    plan: $tenant->plan,
                    user: $actor,
                    billingCycle: $billingCycle,
                );

                $syncTenantLifecycle->execute($tenant);
                $generated++;
            }
        });

        $this->info("Generated {$generated} renewal invoices.");

        return self::SUCCESS;
    }

    private function resolveBillingCycle(Subscription $subscription): string
    {
        if (! $subscription->starts_at || ! $subscription->ends_at) {
            return 'monthly';
        }

        return $subscription->starts_at->diffInDays($subscription->ends_at) > 60 ? 'yearly' : 'monthly';
    }
}
