<?php 

namespace App\Http\Controllers\Offers;

use App\Events\OfferPurchaseRequested;
use App\Http\Controllers\Controller;
use App\Models\BellNotification;
use App\Models\Offer;
use App\Models\Operator;
use App\Models\Purchase;
use App\Models\Transaction;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;              // ✅ for PIN check
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;   // ✅ for pretty errors

class BrowseController extends Controller
{
    /**
     * Offer list page
     */
    public function index(Request $request)
    {
        $operators = Operator::active()
            ->orderBy('sort_order')
            ->orderBy('name')
            ->get();

        if ($operators->isEmpty()) {
            return view('frontend.offers.index', [
                'operators' => collect(),
                'current'   => null,
                'offers'    => collect(),
            ]);
        }

        $current = $request->query('op')
            ? Operator::active()->where('code', $request->query('op'))->firstOrFail()
            : $operators->first();

        $offers = Offer::active()
            ->where('operator_id', $current->id)
            ->orderBy('sort_order')
            ->orderByDesc('id')
            ->get();

        return view('frontend.offers.index', compact('operators', 'current', 'offers'));
    }

    /**
     * Offer details page
     */
    public function show(Offer $offer)
    {
        abort_unless($offer->is_active, 404);

        $offer->load('operator');

        return view('frontend.offers.show', compact('offer'));
    }

    /**
     * Purchase:
     *  - Validate PIN
     *  - Balance check
     *  - Create Purchase (pending) + Transaction
     *  - Redirect to success page
     */
    public function purchase(Request $request, Offer $offer)
    {
        abort_unless($offer->is_active, 404);

        $request->validate([
            'msisdn'    => ['required', 'regex:/^\+?\d{10,15}$/'],
            'reference' => ['nullable', 'string', 'max:60'],
            'login_pin' => ['required', 'digits:4'],   // ✅ PIN must be 4 digits
        ], [
            'msisdn.regex' => 'Enter a valid mobile number (10–15 digits).',
        ]);

        /** @var \App\Models\User $auth */
        $auth   = $request->user();
        $userId = $auth->id;

        // 0️⃣ PIN check (same pattern as send money / bank add money)
        $pin = (string) $request->input('login_pin');

        // If login_pin is stored as bcrypt hash (recommended)
        if (! Hash::check($pin, $auth->login_pin)) {   // 👈 column name adjust if needed
            throw ValidationException::withMessages([
                'login_pin' => 'Incorrect PIN.',
            ]);
        }

        // sale_price if present, otherwise regular_price
        $price = $offer->sale_price > 0 ? $offer->sale_price : $offer->regular_price;

        try {
            // Return both purchase object & new balance
            $result = DB::transaction(function () use ($userId, $offer, $price, $request) {
                /** @var \App\Models\User $user */
                $user = User::whereKey($userId)->lockForUpdate()->first();

                // 1) Balance check – if insufficient, create failed purchase row & throw
                if (bccomp($user->balance, $price, 2) < 0) {
                    Purchase::create([
                        'user_id'   => $user->id,
                        'offer_id'  => $offer->id,
                        'msisdn'    => preg_replace('/\D/', '', $request->msisdn),
                        'reference' => $request->reference,
                        'price'     => $price,
                        'status'    => 'failed',
                        'txn_id'    => null,
                    ]);

                    throw new \RuntimeException('INSUFFICIENT_BALANCE');
                }

                // 2) Balance debit now
                $user->update([
                    'balance' => bcsub($user->balance, $price, 2),
                ]);

                // txn id generate
                $txnId = 'TXN-' . Str::upper(Str::random(6)) . '-' . now()->format('ymdHis');

                // 3) Purchase row (pending)
                $purchase = Purchase::create([
                    'user_id'   => $user->id,
                    'offer_id'  => $offer->id,
                    'msisdn'    => preg_replace('/\D/', '', $request->msisdn),
                    'reference' => $request->reference,
                    'price'     => $price,
                    'status'    => 'pending',   // still pending
                    'txn_id'    => $txnId,
                ]);

                // 4) Transaction row
                Transaction::create([
                    'user_id'       => $user->id,
                    'type'          => 'debit',
                    'amount'        => $price,
                    'balance_after' => $user->fresh()->balance,
                    'related_type'  => Purchase::class,
                    'related_id'    => $purchase->id,
                    'meta'          => [
                        'offer_id'   => $offer->id,
                        'offer_name' => $offer->title ?? $offer->name ?? 'N/A',
                        'msisdn'     => $request->msisdn,
                        'txn_id'     => $txnId,
                        'pending'    => true,
                    ],
                ]);

                // 5) 🔔 Bell notification create
                $cleanMsisdn = preg_replace('/\D/', '', $request->msisdn);
                $offerName   = $offer->title ?? $offer->name ?? 'Offer';

                BellNotification::create([
                    'user_id' => $user->id,
                    'title'   => 'Offer Purchase Request Submitted',
                    'status'  => 'unread',
                    'type'    => 'offer_purchase',
                    'amount'  => $price,
                    'message' => "Your purchase request for '{$offerName}' ({$price} TK) to {$cleanMsisdn} "
                               . "has been submitted and is waiting for admin approval. TXN: {$txnId}",
                    'read_at' => null,
                ]);

                return [
                    'purchase'    => $purchase,
                    'new_balance' => (float) $user->fresh()->balance,
                ];
            });
        } catch (\RuntimeException $e) {
            if ($e->getMessage() === 'INSUFFICIENT_BALANCE') {
                if ($request->wantsJson()) {
                    return response()->json([
                        'ok'      => false,
                        'message' => 'Insufficient balance to purchase this offer.',
                    ], 422);
                }

                return back()
                    ->withErrors(['msisdn' => 'You do not have enough balance to purchase this offer.'])
                    ->withInput();
            }

            throw $e;
        }

        // Transaction success → fire event
        /** @var \App\Models\Purchase $purchase */
        $purchase = $result['purchase'];

        event(new OfferPurchaseRequested($purchase));

        // JSON response
        if ($request->wantsJson()) {
            return response()->json([
                'ok'           => true,
                'message'      => 'Purchase request submitted (pending admin approval).',
                'txn_id'       => $purchase->txn_id,
                'balance'      => $result['new_balance'],
                'redirect_url' => route('offers.purchase.success', $purchase), // ✅ success page url
            ]);
        }

        // Web response → success page
        return redirect()
            ->route('offers.purchase.success', $purchase)
            ->with('success', 'Purchase request submitted (Pending).');
    }

    /**
     * Offer purchase success page
     */
    public function success(Request $request, Purchase $purchase)
    {
        // নিজের purchase না হলে দেখাব না
        // if ($purchase->user_id !== $request->user()->id) {
        //     abort(403);
        // }

        $purchase->load('offer.operator');

        return view('frontend.offers.purchase_success', [
            'purchase' => $purchase,
        ]);
    }
}
