<?php

declare(strict_types=1);

namespace App\Http\Controllers\Subscription;

use Hypervel\Http\Request;
use Hypervel\Support\Facades\Auth;
use Hypervel\Support\Facades\Response;
use App\Models\User;
use App\Models\Subscription\SubscriptionPlan;
use App\Models\Subscription\Subscription;
use App\Models\Subscription\SubscriptionInvoice;
use App\Enums\UserTypes;
use Carbon\Carbon;

class SubscriptionController
{
    // ── User: list available plans (active only) ───────────────────────────
    public function listAvailablePlans()
    {
        $plans = SubscriptionPlan::where('active', true)
            ->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,
        ];
    }
}
