<?php

namespace App\Filament\Association\Pages;

use App\Models\Payment;
use App\Models\PaymentProof;
use App\Models\PlatformBankAccount;
use App\Models\PlatformSubscription;
use App\Models\SubscriptionPlan;
use App\Services\SubscriptionService;
use Filament\Actions\Action;
use Filament\Forms;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Filament\Tables;
use Filament\Tables\Concerns\InteractsWithTable;
use Filament\Tables\Contracts\HasTable;
use Filament\Tables\Table;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Storage;

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

    protected static ?string $navigationIcon = 'heroicon-o-credit-card';

    protected static ?string $navigationGroup = 'Settings';

    protected static ?string $navigationLabel = 'Subscription';

    protected static ?int $navigationSort = 99;

    protected static string $view = 'filament.association.pages.subscription';

    public function getTitle(): string
    {
        return 'Subscription Management';
    }

    // ── Data for the Blade view ──────────────────────────────────

    public function getAssociationProperty()
    {
        return \Filament\Facades\Filament::getTenant();
    }

    public function getCurrentSubscriptionProperty(): ?PlatformSubscription
    {
        return $this->association
            ->platformSubscriptions()
            ->whereIn('status', ['active', 'trial', 'pending'])
            ->latest()
            ->first();
    }

    public function getAvailablePlansProperty()
    {
        return SubscriptionPlan::active()->ordered()->get();
    }

    public function getCurrentPlanProperty(): ?SubscriptionPlan
    {
        return $this->association->subscriptionPlan;
    }

    public function getMemberUsageProperty(): array
    {
        $association = $this->association;
        return [
            'current' => $association->current_member_count,
            'limit' => $association->max_members,
            'percentage' => $association->max_members > 0
                ? min(100, round(($association->current_member_count / $association->max_members) * 100))
                : 0,
        ];
    }

    // ── Payment History Table ────────────────────────────────────

    public function table(Table $table): Table
    {
        return $table
            ->query(
                Payment::query()
                    ->where('association_id', $this->association->id)
                    ->where('payable_type', PlatformSubscription::class)
            )
            ->columns([
                Tables\Columns\TextColumn::make('reference')
                    ->searchable()
                    ->copyable(),
                Tables\Columns\TextColumn::make('amount')
                    ->money('NGN'),
                Tables\Columns\TextColumn::make('payment_method')
                    ->badge()
                    ->color(fn (?string $state): string => match ($state) {
                        'card' => 'success',
                        'bank_transfer' => 'info',
                        default => 'gray',
                    }),
                Tables\Columns\TextColumn::make('status')
                    ->badge()
                    ->color(fn (string $state): string => match ($state) {
                        'completed' => 'success',
                        'pending' => 'warning',
                        'failed' => 'danger',
                        'cancelled' => 'gray',
                        default => 'gray',
                    }),
                Tables\Columns\TextColumn::make('paid_at')
                    ->dateTime('M d, Y H:i')
                    ->placeholder('—'),
                Tables\Columns\TextColumn::make('created_at')
                    ->dateTime('M d, Y H:i')
                    ->label('Initiated'),
            ])
            ->defaultSort('created_at', 'desc')
            ->emptyStateHeading('No subscription payments')
            ->emptyStateDescription('Subscription payments will appear here once you subscribe to a plan.');
    }

    // ── Actions ──────────────────────────────────────────────────

    /**
     * Subscribe to a plan via Paystack card payment.
     */
    public function subscribeWithCard(int $planId): void
    {
        $plan = SubscriptionPlan::findOrFail($planId);
        $service = app(SubscriptionService::class);

        try {
            $result = $service->initiateSubscription(
                association: $this->association,
                plan: $plan,
                paymentMethod: 'card',
                user: auth()->user(),
            );

            if (isset($result['authorization_url'])) {
                $this->redirect($result['authorization_url']);
                return;
            }

            Notification::make()
                ->danger()
                ->title('Payment Error')
                ->body('Could not initialize payment. Please try again.')
                ->send();
        } catch (\Throwable $e) {
            Notification::make()
                ->danger()
                ->title('Payment Error')
                ->body($e->getMessage())
                ->send();
        }
    }

    /**
     * Subscribe to a plan via bank transfer — shows form to upload proof.
     */
    public function subscribeBankTransferAction(): Action
    {
        return Action::make('subscribeBankTransfer')
            ->label('Pay via Bank Transfer')
            ->modalHeading('Bank Transfer Payment')
            ->modalWidth('xl')
            ->form(function () {
                $bankAccounts = PlatformBankAccount::active()->ordered()->get();

                $bankOptions = $bankAccounts->mapWithKeys(fn ($account) => [
                    $account->id => "{$account->bank_name} — {$account->account_number} ({$account->account_name})",
                ])->toArray();

                $plans = SubscriptionPlan::active()->ordered()->get();
                $planOptions = $plans->mapWithKeys(fn ($plan) => [
                    $plan->id => "{$plan->name} — ₦" . number_format($plan->price, 2) . "/{$plan->billing_cycle}",
                ])->toArray();

                return [
                    Forms\Components\Select::make('plan_id')
                        ->label('Select Plan')
                        ->options($planOptions)
                        ->required(),
                    Forms\Components\Select::make('bank_account_id')
                        ->label('Bank Transferred To')
                        ->options($bankOptions)
                        ->required()
                        ->helperText('Select the bank account you transferred to.'),
                    Forms\Components\TextInput::make('amount')
                        ->label('Amount Transferred')
                        ->numeric()
                        ->required()
                        ->prefix('NGN'),
                    Forms\Components\DatePicker::make('transfer_date')
                        ->label('Transfer Date')
                        ->required()
                        ->maxDate(now()),
                    Forms\Components\TextInput::make('account_name')
                        ->label('Your Account Name')
                        ->required()
                        ->maxLength(255),
                    Forms\Components\TextInput::make('bank_name')
                        ->label('Your Bank Name')
                        ->required()
                        ->maxLength(255),
                    Forms\Components\FileUpload::make('receipt')
                        ->label('Transfer Receipt')
                        ->required()
                        ->image()
                        ->acceptedFileTypes(['image/*', 'application/pdf'])
                        ->directory('payment-proofs')
                        ->maxSize(5120),
                ];
            })
            ->action(function (array $data) {
                $plan = SubscriptionPlan::findOrFail($data['plan_id']);
                $service = app(SubscriptionService::class);

                // Create the subscription and payment via the service
                $result = $service->initiateSubscription(
                    association: $this->association,
                    plan: $plan,
                    paymentMethod: 'bank_transfer',
                    user: auth()->user(),
                );

                $payment = $result['payment'];

                // Create payment proof
                $proof = PaymentProof::create([
                    'association_id' => $this->association->id,
                    'user_id' => auth()->id(),
                    'bank_name' => $data['bank_name'],
                    'account_name' => $data['account_name'],
                    'account_number' => '',
                    'amount' => $data['amount'],
                    'transfer_date' => $data['transfer_date'],
                    'receipt_file_path' => $data['receipt'],
                    'status' => 'pending',
                ]);

                // Link proof to payment
                $payment->update(['manual_proof_id' => $proof->id]);

                Notification::make()
                    ->success()
                    ->title('Transfer Proof Submitted')
                    ->body('Your payment proof has been submitted and is awaiting verification by the platform administrator.')
                    ->send();
            });
    }

    /**
     * Start a free trial.
     */
    public function startTrial(int $planId): void
    {
        $plan = SubscriptionPlan::findOrFail($planId);

        // Check if association already had a trial
        $hadTrial = $this->association->platformSubscriptions()
            ->where('status', 'trial')
            ->orWhere(fn ($q) => $q->whereNotNull('trial_ends_at'))
            ->exists();

        if ($hadTrial) {
            Notification::make()
                ->warning()
                ->title('Trial Not Available')
                ->body('Your association has already used a trial period.')
                ->send();
            return;
        }

        $service = app(SubscriptionService::class);
        $service->startTrial($this->association, $plan, auth()->user());

        Notification::make()
            ->success()
            ->title('Trial Started')
            ->body("Your {$plan->trial_duration_days}-day trial of the {$plan->name} plan has started!")
            ->send();
    }
}
