<?php

namespace App\Livewire\Checkout;

use App\Enums\SubscriptionStatus;
use App\Models\Feature;
use App\Models\Plan;
use App\Models\Subscription;
use App\Services\StripeService;
use Livewire\Attributes\Computed;
use Livewire\Component;

class Index extends Component
{
    public Plan $plan;
    public string $billing = 'monthly';

    public function mount(string $planId, string $billing = 'monthly'): void
    {
        $this->plan    = Plan::public()->where('active', true)->findOrFail($planId);
        $this->billing = in_array($billing, ['monthly', 'yearly']) ? $billing : 'monthly';
    }

    /**
     * 'cancel'  → Free Plan gewählt: Stripe-Abo kündigen
     * 'update'  → User hat aktives Stripe-Abo: in-place updaten (keine Weiterleitung zu Stripe)
     * 'new'     → Kein aktives Abo: neuer Stripe Checkout
     */
    #[Computed]
    public function checkoutType(): string
    {
        if ($this->plan->isFree()) {
            return 'cancel';
        }

        return $this->activeStripeSub ? 'update' : 'new';
    }

    #[Computed]
    public function activeStripeSub(): ?Subscription
    {
        return Subscription::where('user_id', auth()->id())
            ->where('provider', 'stripe')
            ->whereNotNull('provider_subscription_id')
            ->where('status', SubscriptionStatus::Active->value)
            ->latest('created_at')
            ->first();
    }

    public function startCheckout(): void
    {
        $user   = auth()->user();
        $stripe = app(StripeService::class);

        try {
            // ── Free Plan: Stripe-Abo kündigen ────────────────────────────
            if ($this->plan->isFree()) {
                $stripe->cancelUserSubscription($user);
                $this->redirect(route('subscription.index'), navigate: false);
                return;
            }

            // ── Upgrade / Downgrade: bestehendes Abo in-place updaten ─────
            $existingSub = $this->activeStripeSub;
            if ($existingSub) {
                $stripe->updateStripeSubscription(
                    $existingSub->provider_subscription_id,
                    $this->plan,
                    $this->billing,
                    $user->id
                );
                $this->redirect(route('subscription.index'), navigate: false);
                return;
            }

            // ── Erstes Abo: neuer Stripe Checkout ─────────────────────────
            $session = $stripe->createCheckoutSession($user, $this->plan, $this->billing);
            $this->redirect($session->url, navigate: false);

        } catch (\Throwable $e) {
            $this->dispatch('notify', ['type' => 'error', 'message' => 'Fehler: ' . $e->getMessage()]);
        }
    }

    public function openBillingPortal(): void
    {
        $customerId = \App\Models\Subscription::where('user_id', auth()->id())
            ->where('provider', 'stripe')
            ->whereNotNull('provider_customer_id')
            ->latest('created_at')
            ->value('provider_customer_id');

        if (!$customerId) {
            $this->dispatch('notify', ['type' => 'error', 'message' => 'Kein Stripe-Konto verknüpft.']);
            return;
        }

        try {
            $url = app(StripeService::class)->createBillingPortalSession($customerId);
            $this->redirect($url, navigate: false);
        } catch (\Throwable $e) {
            $this->dispatch('notify', ['type' => 'error', 'message' => 'Fehler beim Öffnen des Portals.']);
        }
    }

    #[Computed]
    public function monthlyPrice(): int
    {
        return $this->plan->getMonthlyPrice();
    }

    #[Computed]
    public function yearlyPrice(): int
    {
        return $this->plan->getYearlyPrice();
    }

    #[Computed]
    public function activePrice(): int
    {
        return $this->billing === 'yearly' ? $this->yearlyPrice : $this->monthlyPrice;
    }

    #[Computed]
    public function savings(): int
    {
        return ($this->monthlyPrice * 12) - $this->yearlyPrice;
    }

    public function render()
    {
        return view('livewire.checkout.index', [
            'features' => $this->plan->features()->with('group')->orderBy('sort')->get(),
        ])->layout('layouts.app');
    }
}
