<?php

namespace App\Livewire\Dashboard;

use App\Models\ActivationKey;
use App\Models\Plan;
use App\Models\PlanTier;
use Exception;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Log;
use Livewire\Component;

class Pricing extends Component
{
    public $plans;

    public $planTiers;

    public $activation_key;

    public $selectedProvider = 'stripe';

    public $selectedBillingCycle = null;

    public $selectedTier = null;

    public function mount(): void
    {
        $this->loadPlans();
        $this->planTiers = PlanTier::with('plans')->orderBy('sort_order')->get();
    }

    private function loadPlans(): void
    {
        $query = Plan::active()
            ->ordered()
            ->with(['planFeatureLimits.planFeature', 'planProviders', 'trialConfiguration', 'planTier']);

        if ($this->selectedTier) {
            $query->where('plan_tier_id', $this->selectedTier);
        }

        $this->plans = $query->get();
    }

    public function filterByTier($tierId = null): void
    {
        $this->selectedTier = $tierId;
        $this->loadPlans();
    }

    public function choosePlan($planId, $provider = 'stripe'): void
    {
        $plan = Plan::findOrFail($planId);

        if (! $plan?->supportsProvider($provider)) {
            session()->flash('error', "This plan doesn't support {$provider} payments.");

            return;
        }

        $this->redirect(route('checkout.enhanced', [
            'plan' => $planId,
            'provider' => $provider,
        ]));
    }

    public function startTrial($planId, $provider = 'stripe'): void
    {
        $plan = Plan::findOrFail($planId);

        if (! $plan?->hasTrial()) {
            session()->flash('error', "This plan doesn't offer trials.");

            return;
        }

        if (! $plan?->supportsProvider($provider)) {
            session()->flash('error', "This plan doesn't support {$provider} payments for trials.");

            return;
        }

        $this->redirect(route('checkout.trial', [
            'plan' => $planId,
            'provider' => $provider,
        ]));
    }

    public function activateKey(): void
    {
        $this->validate([
            'activation_key' => 'required|alpha_num|max:30',
        ], [
            'activation_key.required' => 'You must enter an activation key.',
            'activation_key.alpha_num' => 'The activation key may only contain letters and numbers (no special characters).',
            'activation_key.max' => 'The activation key must not exceed 30 characters.',
        ]);

        $trimmedKey = trim((string) $this->activation_key);
        $activation = ActivationKey::query()->where('activation_key', $trimmedKey)
            ->where('is_activated', false)
            ->first();

        if ($activation) {
            try {
                $result = $this->activateSubscriptionKey($activation);
                if ($result) {
                    session()->flash('success', 'Activation key is valid and has been activated. Refresh page to see changes.');
                    $this->reset('activation_key');
                } else {
                    session()->flash('error', 'Something went wrong. Kindly drop a mail at contact@zemail.me to activate your subscription manually.');
                }
            } catch (Exception $e) {
                Log::error('Activation key error: '.$e->getMessage());
                session()->flash('error', 'An error occurred while activating your key. Please contact support.');
            }
        } else {
            session()->flash('error', 'Invalid or already activated key.');
        }
    }

    private function activateSubscriptionKey(ActivationKey $activation): bool
    {
        try {
            // Use the ActivationKeyProvider directly
            $provider = app(\App\Services\Payments\Providers\ActivationKeyProvider::class);
            $user = auth()->user();

            // Redeem the activation key using the provider
            $result = $provider->redeemActivationKey($activation->activation_key, $user);

            if ($result['success']) {
                // Mark activation key as used
                $activation->is_activated = true;
                $activation->user_id = $user->id;
                $activation->save();

                return true;
            }

            Log::error('Activation key redemption failed: '.$result['message'] ?? 'Unknown error');

            return false;
        } catch (Exception $e) {
            Log::error('Activation key processing failed: '.$e->getMessage());

            return false;
        }
    }

    /**
     * Get available providers for a plan
     */
    public function getPlanProviders($planId): array
    {
        $plan = $this->plans->firstWhere('id', $planId);

        return $plan ? $plan->getAllowedProviders() : [];
    }

    /**
     * Get plan features with limits
     */
    public function getPlanFeatures($planId): array
    {
        $plan = $this->plans->firstWhere('id', $planId);

        if (! $plan) {
            return [];
        }

        return $plan->getFeaturesWithLimits();
    }

    /**
     * Check if plan has trial available
     */
    public function planHasTrial($planId): bool
    {
        $plan = $this->plans->firstWhere('id', $planId);

        return $plan ? $plan->hasTrial() : false;
    }

    /**
     * Get trial configuration for plan
     */
    public function getTrialConfig($planId): ?array
    {
        $plan = $this->plans->firstWhere('id', $planId);
        if (! $plan || ! $plan->hasTrial()) {
            return null;
        }

        $config = $plan->getTrialConfig();

        return [
            'duration_days' => $config->trial_duration_days,
            'requires_payment_method' => $config->trial_requires_payment_method,
            'auto_converts' => $config->trial_auto_converts,
        ];
    }

    /**
     * Get billing cycle display text
     */
    public function getBillingCycleDisplay($plan): string
    {
        return $plan->getBillingCycleDisplay();
    }

    public function render(): Factory|View
    {
        return view('livewire.dashboard.pricing');
    }
}
