<?php

namespace App\Http\Controllers\User;

use App\Http\Controllers\Controller;
use App\Models\Plan;
use App\Models\PaymentMethod;
use App\Models\Subscription;
use App\Models\SubscriptionRequest;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class SubscriptionController extends Controller
{
    private function uploadToPublic($file, string $folder): string
    {
        $dir = public_path('uploads/' . trim($folder, '/'));

        if (!file_exists($dir)) {
            mkdir($dir, 0755, true);
        }

        $filename = Auth::id() . '_' . time() . '_' . uniqid() . '.' . $file->getClientOriginalExtension();
        $file->move($dir, $filename);

        return 'uploads/' . trim($folder, '/') . '/' . $filename;
    }

    public function index()
    {
        $userId = auth()->id();

        $pendingRequest = SubscriptionRequest::with(['plan', 'paymentMethod'])
            ->where('user_id', $userId)
            ->where('status', 'pending')
            ->latest()
            ->first();

        $activeSubscription = Subscription::with('plan')
            ->where('user_id', $userId)
            ->where('status', 'active')
            ->where('is_trial', false)
            ->latest()
            ->first();

        $plans = collect();

        if (!$pendingRequest && !$activeSubscription) {
            $plans = Plan::where('status', true)
                ->where('is_trial', false)
                ->orderBy('price')
                ->get();
        }

        $selectedPlanId = session('selected_plan_id');

        return view('user.subscriptions.index', compact(
            'plans',
            'pendingRequest',
            'activeSubscription',
            'selectedPlanId'
        ));
    }

    public function history()
    {
        $userId = auth()->id();

        $subscriptions = Subscription::with('plan')
            ->where('user_id', $userId)
            ->latest()
            ->paginate(10)
            ->withQueryString();

        $activeSubscription = Subscription::with('plan')
            ->where('user_id', $userId)
            ->where('status', 'active')
            ->latest()
            ->first();

        $remainingSeconds = 0;

        if ($activeSubscription && $activeSubscription->end_date) {
            $remainingSeconds = max(0, now()->diffInSeconds($activeSubscription->end_date, false));
        }

        return view('user.subscriptions.history', compact(
            'subscriptions',
            'activeSubscription',
            'remainingSeconds'
        ));
    }

    public function selectPlan(Request $request)
    {
        $userId = auth()->id();

        $request->validate([
            'plan_id' => ['required', 'exists:plans,id'],
        ]);

        if (SubscriptionRequest::where('user_id', $userId)->where('status', 'pending')->exists()) {
            return back()->with('error', 'Pending request already exists');
        }

        if (Subscription::where('user_id', $userId)->where('status', 'active')->where('is_trial', false)->exists()) {
            return back()->with('error', 'Active plan already exists');
        }

        $plan = Plan::where('status', true)
            ->where('is_trial', false)
            ->findOrFail($request->plan_id);

        session(['selected_plan_id' => $plan->id]);

        return redirect()->route('user.subscriptions.methods');
    }

    public function methods()
    {
        $userId = auth()->id();
        $selectedPlanId = session('selected_plan_id');

        if (!$selectedPlanId) {
            return redirect()->route('user.subscriptions.index')->with('error', 'Select plan first');
        }

        if (SubscriptionRequest::where('user_id', $userId)->where('status', 'pending')->exists()) {
            return back()->with('error', 'Pending request exists');
        }

        if (Subscription::where('user_id', $userId)->where('status', 'active')->where('is_trial', false)->exists()) {
            return back()->with('error', 'Active plan exists');
        }

        $plan = Plan::where('status', true)
            ->where('is_trial', false)
            ->findOrFail($selectedPlanId);

        $methods = PaymentMethod::where('status', true)->latest()->get();

        return view('user.subscriptions.methods', compact('plan', 'methods'));
    }

    public function paymentPage($methodId)
    {
        $selectedPlanId = session('selected_plan_id');

        if (!$selectedPlanId) {
            return redirect()->route('user.subscriptions.index')->with('error', 'Select plan first');
        }

        $method = PaymentMethod::where('status', true)->findOrFail($methodId);

        $plan = Plan::where('status', true)
            ->where('is_trial', false)
            ->findOrFail($selectedPlanId);

        return view('user.subscriptions.payment', compact('plan', 'method'));
    }

    public function submit(Request $request)
    {
        $userId = auth()->id();
        $selectedPlanId = session('selected_plan_id');

        if (!$selectedPlanId) {
            return redirect()->route('user.subscriptions.index')->with('error', 'Select plan first');
        }

        $plan = Plan::where('status', true)
            ->where('is_trial', false)
            ->findOrFail($selectedPlanId);

        $request->validate([
            'payment_method_id'  => ['required', 'exists:payment_methods,id'],
            'trx_id'             => ['required', 'string', 'max:100', 'unique:subscription_requests,trx_id'],
            'payment_screenshot' => ['nullable', 'image', 'mimes:jpg,jpeg,png,webp', 'max:2048'],
        ]);

        if (SubscriptionRequest::where('user_id', $userId)->where('status', 'pending')->exists()) {
            return back()->with('error', 'Pending request exists');
        }

        if (Subscription::where('user_id', $userId)->where('status', 'active')->where('is_trial', false)->exists()) {
            return back()->with('error', 'Active plan exists');
        }

        $paymentMethod = PaymentMethod::where('status', true)
            ->findOrFail($request->payment_method_id);

        $path = null;

        if ($request->hasFile('payment_screenshot')) {
            $path = $this->uploadToPublic($request->file('payment_screenshot'), 'subscription_screenshots');
        }

        $subscriptionRequest = SubscriptionRequest::create([
            'user_id'            => $userId,
            'plan_id'            => $plan->id,
            'payment_method_id'  => $paymentMethod->id,
            'trx_id'             => $request->trx_id,
            'payment_screenshot' => $path,
            'status'             => 'pending',
        ]);

        session()->forget('selected_plan_id');

        return redirect()->route('user.subscriptions.processing', $subscriptionRequest->id);
    }

    public function processing($id)
    {
        $subscriptionRequest = SubscriptionRequest::where('user_id', auth()->id())
            ->findOrFail($id);

        return view('user.subscriptions.processing', compact('subscriptionRequest'));
    }

    public function checkStatus($id)
    {
        $subscriptionRequest = SubscriptionRequest::where('user_id', auth()->id())
            ->findOrFail($id);

        $subscriptionRequest->load('plan');

        $activeSubscription = Subscription::with('plan')
            ->where('user_id', auth()->id())
            ->where('status', 'active')
            ->where('is_trial', false)
            ->latest()
            ->first();

        return response()->json([
            'status' => $subscriptionRequest->status,
            'request_id' => $subscriptionRequest->id,
            'plan_name' => $subscriptionRequest->plan->name ?? null,
            'has_active_subscription' => (bool) $activeSubscription,
            'active_plan_name' => $activeSubscription->plan->name ?? null,
            'active_end_date' => $activeSubscription?->end_date?->format('d M, Y h:i A'),
        ]);
    }

    public function subscriptionStatus()
    {
        $userId = auth()->id();

        Subscription::where('user_id', $userId)
            ->where('status', 'active')
            ->where('end_date', '<', now())
            ->update([
                'status' => 'expired',
                'updated_at' => now(),
            ]);

        $activeSubscription = Subscription::with('plan')
            ->where('user_id', $userId)
            ->where('status', 'active')
            ->where('end_date', '>=', now())
            ->latest()
            ->first();

        return response()->json([
            'has_active_subscription' => (bool) $activeSubscription,
            'status' => $activeSubscription ? 'active' : 'expired',
            'plan_name' => $activeSubscription->plan->name ?? null,
            'end_date' => $activeSubscription?->end_date?->format('d M, Y h:i A'),
            'remaining_seconds' => $activeSubscription?->end_date
                ? max(0, now()->diffInSeconds($activeSubscription->end_date, false))
                : 0,
        ]);
    }
}