<?php

namespace Database\Seeders;

use App\Models\Order;
use App\Models\PricingTier;
use App\Models\Product;
use App\Models\Subscription;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Str;

/**
 * SubscriptionSeeder
 *
 * Creates 8 subscription records covering every possible lifecycle status:
 *  Active, Trial, Inactive, Cancelled, Expired, Past Due
 *
 * Each subscription has a real Order linked to it (subscription_id set on order).
 * Active subscriptions also get 1–2 renewal orders to show billing history.
 *
 * Uses the SaaS Project Manager product and its Starter/Agency plans.
 */
class SubscriptionSeeder extends Seeder
{
    use WithoutModelEvents;

    public function run(): void
    {
        $product = Product::where('name', 'SaaS Project Manager')->first();
        if (!$product) return;

        $starterPlan = $product->plans()->where('name', 'Starter Plan')->first();
        $agencyPlan  = $product->plans()->where('name', 'Agency Plan')->first();
        if (!$starterPlan || !$agencyPlan) return;

        $starterMonthly = $starterPlan->pricingTiers()->where('tier_name', 'Monthly')->first();
        $starterYearly  = $starterPlan->pricingTiers()->where('tier_name', 'Yearly')->first();
        $agencyMonthly  = $agencyPlan->pricingTiers()->where('tier_name', 'Monthly')->first();
        $agencyYearly   = $agencyPlan->pricingTiers()->where('tier_name', 'Yearly')->first();
        if (!$starterMonthly || !$starterYearly || !$agencyMonthly || !$agencyYearly) return;

        $customerIds = User::whereHas('roles', fn($q) => $q->where('id', 2))
            ->where('id', '!=', 1)->pluck('id')->toArray();
        if (empty($customerIds)) return;

        $paymentMethods = ['stripe', 'paypal'];

        // ----------------------------------------------------------------
        // 1. Active — Starter Monthly
        // ----------------------------------------------------------------
        $userId    = $customerIds[0];
        $startDate = Carbon::now()->subDays(20);
        $periodEnd = $startDate->copy()->addMonth();

        $initOrder = $this->createSubscriptionOrder($userId, $product, $starterPlan, $starterMonthly, 1, $startDate, $paymentMethods[0], null, 1);
        $sub = Subscription::create([
            'user_id'               => $userId,
            'reference_id'          => $this->subRef(),
            'purchasable_type'      => PricingTier::class,
            'purchasable_id'        => $starterMonthly->id,
            'name'                  => $product->name . ' — ' . $starterPlan->name . ' (Monthly)',
            'price'                 => $starterMonthly->price,
            'status'                => 1, // ACTIVE
            'billing_cycle'         => 3, // MONTHLY
            'billing_cycle_count'   => 1,
            'start_date'            => $startDate,
            'current_period_start'  => $startDate->copy()->addMonth(),
            'current_period_end'    => $startDate->copy()->addMonths(2),
            'next_billing_date'     => $startDate->copy()->addMonths(2),
        ]);
        $initOrder->update(['subscription_id' => $sub->id]);
        // Renewal order (completed)
        $this->createSubscriptionOrder($userId, $product, $starterPlan, $starterMonthly, 1, $startDate->copy()->addMonth(), $paymentMethods[0], $sub->id, 2);

        // ----------------------------------------------------------------
        // 2. Active — Agency Yearly
        // ----------------------------------------------------------------
        $userId2    = $customerIds[1 % count($customerIds)];
        $startDate2 = Carbon::now()->subDays(25);

        $initOrder2 = $this->createSubscriptionOrder($userId2, $product, $agencyPlan, $agencyYearly, 1, $startDate2, $paymentMethods[1], null, 3);
        $sub2 = Subscription::create([
            'user_id'               => $userId2,
            'reference_id'          => $this->subRef(),
            'purchasable_type'      => PricingTier::class,
            'purchasable_id'        => $agencyYearly->id,
            'name'                  => $product->name . ' — ' . $agencyPlan->name . ' (Yearly)',
            'price'                 => $agencyYearly->price,
            'status'                => 1, // ACTIVE
            'billing_cycle'         => 6, // YEARLY
            'billing_cycle_count'   => 1,
            'start_date'            => $startDate2,
            'current_period_start'  => $startDate2,
            'current_period_end'    => $startDate2->copy()->addYear(),
            'next_billing_date'     => $startDate2->copy()->addYear(),
        ]);
        $initOrder2->update(['subscription_id' => $sub2->id]);

        // ----------------------------------------------------------------
        // 3. Trial — Agency Monthly (14-day trial)
        // ----------------------------------------------------------------
        $userId3    = $customerIds[2 % count($customerIds)];
        $trialStart = Carbon::now()->subDays(3);
        $trialEnd   = $trialStart->copy()->addDays(14);

        $initOrder3 = $this->createSubscriptionOrder($userId3, $product, $agencyPlan, $agencyMonthly, 0, $trialStart, $paymentMethods[0], null, 4);
        $sub3 = Subscription::create([
            'user_id'             => $userId3,
            'reference_id'        => $this->subRef(),
            'purchasable_type'    => PricingTier::class,
            'purchasable_id'      => $agencyMonthly->id,
            'name'                => $product->name . ' — ' . $agencyPlan->name . ' (Monthly Trial)',
            'price'               => $agencyMonthly->price,
            'status'              => 2, // TRIAL
            'billing_cycle'       => 3, // MONTHLY
            'billing_cycle_count' => 1,
            'trial_active'        => true,
            'trial_start_date'    => $trialStart,
            'trial_end_date'      => $trialEnd,
            'next_billing_date'   => $trialEnd,
        ]);
        $initOrder3->update(['subscription_id' => $sub3->id]);

        // ----------------------------------------------------------------
        // 4. Cancelled — Starter Yearly
        // ----------------------------------------------------------------
        $userId4    = $customerIds[3 % count($customerIds)];
        $startDate4 = Carbon::now()->subDays(28);

        $initOrder4 = $this->createSubscriptionOrder($userId4, $product, $starterPlan, $starterYearly, 1, $startDate4, $paymentMethods[1], null, 5);
        $sub4 = Subscription::create([
            'user_id'              => $userId4,
            'reference_id'         => $this->subRef(),
            'purchasable_type'     => PricingTier::class,
            'purchasable_id'       => $starterYearly->id,
            'name'                 => $product->name . ' — ' . $starterPlan->name . ' (Yearly)',
            'price'                => $starterYearly->price,
            'status'               => 4, // CANCELLED
            'billing_cycle'        => 6,
            'billing_cycle_count'  => 1,
            'start_date'           => $startDate4,
            'current_period_start' => $startDate4,
            'current_period_end'   => $startDate4->copy()->addYear(),
            'cancelled_at'         => Carbon::now()->subMonths(2),
            'cancellation_reason'  => 1, // CR_CUSTOMER_REQUESTED
        ]);
        $initOrder4->update(['subscription_id' => $sub4->id]);

        // ----------------------------------------------------------------
        // 5. Expired — Starter Monthly (started 6 months ago, ended)
        // ----------------------------------------------------------------
        $userId5    = $customerIds[4 % count($customerIds)];
        $startDate5 = Carbon::now()->subDays(28);
        $endDate5   = $startDate5->copy()->addDays(14);

        $initOrder5 = $this->createSubscriptionOrder($userId5, $product, $starterPlan, $starterMonthly, 1, $startDate5, $paymentMethods[0], null, 6);
        $sub5 = Subscription::create([
            'user_id'              => $userId5,
            'reference_id'         => $this->subRef(),
            'purchasable_type'     => PricingTier::class,
            'purchasable_id'       => $starterMonthly->id,
            'name'                 => $product->name . ' — ' . $starterPlan->name . ' (Monthly)',
            'price'                => $starterMonthly->price,
            'status'               => 6, // EXPIRED
            'billing_cycle'        => 3,
            'billing_cycle_count'  => 3,
            'start_date'           => $startDate5,
            'end_date'             => $endDate5,
            'current_period_start' => $endDate5->copy()->subMonth(),
            'current_period_end'   => $endDate5,
            'next_billing_date'    => $endDate5,
        ]);
        $initOrder5->update(['subscription_id' => $sub5->id]);
        // 2 renewal orders for history
        $this->createSubscriptionOrder($userId5, $product, $starterPlan, $starterMonthly, 1, $startDate5->copy()->addMonth(), $paymentMethods[0], $sub5->id, 7);
        $this->createSubscriptionOrder($userId5, $product, $starterPlan, $starterMonthly, 1, $startDate5->copy()->addMonths(2), $paymentMethods[0], $sub5->id, 8);

        // ----------------------------------------------------------------
        // 6. Past Due — Agency Monthly
        // ----------------------------------------------------------------
        $userId6    = $customerIds[5 % count($customerIds)];
        $startDate6 = Carbon::now()->subDays(25);

        $initOrder6 = $this->createSubscriptionOrder($userId6, $product, $agencyPlan, $agencyMonthly, 1, $startDate6, $paymentMethods[1], null, 9);
        $sub6 = Subscription::create([
            'user_id'              => $userId6,
            'reference_id'         => $this->subRef(),
            'purchasable_type'     => PricingTier::class,
            'purchasable_id'       => $agencyMonthly->id,
            'name'                 => $product->name . ' — ' . $agencyPlan->name . ' (Monthly)',
            'price'                => $agencyMonthly->price,
            'status'               => 7, // PAST_DUE
            'billing_cycle'        => 3,
            'billing_cycle_count'  => 1,
            'start_date'           => $startDate6,
            'current_period_start' => $startDate6->copy()->addMonths(2),
            'current_period_end'   => $startDate6->copy()->addMonths(3),
            'next_billing_date'    => $startDate6->copy()->addMonths(3),
        ]);
        $initOrder6->update(['subscription_id' => $sub6->id]);

        // ----------------------------------------------------------------
        // 7. Inactive — Starter Monthly (pending payment)
        // ----------------------------------------------------------------
        $userId7    = $customerIds[6 % count($customerIds)];
        $startDate7 = Carbon::now()->subDays(2);

        $initOrder7 = $this->createSubscriptionOrder($userId7, $product, $starterPlan, $starterMonthly, 0, $startDate7, $paymentMethods[0], null, 10);
        $sub7 = Subscription::create([
            'user_id'             => $userId7,
            'reference_id'        => $this->subRef(),
            'purchasable_type'    => PricingTier::class,
            'purchasable_id'      => $starterMonthly->id,
            'name'                => $product->name . ' — ' . $starterPlan->name . ' (Monthly)',
            'price'               => $starterMonthly->price,
            'status'              => 3, // INACTIVE
            'billing_cycle'       => 3,
            'billing_cycle_count' => 1,
        ]);
        $initOrder7->update(['subscription_id' => $sub7->id]);

        // ----------------------------------------------------------------
        // 8. Active — Starter Yearly (second active sub for variety)
        // ----------------------------------------------------------------
        $userId8    = $customerIds[7 % count($customerIds)];
        $startDate8 = Carbon::now()->subDays(15);

        $initOrder8 = $this->createSubscriptionOrder($userId8, $product, $starterPlan, $starterYearly, 1, $startDate8, $paymentMethods[0], null, 11);
        $sub8 = Subscription::create([
            'user_id'               => $userId8,
            'reference_id'          => $this->subRef(),
            'purchasable_type'      => PricingTier::class,
            'purchasable_id'        => $starterYearly->id,
            'name'                  => $product->name . ' — ' . $starterPlan->name . ' (Yearly)',
            'price'                 => $starterYearly->price,
            'status'                => 1, // ACTIVE
            'billing_cycle'         => 6,
            'billing_cycle_count'   => 1,
            'start_date'            => $startDate8,
            'current_period_start'  => $startDate8,
            'current_period_end'    => $startDate8->copy()->addYear(),
            'next_billing_date'     => $startDate8->copy()->addYear(),
        ]);
        $initOrder8->update(['subscription_id' => $sub8->id]);

        // ----------------------------------------------------------------
        // 9. Hybrid Cloud Storage — Active Monthly
        // ----------------------------------------------------------------
        $hybridProduct = Product::where('name', 'Hybrid Cloud Storage')->first();
        if ($hybridProduct) {
            $cloudPlan = $hybridProduct->plans()->where('name', 'Managed Cloud')->first();
            if ($cloudPlan) {
                $cloudMonthly = $cloudPlan->pricingTiers()->where('tier_name', 'Monthly')->first();
                $cloudYearly  = $cloudPlan->pricingTiers()->where('tier_name', 'Yearly')->first();

                if ($cloudMonthly) {
                    $userId9    = $customerIds[8 % count($customerIds)];
                    $startDate9 = Carbon::now()->subDays(20);

                    $initOrder9 = $this->createSubscriptionOrder($userId9, $hybridProduct, $cloudPlan, $cloudMonthly, 1, $startDate9, $paymentMethods[0], null, 12);
                    $sub9 = Subscription::create([
                        'user_id'               => $userId9,
                        'reference_id'          => $this->subRef(),
                        'purchasable_type'      => PricingTier::class,
                        'purchasable_id'        => $cloudMonthly->id,
                        'name'                  => $hybridProduct->name . ' — ' . $cloudPlan->name . ' (Monthly)',
                        'price'                 => $cloudMonthly->price,
                        'status'                => 1, // ACTIVE
                        'billing_cycle'         => 3,
                        'billing_cycle_count'   => 1,
                        'start_date'            => $startDate9,
                        'current_period_start'  => $startDate9,
                        'current_period_end'    => $startDate9->copy()->addMonth(),
                        'next_billing_date'     => $startDate9->copy()->addMonth(),
                    ]);
                    $initOrder9->update(['subscription_id' => $sub9->id]);
                }

                // ----------------------------------------------------------------
                // 10. Hybrid Cloud Storage — Trial Monthly
                // ----------------------------------------------------------------
                if ($cloudMonthly) {
                    $userId10    = $customerIds[9 % count($customerIds)];
                    $trialStart10 = Carbon::now()->subDays(2);
                    $trialEnd10   = $trialStart10->copy()->addDays(7);

                    $initOrder10 = $this->createSubscriptionOrder($userId10, $hybridProduct, $cloudPlan, $cloudMonthly, 0, $trialStart10, $paymentMethods[1], null, 13);
                    $sub10 = Subscription::create([
                        'user_id'             => $userId10,
                        'reference_id'        => $this->subRef(),
                        'purchasable_type'    => PricingTier::class,
                        'purchasable_id'      => $cloudMonthly->id,
                        'name'                => $hybridProduct->name . ' — ' . $cloudPlan->name . ' (Monthly Trial)',
                        'price'               => $cloudMonthly->price,
                        'status'              => 2, // TRIAL
                        'billing_cycle'       => 3,
                        'billing_cycle_count' => 1,
                        'trial_active'        => true,
                        'trial_start_date'    => $trialStart10,
                        'trial_end_date'      => $trialEnd10,
                        'next_billing_date'   => $trialEnd10,
                    ]);
                    $initOrder10->update(['subscription_id' => $sub10->id]);
                }
            }
        }
    }

    /**
     * Create a subscription initial (or renewal) order.
     */
    private function createSubscriptionOrder(
        int $userId,
        $product,
        $plan,
        PricingTier $pricingTier,
        int $status, // 0=pending, 1=completed
        Carbon $createdAt,
        string $paymentMethod,
        ?int $subscriptionId = null,
        int $index = 0
    ): Order {
        $price = (float) $pricingTier->price;

        do {
            $ref = 'RIX-' . \Illuminate\Support\Str::upper(\Illuminate\Support\Str::random(10));
        } while (Order::where('order_reference', $ref)->exists());

        $order = Order::create([
            'user_id'             => $userId,
            'order_reference'     => $ref,
            'order_type'          => getConstant('BILLING_SUBSCRIPTION'),
            'status'              => $status,
            'discount_amount'     => 0,
            'tax_amount'          => 0,
            'tax_rate'            => 0,
            'subtotal'            => $price,
            'total'               => $price,
            'currency'            => 'USD',
            'payment_method'      => $paymentMethod,
            'transaction_id'      => $status ? 'DEMO-' . strtoupper(substr(md5(uniqid()), 0, 10)) : null,
            'customer_ip_address' => '172.16.' . rand(1, 254) . '.' . rand(1, 254),
            'invoice_number'      => (int) (date('YmdHis') . str_pad($index + 200, 4, '0', STR_PAD_LEFT)),
            'subscription_id'     => $subscriptionId,
            'created_at'          => $createdAt,
            'updated_at'          => $createdAt,
        ]);

        $order->items()->create([
            'purchasable_type' => PricingTier::class,
            'purchasable_id'   => $pricingTier->id,
            'name'             => $product->name . ' — ' . $plan->name . ' (' . $pricingTier->tier_name . ')',
            'price'            => $price,
            'quantity'         => 1,
        ]);

        $billingAddress = \App\Models\BillingAddress::where('user_id', $userId)->first();
        $order->billingInfo()->create([
            'first_name'  => $billingAddress?->first_name ?? 'Demo',
            'last_name'   => $billingAddress?->last_name ?? 'User',
            'address'     => $billingAddress?->address ?? '123 Demo Street',
            'city'        => $billingAddress?->city ?? 'Demo City',
            'state_id'    => $billingAddress?->state_id,
            'zip'         => $billingAddress?->zip ?? '00000',
            'country_id'  => $billingAddress?->country_id ?? 166,
            'email'       => User::find($userId)?->email ?? 'demo@example.com',
        ]);

        return $order;
    }

    private function subRef(): string
    {
        $prefix = setting('subscription.subscription_id_prefix', 'SUB');
        do {
            $ref = $prefix . '-' . Str::upper(Str::random(10));
        } while (Subscription::where('reference_id', $ref)->exists());

        return $ref;
    }
}
