<?php

namespace App\Filament\Clusters\DailyOps\Resources\TenantPaddleHealths\Tables;

use App\Filament\Clusters\DailyOps\Resources\TenantPaddleHealths\TenantPaddleHealthResource;
use App\Models\CheckoutSession;
use App\Models\Tenant;
use Filament\Forms\Components\TextInput;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\Filter;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Carbon;
use Illuminate\Support\Str;

class TenantPaddleHealthTable
{
    private const FAILED_SYNC_STATUSES = ['failed', 'pull-failed'];

    public static function configure(Table $table): Table
    {
        return $table
            ->columns([
                TextColumn::make('name')
                    ->label(__('admin.common.tenant'))
                    ->searchable()
                    ->sortable(),
                TextColumn::make('slug')
                    ->label(__('admin.common.slug'))
                    ->searchable()
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('contact_email')
                    ->label(__('admin.tenants.fields.contact_email'))
                    ->searchable()
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('paddle_customer_id')
                    ->label('Paddle customer')
                    ->toggleable(isToggledHiddenByDefault: true)
                    ->copyable()
                    ->formatStateUsing(fn (?string $state) => $state ?: '—'),
                TextColumn::make('subscription_status')
                    ->label('Subscription')
                    ->badge()
                    ->color(fn (?string $state) => match ($state) {
                        'active' => 'success',
                        'suspended' => 'warning',
                        'expired' => 'danger',
                        'free' => 'gray',
                        default => 'gray',
                    }),
                TextColumn::make('active_reseller_package')
                    ->label('Active package')
                    ->getStateUsing(fn (Tenant $record) => $record->activeResellerPackage?->package?->name ?? '—')
                    ->badge()
                    ->color(fn (string $state) => $state === '—' ? 'gray' : 'success')
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('paddle_subscription_id')
                    ->label('Paddle subscription')
                    ->toggleable(isToggledHiddenByDefault: true)
                    ->copyable()
                    ->getStateUsing(fn (Tenant $record) => $record->activeResellerPackage?->paddle_subscription_id)
                    ->formatStateUsing(fn (?string $state) => $state ?: '—'),
                IconColumn::make('missing_paddle_subscription')
                    ->label('Missing Paddle subscription')
                    ->boolean()
                    ->getStateUsing(fn (Tenant $record) => self::missingPaddleSubscription($record)),
                IconColumn::make('status_mismatch')
                    ->label('Status mismatch')
                    ->boolean()
                    ->getStateUsing(fn (Tenant $record) => self::hasStatusMismatch($record)),
                TextColumn::make('paddle_customer_duplicates')
                    ->label('Paddle duplicates')
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true)
                    ->formatStateUsing(fn (?int $state) => $state && $state > 1 ? (string) $state : '—'),
                TextColumn::make('paddle_sync_status')
                    ->label('Paddle sync')
                    ->badge()
                    ->color(fn (?string $state) => match ($state) {
                        'synced' => 'success',
                        'syncing' => 'warning',
                        'pulled' => 'info',
                        'dry-run' => 'gray',
                        'failed', 'pull-failed' => 'danger',
                        default => 'gray',
                    })
                    ->formatStateUsing(fn (?string $state) => $state ? Str::headline($state) : '—')
                    ->getStateUsing(fn (Tenant $record) => $record->activeResellerPackage?->package?->paddle_sync_status)
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('paddle_synced_at')
                    ->label('Paddle synced')
                    ->badge()
                    ->color(fn ($state) => self::syncAgeColor($state))
                    ->formatStateUsing(fn ($state) => $state?->diffForHumans() ?? '—')
                    ->getStateUsing(fn (Tenant $record) => $record->activeResellerPackage?->package?->paddle_synced_at),
                TextColumn::make('last_paddle_transaction_at')
                    ->label('Last Paddle tx')
                    ->badge()
                    ->color(fn (?Carbon $state) => self::transactionAgeColor($state))
                    ->getStateUsing(fn (Tenant $record) => $record->last_paddle_transaction_at
                        ? Carbon::parse($record->last_paddle_transaction_at)
                        : null)
                    ->formatStateUsing(fn (?Carbon $state) => $state?->diffForHumans() ?? '—')
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('paddle_transaction_count_window')
                    ->label('Paddle tx (30d)')
                    ->default('0')
                    ->sortable()
                    ->toggleable(),
                TextColumn::make('paddle_transaction_total_window')
                    ->label('Paddle total (30d)')
                    ->default(0)
                    ->money('EUR')
                    ->sortable()
                    ->toggleable(),
                TextColumn::make('paddle_refund_count_window')
                    ->label('Refunds (30d)')
                    ->badge()
                    ->color(fn (?int $state) => $state && $state > 0 ? 'danger' : 'gray')
                    ->default('0')
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('paddle_refund_total_window')
                    ->label('Refund total (30d)')
                    ->default(0)
                    ->money('EUR')
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('paddle_checkout_requires_action_count')
                    ->label('Checkout action required')
                    ->badge()
                    ->color(fn (?int $state) => $state && $state > 0 ? 'warning' : 'gray')
                    ->default('0')
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('paddle_checkout_processing_count')
                    ->label('Checkout processing')
                    ->badge()
                    ->color(fn (?int $state) => $state && $state > 0 ? 'warning' : 'gray')
                    ->default('0')
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('paddle_checkout_expired_count')
                    ->label('Checkout expired')
                    ->badge()
                    ->color(fn (?int $state) => $state && $state > 0 ? 'danger' : 'gray')
                    ->default('0')
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('paddle_transaction_count')
                    ->label('Paddle tx (all)')
                    ->default('0')
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('paddle_transaction_total')
                    ->label('Paddle total (all)')
                    ->default(0)
                    ->money('EUR')
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true),
            ])
            ->filters([
                Filter::make('missing_paddle_customer')
                    ->label('Missing Paddle customer')
                    ->indicator('Missing Paddle customer')
                    ->query(fn (Builder $query) => $query->whereNull('paddle_customer_id')),
                Filter::make('missing_paddle_subscription')
                    ->label('Missing Paddle subscription')
                    ->indicator('Missing Paddle subscription')
                    ->query(fn (Builder $query) => $query->whereHas('activeResellerPackage', fn (Builder $query) => $query
                        ->where('active', true)
                        ->whereNull('paddle_subscription_id'))),
                Filter::make('duplicate_paddle_customer')
                    ->label('Duplicate Paddle customer')
                    ->indicator('Duplicate Paddle customer')
                    ->query(fn (Builder $query) => $query
                        ->whereNotNull('paddle_customer_id')
                        ->whereIn('paddle_customer_id', function ($subquery) {
                            $subquery->select('paddle_customer_id')
                                ->from('tenants')
                                ->whereNotNull('paddle_customer_id')
                                ->groupBy('paddle_customer_id')
                                ->havingRaw('count(*) > 1');
                        })),
                Filter::make('status_mismatch')
                    ->label('Status mismatch')
                    ->indicator('Status mismatch')
                    ->query(fn (Builder $query) => self::applyStatusMismatchFilter($query)),
                Filter::make('active_package')
                    ->label('Active package')
                    ->indicator('Active package')
                    ->query(fn (Builder $query) => $query->whereHas('activeResellerPackage', function (Builder $query) {
                        $query->where('active', true)
                            ->where(function (Builder $query) {
                                $query->whereNull('expires_at')
                                    ->orWhere('expires_at', '>=', now());
                            });
                    })),
                Filter::make('not_suspended_or_deleted')
                    ->label('Not suspended/deleted')
                    ->indicator('Not suspended/deleted')
                    ->query(fn (Builder $query) => $query
                        ->where('is_suspended', false)
                        ->whereNull('pending_deletion_at')
                        ->whereNull('anonymized_at')),
                Filter::make('paddle_sync_failed')
                    ->label('Paddle sync failed')
                    ->indicator('Paddle sync failed')
                    ->query(fn (Builder $query) => $query->whereHas('activeResellerPackage.package', fn (Builder $query) => $query
                        ->whereIn('paddle_sync_status', self::FAILED_SYNC_STATUSES))),
                Filter::make('paddle_sync_stale')
                    ->label('Paddle sync stale')
                    ->indicator('Paddle sync stale')
                    ->query(fn (Builder $query) => $query->whereHas('activeResellerPackage.package', fn (Builder $query) => $query
                        ->whereNotNull('paddle_synced_at')
                        ->where('paddle_synced_at', '<', now()->subDays(TenantPaddleHealthResource::STALE_SYNC_DAYS)))),
                Filter::make('paddle_sync_missing')
                    ->label('Missing Paddle sync timestamp')
                    ->indicator('Missing Paddle sync timestamp')
                    ->query(fn (Builder $query) => $query->whereHas('activeResellerPackage.package', fn (Builder $query) => $query
                        ->whereNull('paddle_synced_at'))),
                Filter::make('paddle_transaction_stale')
                    ->label('Stale Paddle transactions')
                    ->indicator('Stale Paddle transactions')
                    ->query(function (Builder $query): Builder {
                        $cutoff = now()->subDays(TenantPaddleHealthResource::TRANSACTION_WINDOW_DAYS);

                        return $query
                            ->whereHas('purchases', fn (Builder $query) => $query->where('provider', 'paddle'))
                            ->whereDoesntHave('purchases', fn (Builder $query) => $query
                                ->where('provider', 'paddle')
                                ->where('purchased_at', '>=', $cutoff));
                    }),
                Filter::make('checkout_attention')
                    ->label('Checkout attention')
                    ->indicator('Checkout attention')
                    ->query(fn (Builder $query) => $query->whereHas('checkoutSessions', function (Builder $query) {
                        $query->where('provider', 'paddle')
                            ->where(function (Builder $query) {
                                $query->whereIn('status', [
                                    CheckoutSession::STATUS_REQUIRES_CUSTOMER_ACTION,
                                    CheckoutSession::STATUS_PROCESSING,
                                ])
                                    ->orWhere(function (Builder $query) {
                                        $query->whereNotIn('status', [
                                            CheckoutSession::STATUS_COMPLETED,
                                            CheckoutSession::STATUS_CANCELLED,
                                        ])
                                            ->whereNotNull('expires_at')
                                            ->where('expires_at', '<', now());
                                    });
                            });
                    })),
                Filter::make('refund_spike')
                    ->label('Refund spike (30d)')
                    ->form([
                        TextInput::make('min_refunds')
                            ->label('Minimum refunds')
                            ->numeric()
                            ->default(1)
                            ->minValue(1),
                    ])
                    ->indicateUsing(function (array $data): ?string {
                        $min = (int) ($data['min_refunds'] ?? 0);

                        return $min > 0 ? "Refunds >= {$min} (30d)" : null;
                    })
                    ->query(function (Builder $query, array $data): Builder {
                        $min = (int) ($data['min_refunds'] ?? 0);

                        if ($min < 1) {
                            return $query;
                        }

                        $cutoff = now()->subDays(TenantPaddleHealthResource::TRANSACTION_WINDOW_DAYS);

                        return $query->whereHas('purchases', fn (Builder $query) => $query
                            ->where('provider', 'paddle')
                            ->where('refunded', true)
                            ->where('purchased_at', '>=', $cutoff), '>=', $min);
                    }),
                SelectFilter::make('subscription_status')
                    ->label('Subscription')
                    ->options([
                        'active' => 'Active',
                        'suspended' => 'Suspended',
                        'expired' => 'Expired',
                        'free' => 'Free',
                    ]),
            ])
            ->actions([]);
    }

    private static function hasStatusMismatch(Tenant $record): bool
    {
        $hasActivePackage = (bool) ($record->has_active_reseller_package ?? $record->activeResellerPackage);
        $status = (string) ($record->subscription_status ?? '');
        $expiresAt = $record->subscription_expires_at;

        if ($status === 'active' && ! $hasActivePackage) {
            return true;
        }

        if ($status !== 'active' && $hasActivePackage) {
            return true;
        }

        if ($status === 'active' && $expiresAt && $expiresAt->isPast()) {
            return true;
        }

        return false;
    }

    private static function missingPaddleSubscription(Tenant $record): bool
    {
        $package = $record->activeResellerPackage;

        return $package && $package->active && ! $package->paddle_subscription_id;
    }

    private static function applyStatusMismatchFilter(Builder $query): Builder
    {
        return $query->where(function (Builder $query) {
            $query->where(function (Builder $query) {
                $query->where('subscription_status', 'active')
                    ->whereDoesntHave('activeResellerPackage');
            })->orWhere(function (Builder $query) {
                $query->where('subscription_status', '!=', 'active')
                    ->whereHas('activeResellerPackage');
            })->orWhere(function (Builder $query) {
                $query->where('subscription_status', 'active')
                    ->whereNotNull('subscription_expires_at')
                    ->where('subscription_expires_at', '<', now());
            });
        });
    }

    private static function syncAgeColor($state): string
    {
        if (! $state) {
            return 'gray';
        }

        if ($state->lt(now()->subDays(TenantPaddleHealthResource::STALE_SYNC_DAYS))) {
            return 'danger';
        }

        return 'success';
    }

    private static function transactionAgeColor(?Carbon $state): string
    {
        if (! $state) {
            return 'gray';
        }

        if ($state->lt(now()->subDays(TenantPaddleHealthResource::TRANSACTION_WINDOW_DAYS))) {
            return 'danger';
        }

        return 'success';
    }
}
