<?php

namespace App\Http\Controllers;

use App\Models\SubscriptionPlan;
use App\Models\UserSubscription;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use App\Models\Transaction;

class SubscriptionPlanController extends Controller
{
    /**
     * Get all active subscription plans (public)
     */
    public function index()
    {
        $plans = SubscriptionPlan::active()
            ->ordered()
            ->get();

        return response()->json([
            'success' => true,
            'plans' => $plans
        ]);
    }

    /**
     * Get a single plan by slug
     */
    public function show($slug)
    {
        $plan = SubscriptionPlan::where('slug', $slug)->first();

        if (!$plan) {
            return response()->json(['error' => 'Plan not found'], 404);
        }

        return response()->json([
            'success' => true,
            'plan' => $plan
        ]);
    }

    /**
     * Get current user's subscription status
     */
    public function mySubscription()
    {
        $user = Auth::user();
        
        $activeSubscription = UserSubscription::with('plan')
            ->where('user_id', $user->id)
            ->active()
            ->first();

        $subscriptionHistory = UserSubscription::with('plan')
            ->where('user_id', $user->id)
            ->orderBy('created_at', 'desc')
            ->limit(10)
            ->get();

        return response()->json([
            'success' => true,
            'has_active_subscription' => (bool) $activeSubscription,
            'active_subscription' => $activeSubscription ? [
                'id' => $activeSubscription->id,
                'plan' => $activeSubscription->plan,
                'starts_at' => $activeSubscription->starts_at,
                'expires_at' => $activeSubscription->expires_at,
                'days_remaining' => $activeSubscription->daysRemaining(),
                'status' => $activeSubscription->status,
            ] : null,
            'history' => $subscriptionHistory
        ]);
    }

    /**
     * Request a subscription (manual payment flow)
     */
    public function requestSubscription(Request $request)
    {
        $request->validate([
            'plan_id' => 'required|exists:subscription_plans,id',
            'payment_reference' => 'nullable|string|max:255',
        ]);

        $user = Auth::user();
        $plan = SubscriptionPlan::findOrFail($request->plan_id);

        if (!$plan->is_active) {
            return response()->json(['error' => 'This plan is not available'], 400);
        }

        // Check if user already has an active subscription
        $existingActive = UserSubscription::where('user_id', $user->id)
            ->active()
            ->first();

        if ($existingActive) {
            return response()->json([
                'error' => 'You already have an active subscription',
                'current_subscription' => $existingActive
            ], 400);
        }

        // Create a pending subscription request
        $subscription = UserSubscription::create([
            'user_id' => $user->id,
            'subscription_plan_id' => $plan->id,
            'starts_at' => now(),
            'expires_at' => now()->addDays($plan->duration_days),
            'status' => 'active', // Will be set to pending if you want admin approval
            'amount_paid' => $plan->price,
            'payment_method' => 'pending',
            'payment_reference' => $request->payment_reference,
        ]);

        Log::info('Subscription requested', [
            'user_id' => $user->id,
            'plan_id' => $plan->id,
            'subscription_id' => $subscription->id
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Subscription request submitted successfully',
            'subscription' => $subscription->load('plan')
        ], 201);
    }

    // ==================== ADMIN ENDPOINTS ====================

    /**
     * Admin: Get all plans (including inactive)
     */
    public function adminIndex()
    {
        $plans = SubscriptionPlan::ordered()->get();

        return response()->json([
            'success' => true,
            'plans' => $plans
        ]);
    }

    /**
     * Admin: Create a new plan
     */
    public function store(Request $request)
    {
        $request->validate([
            'name' => 'required|string|max:255',
            'description' => 'nullable|string',
            'price' => 'required|numeric|min:0',
            'duration_days' => 'required|integer|min:1',
            'duration_type' => 'required|in:daily,weekly,monthly',
            'features' => 'nullable|array',
            'is_active' => 'boolean',
            'sort_order' => 'integer',
        ]);

        $plan = SubscriptionPlan::create([
            'name' => $request->name,
            'slug' => Str::slug($request->name),
            'description' => $request->description,
            'price' => $request->price,
            'duration_days' => $request->duration_days,
            'duration_type' => $request->duration_type,
            'features' => $request->features,
            'is_active' => $request->is_active ?? true,
            'sort_order' => $request->sort_order ?? 0,
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Plan created successfully',
            'plan' => $plan
        ], 201);
    }

    /**
     * Admin: Update a plan
     */
    public function update(Request $request, $id)
    {
        $plan = SubscriptionPlan::find($id);

        if (!$plan) {
            return response()->json(['error' => 'Plan not found'], 404);
        }

        $request->validate([
            'name' => 'string|max:255',
            'description' => 'nullable|string',
            'price' => 'numeric|min:0',
            'duration_days' => 'integer|min:1',
            'duration_type' => 'in:daily,weekly,monthly',
            'features' => 'nullable|array',
            'is_active' => 'boolean',
            'sort_order' => 'integer',
        ]);

        $plan->update($request->only([
            'name', 'description', 'price', 'duration_days', 
            'duration_type', 'features', 'is_active', 'sort_order'
        ]));

        if ($request->has('name')) {
            $plan->update(['slug' => Str::slug($request->name)]);
        }

        return response()->json([
            'success' => true,
            'message' => 'Plan updated successfully',
            'plan' => $plan->fresh()
        ]);
    }

    /**
     * Admin: Delete a plan
     */
    public function destroy($id)
    {
        $plan = SubscriptionPlan::find($id);

        if (!$plan) {
            return response()->json(['error' => 'Plan not found'], 404);
        }

        // Check if plan has active subscriptions
        $activeCount = UserSubscription::where('subscription_plan_id', $id)
            ->active()
            ->count();

        if ($activeCount > 0) {
            return response()->json([
                'error' => 'Cannot delete plan with active subscriptions',
                'active_subscriptions' => $activeCount
            ], 400);
        }

        $plan->delete();

        return response()->json([
            'success' => true,
            'message' => 'Plan deleted successfully'
        ]);
    }

    /**
     * Admin: Get all user subscriptions
     */
    public function adminSubscriptions(Request $request)
    {
        $status = $request->query('status', 'all');
        $page = (int) $request->query('page', 1);
        $limit = (int) $request->query('limit', 20);

        $query = UserSubscription::with(['user', 'plan', 'activatedBy']);

        if ($status !== 'all') {
            if ($status === 'active') {
                $query->active();
            } elseif ($status === 'expired') {
                $query->where('status', 'expired');
            } elseif ($status === 'expiring_soon') {
                $query->expiringSoon(3); // Expiring within 3 days
            }
        }

        $subscriptions = $query->orderBy('created_at', 'desc')
            ->paginate($limit, ['*'], 'page', $page);

        return response()->json([
            'success' => true,
            'subscriptions' => $subscriptions->items(),
            'pagination' => [
                'page' => $subscriptions->currentPage(),
                'limit' => $subscriptions->perPage(),
                'total' => $subscriptions->total(),
                'pages' => $subscriptions->lastPage()
            ]
        ]);
    }

    /**
     * Admin: Get subscription stats
     */
    public function adminStats()
    {
        $totalActive = UserSubscription::active()->count();
        $totalExpired = UserSubscription::where('status', 'expired')->count();
        $expiringSoon = UserSubscription::expiringSoon(3)->count();
        
        $revenueThisMonth = UserSubscription::where('created_at', '>=', now()->startOfMonth())
            ->sum('amount_paid');

        $subscriptionsByPlan = SubscriptionPlan::withCount(['userSubscriptions as active_count' => function ($query) {
            $query->active();
        }])->get()->map(function ($plan) {
            return [
                'plan' => $plan->name,
                'active_subscriptions' => $plan->active_count
            ];
        });

        return response()->json([
            'success' => true,
            'stats' => [
                'total_active' => $totalActive,
                'total_expired' => $totalExpired,
                'expiring_soon' => $expiringSoon,
                'revenue_this_month' => $revenueThisMonth,
                'by_plan' => $subscriptionsByPlan
            ]
        ]);
    }

    /**
     * Admin: Activate subscription for a user
     */
    public function activateSubscription(Request $request)
    {
        $request->validate([
            'user_id' => 'required|exists:users,id',
            'plan_id' => 'required|exists:subscription_plans,id',
            'payment_method' => 'nullable|string|max:255',
            'payment_reference' => 'nullable|string|max:255',
            'admin_notes' => 'nullable|string',
        ]);

        $admin = Auth::user();
        $user = User::findOrFail($request->user_id);
        $plan = SubscriptionPlan::findOrFail($request->plan_id);

        // Check if user already has an active subscription
        $existingActive = UserSubscription::where('user_id', $user->id)
            ->active()
            ->first();

        if ($existingActive) {
            // Extend existing subscription
            $newExpiry = Carbon::parse($existingActive->expires_at)->addDays($plan->duration_days);
            $existingActive->update([
                'expires_at' => $newExpiry,
                'amount_paid' => $existingActive->amount_paid + $plan->price,
                'admin_notes' => $request->admin_notes,
            ]);

            Log::info('Subscription extended by admin', [
                'admin_id' => $admin->id,
                'user_id' => $user->id,
                'subscription_id' => $existingActive->id,
                'new_expiry' => $newExpiry
            ]);

            return response()->json([
                'success' => true,
                'message' => 'Subscription extended successfully',
                'subscription' => $existingActive->fresh()->load('plan')
            ]);
        }

        // Create new subscription
        $subscription = UserSubscription::create([
            'user_id' => $user->id,
            'subscription_plan_id' => $plan->id,
            'starts_at' => now(),
            'expires_at' => now()->addDays($plan->duration_days),
            'status' => 'active',
            'amount_paid' => $plan->price,
            'payment_method' => $request->payment_method ?? 'manual',
            'payment_reference' => $request->payment_reference,
            'admin_notes' => $request->admin_notes,
            'activated_by' => $admin->id,
        ]);

        Log::info('Subscription activated by admin', [
            'admin_id' => $admin->id,
            'user_id' => $user->id,
            'plan_id' => $plan->id,
            'subscription_id' => $subscription->id
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Subscription activated successfully',
            'subscription' => $subscription->load('plan')
        ], 201);
    }

    /**
     * Admin: Extend a subscription
     */
    public function extendSubscription(Request $request, $id)
    {
        $request->validate([
            'days' => 'required|integer|min:1',
            'admin_notes' => 'nullable|string',
        ]);

        $subscription = UserSubscription::find($id);

        if (!$subscription) {
            return response()->json(['error' => 'Subscription not found'], 404);
        }

        $oldExpiry = $subscription->expires_at;
        $baseDate = $subscription->isActive() ? $subscription->expires_at : now();
        $newExpiry = Carbon::parse($baseDate)->addDays($request->days);

        $subscription->update([
            'expires_at' => $newExpiry,
            'status' => 'active',
            'admin_notes' => $request->admin_notes,
        ]);

        Log::info('Subscription extended', [
            'subscription_id' => $id,
            'old_expiry' => $oldExpiry,
            'new_expiry' => $newExpiry,
            'days_added' => $request->days
        ]);

        return response()->json([
            'success' => true,
            'message' => "Subscription extended by {$request->days} days",
            'subscription' => $subscription->fresh()->load('plan')
        ]);
    }

    /**
     * Admin: Cancel a subscription
     */
    public function cancelSubscription(Request $request, $id)
    {
        $subscription = UserSubscription::find($id);

        if (!$subscription) {
            return response()->json(['error' => 'Subscription not found'], 404);
        }

        $subscription->update([
            'status' => 'cancelled',
            'admin_notes' => $request->admin_notes ?? 'Cancelled by admin',
        ]);

        Log::info('Subscription cancelled', [
            'subscription_id' => $id,
            'user_id' => $subscription->user_id
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Subscription cancelled successfully'
        ]);
    }

    /**
     * Admin: Get subscriptions by user
     */
    public function getUserSubscriptions($userId)
    {
        $user = User::find($userId);

        if (!$user) {
            return response()->json(['error' => 'User not found'], 404);
        }

        $subscriptions = UserSubscription::with('plan')
            ->where('user_id', $userId)
            ->orderBy('created_at', 'desc')
            ->get();

        $activeSubscription = $subscriptions->first(function ($sub) {
            return $sub->isActive();
        });

        return response()->json([
            'success' => true,
            'user' => [
                'id' => $user->id,
                'name' => $user->name,
                'email' => $user->email,
            ],
            'has_active_subscription' => (bool) $activeSubscription,
            'active_subscription' => $activeSubscription,
            'all_subscriptions' => $subscriptions
        ]);
    }

    /**
     * Check if user has active subscription (middleware helper)
     */
    public function checkAccess()
    {
        $user = Auth::user();
        
        $hasAccess = UserSubscription::where('user_id', $user->id)
            ->active()
            ->exists();

        return response()->json([
            'has_access' => $hasAccess
        ]);
    }

    /**
     * Verify Paystack payment and activate subscription
     */
    public function verifyPaystackPayment(Request $request)
    {
        Log::info('Subscription plan Paystack payment verification', $request->all());

        $reference = $request->input('reference');
        $country = $request->input('country');
        $planId = $request->input('plan_id');
        $normalizedCountry = strtolower($country ?? 'ghana');

        if (!$reference) {
            return response()->json(['status' => 'failed', 'message' => 'Reference is required'], 400);
        }

        if (!$planId) {
            return response()->json(['status' => 'failed', 'message' => 'Plan ID is required'], 400);
        }

        // Get the plan
        $plan = SubscriptionPlan::find($planId);
        if (!$plan) {
            return response()->json(['status' => 'failed', 'message' => 'Plan not found'], 404);
        }

        // Check if transaction already processed
        $existingTransaction = Transaction::where('reference', $reference)->first();
        if ($existingTransaction) {
            return response()->json(['status' => 'failed', 'message' => 'Transaction already processed'], 400);
        }

        // Select Paystack secret key based on country
        // Using live keys for production
        $secretKey = '';
        if ($normalizedCountry == "nigeria") {
            $secretKey = 'sk_live_69997ecfeba45df388ed13da6baf41068e3ec3d0'; // Nigeria live
        } else {
            $secretKey = "sk_live_c7c66e812fa33649e7eeb9248862a31e69b9811d"; // Ghana live
        }

        // Verify with Paystack
        $response = Http::withToken($secretKey)->get("https://api.paystack.co/transaction/verify/{$reference}");

        if ($response->successful()) {
            $transactionData = $response->json()['data'];

            if ($transactionData['status'] === 'success') {
                $email = $transactionData['customer']['email'];
                $user = User::where('email', $email)->first();

                if (!$user) {
                    return response()->json(['status' => 'failed', 'message' => 'User not found'], 404);
                }

                $amountPaid = $transactionData['amount'] / 100;

                // Check if user already has active subscription
                $existingActive = UserSubscription::where('user_id', $user->id)
                    ->active()
                    ->first();

                if ($existingActive) {
                    // Extend existing subscription
                    $newExpiry = Carbon::parse($existingActive->expires_at)->addDays($plan->duration_days);
                    $existingActive->update([
                        'expires_at' => $newExpiry,
                        'amount_paid' => $existingActive->amount_paid + $amountPaid,
                    ]);

                    // Create transaction record
                    Transaction::create([
                        'reference' => $reference,
                        'user_id' => $user->id,
                        'amount' => $amountPaid,
                        'status' => 'success',
                        'gateway_response' => $transactionData['gateway_response'],
                        'channel' => $transactionData['channel'],
                        'paid_at' => Carbon::now(),
                    ]);

                    Log::info('Subscription extended via Paystack', [
                        'user_id' => $user->id,
                        'subscription_id' => $existingActive->id,
                        'new_expiry' => $newExpiry
                    ]);

                    return response()->json([
                        'status' => 'success',
                        'message' => 'Subscription extended successfully',
                        'subscription' => $existingActive->fresh()->load('plan')
                    ]);
                }

                // Create new subscription
                $subscription = UserSubscription::create([
                    'user_id' => $user->id,
                    'subscription_plan_id' => $plan->id,
                    'starts_at' => now(),
                    'expires_at' => now()->addDays($plan->duration_days),
                    'status' => 'active',
                    'amount_paid' => $amountPaid,
                    'payment_method' => 'paystack',
                    'payment_reference' => $reference,
                ]);

                // Create transaction record
                Transaction::create([
                    'reference' => $reference,
                    'user_id' => $user->id,
                    'amount' => $amountPaid,
                    'status' => 'success',
                    'gateway_response' => $transactionData['gateway_response'],
                    'channel' => $transactionData['channel'],
                    'paid_at' => Carbon::now(),
                ]);

                Log::info('Subscription created via Paystack', [
                    'user_id' => $user->id,
                    'plan_id' => $plan->id,
                    'subscription_id' => $subscription->id
                ]);

                return response()->json([
                    'status' => 'success',
                    'message' => 'Subscription activated successfully',
                    'subscription' => $subscription->load('plan')
                ]);

            } else {
                return response()->json([
                    'status' => 'failed',
                    'message' => 'Payment not successful: ' . $transactionData['status']
                ], 400);
            }
        } else {
            Log::error('Paystack verification failed', ['response' => $response->json()]);
            return response()->json([
                'status' => 'failed',
                'message' => 'Payment verification failed'
            ], 400);
        }
    }
}
