<?php

declare(strict_types=1);

namespace App\Filament\Pages;

use App\Models\Subscription;
use Filament\Actions\Action;
use Filament\Actions\Concerns\InteractsWithActions;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\Select;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Pages\Page;
use Filament\Schemas\Components\Grid;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Concerns\InteractsWithTable;
use Filament\Tables\Contracts\HasTable;
use Filament\Tables\Filters\Filter;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
use UnitEnum;

class CustomerAnalytics extends Page implements HasForms, HasTable
{
    use InteractsWithActions;
    use InteractsWithForms;
    use InteractsWithTable;

    protected static string|null|\BackedEnum $navigationIcon = 'heroicon-o-chart-bar';

    protected static string|UnitEnum|null $navigationGroup = 'Admin';

    protected static ?int $navigationSort = 1;

    protected string $view = 'filament.pages.customer-analytics';

    public $startDate;

    public $endDate;

    public $selectedProvider = 'all';

    public $selectedPlan = 'all';

    public function mount(): void
    {
        $this->startDate = now()->subDays(30)->format('Y-m-d');
        $this->endDate = now()->format('Y-m-d');
    }

    public function getTitle(): string
    {
        return 'Customer Analytics';
    }

    protected function getHeaderActions(): array
    {
        return [
            Action::make('export_report')
                ->label('Export Report')
                ->icon('heroicon-o-arrow-down-tray')
                ->color('success')
                ->action(fn () => $this->exportReport()),

            Action::make('refresh')
                ->label('Refresh')
                ->icon('heroicon-o-arrow-path')
                ->color('gray')
                ->action(fn () => $this->resetTable()),
        ];
    }

    protected function getHeaderWidgets(): array
    {
        return [
            \App\Filament\Widgets\CustomerAnalyticsOverview::class,
            \App\Filament\Widgets\SubscriptionMetrics::class,
            \App\Filament\Widgets\CouponPerformanceMetrics::class,
        ];
    }

    protected function getFormSchema(): array
    {
        return [
            Grid::make(4)
                ->schema([
                    DatePicker::make('startDate')
                        ->label('Start Date')
                        ->default(fn () => now()->subDays(30))
                        ->required(),

                    DatePicker::make('endDate')
                        ->label('End Date')
                        ->default(fn () => now())
                        ->required(),

                    Select::make('selectedProvider')
                        ->label('Provider')
                        ->options([
                            'all' => 'All Providers',
                            'stripe' => 'Stripe',
                            'lemon_squeezy' => 'Lemon Squeezy',
                            'polar' => 'Polar.sh',
                            'oxapay' => 'OxaPay',
                            'crypto' => 'Crypto',
                            'activation_key' => 'Activation Key',
                        ])
                        ->default('all'),

                    Select::make('selectedPlan')
                        ->label('Plan')
                        ->options(function () {
                            $plans = DB::table('plans')->pluck('name', 'id');

                            return ['all' => 'All Plans'] + $plans->toArray();
                        })
                        ->default('all'),
                ]),
        ];
    }

    public function table(Table $table): Table
    {
        return $table
            ->query(
                $this->getCustomerAnalyticsQuery()
            )
            ->columns([
                TextColumn::make('user.name')
                    ->label('Customer')
                    ->searchable()
                    ->sortable()
                    ->weight('medium'),

                TextColumn::make('user.email')
                    ->label('Email')
                    ->searchable()
                    ->copyable()
                    ->toggleable(),

                TextColumn::make('plan.name')
                    ->label('Plan')
                    ->searchable()
                    ->sortable()
                    ->badge()
                    ->color('primary'),

                TextColumn::make('provider')
                    ->label('Provider')
                    ->badge()
                    ->colors([
                        'blue' => 'stripe',
                        'green' => 'lemon_squeezy',
                        'purple' => 'polar',
                        'orange' => 'oxapay',
                        'gray' => 'crypto',
                        'pink' => 'activation_key',
                    ]),

                TextColumn::make('status')
                    ->label('Status')
                    ->badge()
                    ->colors([
                        'success' => 'active',
                        'warning' => 'trialing',
                        'danger' => 'cancelled',
                        'secondary' => 'paused',
                        'gray' => 'incomplete',
                    ]),

                TextColumn::make('subscription_age')
                    ->label('Age')
                    ->state(function ($record) {
                        $started = $record->starts_at ?? $record->created_at;

                        return $started ? $started->diffForHumans() : 'Unknown';
                    })
                    ->sortable(),

                TextColumn::make('total_coupon_discount')
                    ->label('Total Discount')
                    ->money('USD')
                    ->sortable()
                    ->toggleable(),

                TextColumn::make('trial_extensions_count')
                    ->label('Trial Extensions')
                    ->state(fn ($record) => $record->trial_extensions_count ?? 0)
                    ->alignCenter()
                    ->toggleable(),

                TextColumn::make('subscription_changes_count')
                    ->label('Changes')
                    ->state(fn ($record) => $record->subscription_changes_count ?? 0)
                    ->alignCenter()
                    ->toggleable(),

                TextColumn::make('mrr')
                    ->label('MRR')
                    ->money('USD')
                    ->state(fn ($record) => $record->calculateMRR())
                    ->sortable()
                    ->toggleable(),
            ])
            ->defaultSort('created_at', 'desc')
            ->filters([
                SelectFilter::make('provider')
                    ->options([
                        'stripe' => 'Stripe',
                        'lemon_squeezy' => 'Lemon Squeezy',
                        'polar' => 'Polar.sh',
                        'oxapay' => 'OxaPay',
                        'crypto' => 'Crypto',
                        'activation_key' => 'Activation Key',
                    ]),

                SelectFilter::make('status')
                    ->options([
                        'active' => 'Active',
                        'trialing' => 'Trial',
                        'cancelled' => 'Cancelled',
                        'paused' => 'Paused',
                        'incomplete' => 'Incomplete',
                    ]),

                Filter::make('date_range')
                    ->schema([
                        DatePicker::make('start_date')
                            ->label('Start Date')
                            ->required(),
                        DatePicker::make('end_date')
                            ->label('End Date')
                            ->required(),
                    ])
                    ->query(function (Builder $query, array $data): Builder {
                        return $query
                            ->when(
                                $data['start_date'],
                                fn (Builder $query, $date): Builder => $query->whereDate('subscriptions.created_at', '>=', $date)
                            )
                            ->when(
                                $data['end_date'],
                                fn (Builder $query, $date): Builder => $query->whereDate('subscriptions.created_at', '<=', $date)
                            );
                    }),

                Filter::make('has_coupon_usage')
                    ->label('Has Coupon Usage')
                    ->query(fn (Builder $query): Builder => $query->whereHas('couponUsages')),

                Filter::make('has_trial_extension')
                    ->label('Has Trial Extension')
                    ->query(fn (Builder $query): Builder => $query->whereHas('trialExtensions')),
            ])
            ->emptyStateHeading('No customer data found')
            ->emptyStateDescription('No customer analytics data available for the selected filters.')
            ->emptyStateActions([
                Action::make('reset_filters')
                    ->label('Reset Filters')
                    ->icon('heroicon-o-arrow-path')
                    ->action(fn () => $this->resetTable()),
            ]);
    }

    protected function getCustomerAnalyticsQuery(): Builder
    {
        return Subscription::query()
            ->with(['user', 'plan', 'couponUsages', 'trialExtensions', 'subscriptionChanges'])
            ->withCount(['couponUsages', 'trialExtensions', 'subscriptionChanges'])
            ->when($this->selectedProvider !== 'all', function ($query) {
                $query->where('provider', $this->selectedProvider);
            })
            ->when($this->selectedPlan !== 'all', function ($query) {
                $query->where('plan_id', $this->selectedPlan);
            })
            ->when($this->startDate, function ($query) {
                $query->whereDate('subscriptions.created_at', '>=', $this->startDate);
            })
            ->when($this->endDate, function ($query) {
                $query->whereDate('subscriptions.created_at', '<=', $this->endDate);
            });
    }

    public function exportReport()
    {
        $subscriptions = $this->getCustomerAnalyticsQuery()->get();

        $filename = 'customer_analytics_'.now()->format('Y_m_d_H_i_s').'.csv';

        // Create a temporary file
        $handle = fopen('php://temp', 'r+');

        // Add BOM for Excel UTF-8 support
        fwrite($handle, "\xEF\xBB\xBF");

        // Write headers
        $headers = [
            'Customer', 'Email', 'Plan', 'Provider', 'Status', 'Subscription Age',
            'Total Discount', 'Trial Extensions', 'Subscription Changes', 'MRR',
            'Created At', 'Trial Ends At', 'Ends At',
        ];
        fputcsv($handle, $headers);

        // Write data rows
        foreach ($subscriptions as $subscription) {
            $started = $subscription->starts_at ?? $subscription->created_at;
            fputcsv($handle, [
                $subscription->user?->name ?? 'Unknown',
                $subscription->user?->email ?? 'Unknown',
                $subscription->plan?->name ?? 'Unknown',
                $subscription->provider,
                $subscription->status,
                $started ? $started->diffForHumans() : 'Unknown',
                $subscription->couponUsages()->sum('discount_amount'),
                $subscription->trialExtensions()->count(),
                $subscription->subscriptionChanges()->count(),
                $subscription->calculateMRR(),
                $subscription->created_at->toDateTimeString(),
                $subscription->trial_ends_at?->toDateTimeString() ?? 'N/A',
                $subscription->ends_at?->toDateTimeString() ?? 'N/A',
            ]);
        }

        // Rewind the file pointer
        rewind($handle);

        // Get the CSV content
        $csvContent = stream_get_contents($handle);

        // Close the file handle
        fclose($handle);

        // Return a download response
        return response()->streamDownload(
            function () use ($csvContent) {
                echo $csvContent;
            },
            $filename,
            [
                'Content-Type' => 'text/csv',
                'Content-Disposition' => 'attachment; filename="'.$filename.'"',
            ]
        );
    }
}
