<?php

use App\Enums\SubscriptionPlan;
use App\Enums\SubscriptionStatus;
use App\Models\Subscription;
use Flux\Flux;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Livewire\Attributes\Computed;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
use Livewire\Component;
use Livewire\WithPagination;

new #[Title('Subscriptions')] class extends Component {
    use WithPagination;

    #[Url(as: 'status')]
    public string $statusFilter = 'all';

    #[Url(as: 'plan')]
    public string $planFilter = 'all';

    #[Url(as: 'q')]
    public string $search = '';

    #[Url(as: 'per_page')]
    public int $perPage = 50;

    /**
     * Reset pagination whenever the status filter changes.
     */
    public function updatingStatusFilter(): void
    {
        $this->resetPage();
    }

    /**
     * Reset pagination whenever the plan filter changes.
     */
    public function updatingPlanFilter(): void
    {
        $this->resetPage();
    }

    /**
     * Reset pagination whenever the search term changes.
     */
    public function updatingSearch(): void
    {
        $this->resetPage();
    }

    /**
     * Reset pagination whenever the per-page selection changes.
     */
    public function updatingPerPage(): void
    {
        $this->resetPage();
    }

    /**
     * Update a subscription's order status from the listing page.
     */
    public function updateStatus(int $subscriptionId, string $status): void
    {
        $validated = Validator::make(['status' => $status], [
            'status' => ['required', 'string', Rule::enum(SubscriptionStatus::class)],
        ])->validate();

        Subscription::query()->whereKey($subscriptionId)->firstOrFail()->update([
            'order_status' => SubscriptionStatus::from($validated['status']),
        ]);

        Flux::toast(variant: 'success', text: __('Status updated successfully!'));
    }

    /**
     * @return LengthAwarePaginator<int, Subscription>
     */
    #[Computed]
    public function subscriptions(): LengthAwarePaginator
    {
        return Subscription::query()
            ->when($this->normalizedStatus() !== 'all', fn ($query) => $query->where('order_status', $this->normalizedStatus()))
            ->when($this->normalizedPlan() !== 'all', fn ($query) => $query->where('plan', $this->normalizedPlan()))
            ->when($this->search !== '', function ($query) {
                $query->where(function ($query) {
                    $query->where('full_name', 'like', "%{$this->search}%")
                        ->orWhere('email', 'like', "%{$this->search}%")
                        ->orWhere('phone', 'like', "%{$this->search}%")
                        ->orWhere('order_id', 'like', "%{$this->search}%");
                });
            })
            ->orderByDesc('created_at')
            ->paginate($this->normalizedPerPage());
    }

    /**
     * Stats are computed over the whole table, unaffected by the current
     * filter/search.
     *
     * @return array<string, int|float>
     */
    #[Computed]
    public function stats(): array
    {
        return [
            'total' => Subscription::query()->count(),
            'pending' => Subscription::query()->where('order_status', SubscriptionStatus::Pending)->count(),
            'active' => Subscription::query()->where('order_status', SubscriptionStatus::Active)->count(),
            'cancelled' => Subscription::query()->where('order_status', SubscriptionStatus::Cancelled)->count(),
            'mrr' => (float) Subscription::query()->where('order_status', SubscriptionStatus::Active)->sum('plan_price'),
        ];
    }

    /**
     * Any unrecognised status value silently falls back to "all".
     */
    private function normalizedStatus(): string
    {
        return $this->statusFilter === 'all' || SubscriptionStatus::tryFrom($this->statusFilter) !== null
            ? $this->statusFilter
            : 'all';
    }

    /**
     * Any unrecognised plan value silently falls back to "all".
     */
    private function normalizedPlan(): string
    {
        return $this->planFilter === 'all' || SubscriptionPlan::tryFrom($this->planFilter) !== null
            ? $this->planFilter
            : 'all';
    }

    /**
     * Any unrecognised per-page value falls back to the default of 50.
     */
    private function normalizedPerPage(): int
    {
        return in_array($this->perPage, [25, 50, 100], true) ? $this->perPage : 50;
    }
}; ?>

<section class="w-full space-y-6">
    <div>
        <flux:heading size="xl" level="1">{{ __('Subscriptions') }}</flux:heading>
        <flux:subheading size="lg">{{ __('Manage recurring flower delivery subscriptions') }}</flux:subheading>
    </div>

    <div class="grid grid-cols-2 gap-4 lg:grid-cols-5">
        <flux:card size="sm" data-test="stat-total">
            <flux:subheading>{{ __('Total') }}</flux:subheading>
            <flux:heading size="xl">{{ $this->stats['total'] }}</flux:heading>
        </flux:card>

        <flux:card size="sm" data-test="stat-pending">
            <flux:subheading>{{ __('Pending') }}</flux:subheading>
            <flux:heading size="xl">{{ $this->stats['pending'] }}</flux:heading>
        </flux:card>

        <flux:card size="sm" data-test="stat-active">
            <flux:subheading>{{ __('Active') }}</flux:subheading>
            <flux:heading size="xl">{{ $this->stats['active'] }}</flux:heading>
        </flux:card>

        <flux:card size="sm" data-test="stat-cancelled">
            <flux:subheading>{{ __('Cancelled') }}</flux:subheading>
            <flux:heading size="xl">{{ $this->stats['cancelled'] }}</flux:heading>
        </flux:card>

        <flux:card size="sm" data-test="stat-mrr">
            <flux:subheading>{{ __('Monthly Recurring Revenue') }}</flux:subheading>
            <flux:heading size="xl">₹{{ number_format($this->stats['mrr'], 2) }}</flux:heading>
        </flux:card>
    </div>

    <div class="flex flex-col gap-4 sm:flex-row sm:items-end">
        <flux:input
            wire:model.live.debounce.300ms="search"
            icon="magnifying-glass"
            :label="__('Search')"
            :placeholder="__('Search by name, email, phone, or order ID')"
            class="sm:max-w-sm"
            data-test="subscriptions-search-input"
        />

        <flux:select wire:model.live="statusFilter" :label="__('Status')" class="sm:max-w-xs" data-test="subscriptions-status-filter">
            <flux:select.option value="all">{{ __('All') }}</flux:select.option>
            @foreach (SubscriptionStatus::cases() as $case)
                <flux:select.option :value="$case->value">{{ $case->label() }}</flux:select.option>
            @endforeach
        </flux:select>

        <flux:select wire:model.live="planFilter" :label="__('Plan')" class="sm:max-w-xs" data-test="subscriptions-plan-filter">
            <flux:select.option value="all">{{ __('All') }}</flux:select.option>
            @foreach (SubscriptionPlan::cases() as $case)
                <flux:select.option :value="$case->value">{{ $case->label() }}</flux:select.option>
            @endforeach
        </flux:select>

        <flux:select wire:model.live="perPage" :label="__('Per page')" class="sm:max-w-32" data-test="subscriptions-per-page">
            <flux:select.option value="25">25</flux:select.option>
            <flux:select.option value="50">50</flux:select.option>
            <flux:select.option value="100">100</flux:select.option>
        </flux:select>
    </div>

    <flux:table :paginate="$this->subscriptions">
        <flux:table.columns>
            <flux:table.column>{{ __('Order ID') }}</flux:table.column>
            <flux:table.column>{{ __('Name') }}</flux:table.column>
            <flux:table.column>{{ __('Phone') }}</flux:table.column>
            <flux:table.column>{{ __('Plan') }}</flux:table.column>
            <flux:table.column>{{ __('Price') }}</flux:table.column>
            <flux:table.column>{{ __('Start Date') }}</flux:table.column>
            <flux:table.column>{{ __('Status') }}</flux:table.column>
            <flux:table.column>{{ __('Created') }}</flux:table.column>
            <flux:table.column>{{ __('Actions') }}</flux:table.column>
        </flux:table.columns>

        <flux:table.rows>
            @forelse ($this->subscriptions as $subscription)
                <flux:table.row :key="$subscription->id" data-test="subscription-row">
                    <flux:table.cell variant="strong">{{ $subscription->order_id }}</flux:table.cell>
                    <flux:table.cell>{{ $subscription->full_name }}</flux:table.cell>
                    <flux:table.cell>
                        <flux:link href="tel:{{ $subscription->phone }}">{{ $subscription->phone }}</flux:link>
                    </flux:table.cell>
                    <flux:table.cell>
                        <flux:badge color="zinc">{{ $subscription->plan->label() }}</flux:badge>
                    </flux:table.cell>
                    <flux:table.cell>₹{{ number_format((float) $subscription->plan_price, 2) }}</flux:table.cell>
                    <flux:table.cell>{{ $subscription->start_date?->format('d M Y') }}</flux:table.cell>
                    <flux:table.cell>
                        <flux:dropdown position="bottom" align="start">
                            <flux:button variant="ghost" size="sm" icon:trailing="chevron-down" data-test="subscription-status-trigger">
                                <flux:badge :color="$subscription->order_status->badgeColor()">
                                    {{ $subscription->order_status->label() }}
                                </flux:badge>
                            </flux:button>
                            <flux:menu>
                                @foreach (SubscriptionStatus::cases() as $case)
                                    <flux:menu.item
                                        as="button"
                                        type="button"
                                        wire:click="updateStatus({{ $subscription->id }}, '{{ $case->value }}')"
                                        data-test="subscription-status-option"
                                    >
                                        {{ $case->label() }}
                                    </flux:menu.item>
                                @endforeach
                            </flux:menu>
                        </flux:dropdown>
                    </flux:table.cell>
                    <flux:table.cell>{{ $subscription->created_at?->format('d M Y, H:i') }}</flux:table.cell>
                    <flux:table.cell>
                        <flux:modal.trigger name="view-subscription-{{ $subscription->id }}">
                            <flux:button size="sm" variant="ghost" data-test="view-subscription-button">
                                {{ __('View') }}
                            </flux:button>
                        </flux:modal.trigger>
                    </flux:table.cell>
                </flux:table.row>
            @empty
                <flux:table.row>
                    <flux:table.cell colspan="9" align="center" data-test="subscriptions-empty-state">
                        {{ __('No subscriptions found') }}
                    </flux:table.cell>
                </flux:table.row>
            @endforelse
        </flux:table.rows>
    </flux:table>

    {{-- Detail modals render outside the table markup: a <dialog>/popover inside a
    <tbody> is invalid HTML and gets relocated by the browser's parser. --}}
    @foreach ($this->subscriptions as $subscription)
        <flux:modal name="view-subscription-{{ $subscription->id }}" class="max-w-lg">
            <div class="space-y-6">
                <div>
                    <flux:heading size="lg">{{ __('Subscription :order', ['order' => $subscription->order_id]) }}</flux:heading>
                    <flux:subheading>{{ $subscription->full_name }}</flux:subheading>
                </div>

                <div class="space-y-3 text-sm">
                    <div>
                        <flux:text class="text-zinc-500 dark:text-zinc-400">{{ __('Address') }}</flux:text>
                        <div class="font-medium">{{ $subscription->address }}</div>
                    </div>

                    <div class="grid grid-cols-2 gap-3">
                        <div>
                            <flux:text class="text-zinc-500 dark:text-zinc-400">{{ __('City') }}</flux:text>
                            <div class="font-medium">{{ $subscription->city }}</div>
                        </div>

                        <div>
                            <flux:text class="text-zinc-500 dark:text-zinc-400">{{ __('Pincode') }}</flux:text>
                            <div class="font-medium">{{ $subscription->pincode }}</div>
                        </div>
                    </div>

                    <div>
                        <flux:text class="text-zinc-500 dark:text-zinc-400">{{ __('Landmark') }}</flux:text>
                        <div class="font-medium">{{ $subscription->landmark ?? __('Not specified') }}</div>
                    </div>

                    <div>
                        <flux:text class="text-zinc-500 dark:text-zinc-400">{{ __('WhatsApp') }}</flux:text>
                        <div class="font-medium">{{ $subscription->whatsapp ?? __('Not specified') }}</div>
                    </div>

                    <div>
                        <flux:text class="text-zinc-500 dark:text-zinc-400">{{ __('Special Instructions') }}</flux:text>
                        <div class="font-medium" style="white-space: pre-wrap">
                            {{ $subscription->special_instructions ?? __('None') }}
                        </div>
                    </div>

                    <div class="grid grid-cols-2 gap-3">
                        <div>
                            <flux:text class="text-zinc-500 dark:text-zinc-400">{{ __('Terms Agreed') }}</flux:text>
                            <div class="font-medium">
                                {{ $subscription->terms_agreed ? __('Yes') : __('No') }}
                            </div>
                        </div>

                        <div>
                            <flux:text class="text-zinc-500 dark:text-zinc-400">{{ __('Terms Agreed At') }}</flux:text>
                            <div class="font-medium">
                                {{ $subscription->terms_agreed_at?->format('d M Y, H:i') ?? '-' }}
                            </div>
                        </div>
                    </div>

                    <div>
                        <flux:text class="text-zinc-500 dark:text-zinc-400">{{ __('IP Address') }}</flux:text>
                        <div class="font-medium">{{ $subscription->ip_address ?? __('Unknown') }}</div>
                    </div>
                </div>

                <div class="flex justify-end">
                    <flux:modal.close>
                        <flux:button variant="filled">{{ __('Close') }}</flux:button>
                    </flux:modal.close>
                </div>
            </div>
        </flux:modal>
    @endforeach
</section>
