orderBy('price') ->get() ->map(fn($p) => [ 'hashkey' => $p->hashkey, 'name' => $p->name, 'description' => $p->description, 'price' => $p->price, 'duration_days' => $p->duration_days, 'expiry_action' => $p->expiry_action, ]); return Response::json($plans); } // ── User: get my current subscription ───────────────────────────────── public function mySubscription() { $user = User::findOrFail(Auth::id()); $sub = self::getActiveSubscription($user->id); if (!$sub) { return Response::json([ 'has_subscription' => false, 'balance' => $user->total_balance, ]); } return Response::json([ 'has_subscription' => true, 'subscription' => self::formatUserSubscription($sub), 'balance' => $user->total_balance, ]); } // ── User: pay for a subscription via wallet ──────────────────────────── public function payWithWallet(Request $request) { $planHashkey = $request->input('plan_hashkey'); if (!$planHashkey) { return Response::json('Plan is required.', 422); } $plan = SubscriptionPlan::where('hashkey', $planHashkey) ->where('active', true) ->first(); if (!$plan) { return Response::json('Plan not found or no longer available.', 404); } $user = User::findOrFail(Auth::id()); if ($user->total_balance < $plan->price) { return Response::json('Insufficient wallet balance.', 402); } $admin = User::where('acct_type', UserTypes::ULTIMATE->value)->first(); if (!$admin) { return Response::json('Payment recipient not configured.', 500); } try { // Deduct from user, credit admin $user->total_balance -= $plan->price; $user->save(); $admin->total_balance += $plan->price; $admin->save(); // Create or extend subscription $now = Carbon::now(); $expiry = $now->copy()->addDays($plan->duration_days); $existing = self::getActiveSubscription($user->id); if ($existing) { // Extend from current expiry if still active, otherwise from now $base = $existing->expires_at && $existing->expires_at->isFuture() ? $existing->expires_at : $now; $expiry = $base->copy()->addDays($plan->duration_days); $existing->expires_at = $expiry; $existing->status = 'active'; $existing->payment_method = 'wallet'; $existing->save(); $subscription = $existing; } else { $subscription = Subscription::create([ 'user_id' => $user->id, 'plan_id' => $plan->id, 'status' => 'active', 'starts_at' => $now, 'expires_at' => $expiry, 'payment_method' => 'wallet', ]); } // Record invoice SubscriptionInvoice::create([ 'subscription_id' => $subscription->id, 'user_id' => $user->id, 'amount' => $plan->price, 'status' => 'paid', 'paid_at' => $now, 'payment_method' => 'wallet', 'payment_reference' => null, 'additional_details' => [ 'plan_name' => $plan->name, 'plan_hashkey' => $plan->hashkey, 'admin_id' => $admin->id, ], ]); return Response::json([ 'success' => true, 'expires_at' => $expiry, 'balance' => $user->total_balance, ]); } catch (\Throwable $th) { return Response::json($th->getMessage(), 500); } } // ── User: my invoice history ─────────────────────────────────────────── public function myInvoices() { $invoices = SubscriptionInvoice::where('user_id', Auth::id()) ->orderByDesc('created_at') ->get() ->map(fn($inv) => [ 'hashkey' => $inv->hashkey, 'amount' => $inv->amount, 'status' => $inv->status, 'payment_method' => $inv->payment_method, 'payment_reference' => $inv->payment_reference, 'paid_at' => $inv->paid_at, 'plan_name' => $inv->additional_details['plan_name'] ?? '', 'created_at' => $inv->created_at, ]); return Response::json($invoices); } // ── Helper: get user's latest active subscription ───────────────────── private static function getActiveSubscription(int $userId): ?Subscription { return Subscription::where('user_id', $userId) ->where('status', 'active') ->where('expires_at', '>', Carbon::now()) ->with('plan') ->orderByDesc('expires_at') ->first(); } private static function formatUserSubscription(Subscription $sub): array { $plan = $sub->plan; $expiresAt = $sub->expires_at; $daysRemaining = $expiresAt ? (int) now()->diffInDays($expiresAt, false) : 0; return [ 'hashkey' => $sub->hashkey, 'status' => $sub->status, 'starts_at' => $sub->starts_at, 'expires_at' => $expiresAt, 'days_remaining' => max(0, $daysRemaining), 'payment_method' => $sub->payment_method, 'plan' => $plan ? [ 'hashkey' => $plan->hashkey, 'name' => $plan->name, 'price' => $plan->price, 'duration_days' => $plan->duration_days, 'expiry_action' => $plan->expiry_action, ] : null, ]; } }