<?php

declare(strict_types=1);

namespace App\Console\Commands;

use App\Models\Invoice;
use App\Models\PlanPrice;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Laravel\Cashier\Subscription;

class BackfillSubscriptionAmountsCommand extends Command
{
    protected $signature = 'subscriptions:backfill-amounts
        {--dry-run : Preview changes without writing to the database}';

    protected $description = 'Backfill recurring_amount on subscriptions from invoice history or plan prices';

    public function handle(): int
    {
        $dryRun = (bool) $this->option('dry-run');

        if ($dryRun) {
            $this->warn('DRY RUN — no changes will be written.');
        }

        $subscriptions = Subscription::query()
            ->where('stripe_status', 'active')
            ->whereNull('recurring_amount')
            ->whereNotNull('plan_id')
            ->with('user')
            ->get();

        if ($subscriptions->isEmpty()) {
            $this->info('No active subscriptions without recurring_amount found.');

            return self::SUCCESS;
        }

        $this->info("Found {$subscriptions->count()} subscription(s) to backfill.");

        $fromInvoice = 0;
        $fromPlanPrice = 0;
        $fromPlanBase = 0;
        $skipped = 0;

        foreach ($subscriptions as $subscription) {
            $amount = null;
            $source = 'none';

            // Strategy 1: Find invoice items matching the plan name
            $plan = DB::table('plans')->where('id', $subscription->plan_id)->first();

            if (! $plan) {
                $this->warn("  Subscription #{$subscription->id}: no plan found (plan_id={$subscription->plan_id}), skipping.");
                $skipped++;

                continue;
            }

            // Look for the most recent paid invoice for this user that has items
            // referencing the plan name
            $invoiceAmount = Invoice::query()
                ->where('user_id', $subscription->user_id)
                ->where('status', 'paid')
                ->whereHas('items', function ($query) use ($plan): void {
                    $query->where('description', 'like', '%'.$plan->name.'%');
                })
                ->orderByDesc('paid_at')
                ->first();

            if ($invoiceAmount) {
                // Sum the invoice items that match the plan name
                $matchingItemsTotal = (float) $invoiceAmount->items()
                    ->where('description', 'like', '%'.$plan->name.'%')
                    ->sum(DB::raw('amount * quantity'));

                if ($matchingItemsTotal > 0) {
                    $amount = $matchingItemsTotal;
                    $source = 'invoice';
                }
            }

            // Strategy 2: Fall back to plan_prices table
            if ($amount === null) {
                $planPrice = PlanPrice::query()
                    ->where('plan_id', $subscription->plan_id)
                    ->where('billing_cycle', $subscription->billing_cycle ?? 'monthly')
                    ->first();

                if ($planPrice) {
                    $amount = (float) $planPrice->price;
                    $source = 'plan_price';
                }
            }

            // Strategy 3: Fall back to plans.price base
            if ($amount === null && $plan->price > 0) {
                $amount = (float) $plan->price;
                $source = 'plan_base';
            }

            if ($amount === null) {
                $this->warn("  Subscription #{$subscription->id} (plan: {$plan->name}): no amount found, skipping.");
                $skipped++;

                continue;
            }

            $userName = $subscription->user?->name ?? "user #{$subscription->user_id}";
            $this->info("  Subscription #{$subscription->id} ({$userName}, plan: {$plan->name}, cycle: {$subscription->billing_cycle}): \${$amount} [source: {$source}]");

            if (! $dryRun) {
                Subscription::query()
                    ->where('id', $subscription->id)
                    ->update(['recurring_amount' => $amount]);
            }

            match ($source) {
                'invoice' => $fromInvoice++,
                'plan_price' => $fromPlanPrice++,
                'plan_base' => $fromPlanBase++,
                default => $skipped++,
            };
        }

        $this->newLine();
        $this->info('Backfill summary:');
        $this->info("  From invoice items: {$fromInvoice}");
        $this->info("  From plan prices:   {$fromPlanPrice}");
        $this->info("  From plan base:     {$fromPlanBase}");
        $this->info("  Skipped:            {$skipped}");

        if ($dryRun) {
            $this->warn('DRY RUN — no changes were written. Run without --dry-run to apply.');
        }

        return self::SUCCESS;
    }
}
