<?php

namespace App\Http\Controllers;

use App\Models\User;
use App\Models\Market;
use App\Models\Bid;
use App\Models\Sell;
use App\Models\Transaction;
use App\Models\Product;
use App\Models\Ownership;
use App\Models\Vendor;
use App\Models\VendorProduct;
use App\Models\AgentRequest;
use App\Models\Grant;
use App\Models\Plan;
use App\Models\Investment;
use App\Http\Controllers\Admin\MailController;
use App\Models\Withdrawal;
use App\Models\Deposit;
use Illuminate\Support\Str;
use DateTime;
use DateInterval;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use App\Nexus\Engine\NexusConfig;
use App\Nexus\Engine\SessionController as NexusSessionController;

class ArbitrageController extends Controller
{
    public function __construct()
    {
        $this->middleware(['activated', '2fa']);
    }
    
    // public function placeBid(Request $request, Product $product)
    // {
    //     $request->validate([
    //         'amount' => ['required', 'numeric', 'min:1'],
    //         'quantity' => ['required', 'integer', 'min:1'],
    //     ]);
    
    //     $total = $request->amount * $request->quantity;
    
    //     if ($total <= 0) {
    //         return redirect()->back()->with('error', 'Invalid bid amount.');
    //     }
    
    //     if (auth()->user()->balance < $total) {
    //         return redirect()->back()->with(
    //             'error',
    //             'Sorry you have insufficient funds in your wallet to place this bid.'
    //         );
    //     }
    
    //     if ($product->value <= 999) {
    //         $max = 100;
    //     } elseif ($product->value <= 10000) {
    //         $max = 10;
    //     } else {
    //         $max = 2;
    //     }
    
    //     if ($request->quantity > $max) {
    //         return redirect()->back()->with(
    //             'error',
    //             "The maximum allowed quantity for this product is {$max}. Reduce quantity or try another product."
    //         );
    //     }
    
    //     $placeBid = Bid::create([
    //         'user_id'    => auth()->id(),
    //         'store_name' => auth()->user()->username,
    //         'product_id' => $product->id,
    //         'market_id'  => $product->market?->id,
    //         'amount'     => $request->amount,
    //         'quantity'   => $request->quantity,
    //         'status'     => 0,
    //         'type'       => 'manual_bid',
    //         'bid_time'   => now(),
    //     ]);
    
    //     if ($placeBid) {
    //         auth()->user()->decrement('balance', $total);
    
    //         return redirect()->back()->with(
    //             'message',
    //             'Nice! your Bid has been placed successfully. The bid process will be completed after 24 hours. Please note that your bid amount will be refunded to your wallet if you do not win the auction, Good Luck!'
    //         );
    //     }
    
    //     return redirect()->back()->with('error', 'Oops, something went wrong.');
    // }


    /**
     * Place Bid - updated to support wallet_source: 'main' | 'ictp'
     *
     * The view sends a hidden/radio field: name="wallet_source" value="main"|"ictp"
     */
    public function placeBid(Request $request, Product $product)
    {
        if ($product->market == null) {
            return redirect()->back()->with('error', 'Oops, something went wrong.');
        }

        // NEXUS session gate: when engine is active, bids only accepted during open sessions.
        // When inactive, this check is skipped entirely (existing behavior preserved).
        if (NexusConfig::isNexusActive() && !(new NexusSessionController())->isSessionOpen()) {
            return redirect()->back()->with('error', 'Bidding is currently closed. Please wait for the next trading session to open.');
        }

        $request->validate([
            'amount'        => ['required', 'numeric', 'min:1'],
            'quantity'      => ['required', 'integer', 'min:1'],
            'wallet_source' => ['required', 'in:main,ictp'],
        ]);

        $total        = $request->amount * $request->quantity;
        $walletSource = $request->wallet_source;   // 'main' or 'ictp'

        if ($total <= 0) {
            return redirect()->back()->with('error', 'Invalid bid amount.');
        }

        if ($product->value <= 999) {
            $max = 100;
        } elseif ($product->value <= 10000) {
            $max = 10;
        } else {
            $max = 2;
        }

        if ($request->quantity > $max) {
            return redirect()->back()->with(
                'error',
                "The maximum allowed quantity for this product is {$max}. Reduce quantity or try another product."
            );
        }

        // ── Balance check based on chosen wallet ────────────────────────────
        $user = auth()->user();

        if ($walletSource === 'ictp') {
            $available = $user->ictp_balance ?? 0;
            $balanceField = 'ictp_balance';
            $walletLabel  = 'ICTP';
        } else {
            $available = $user->balance;
            $balanceField = 'balance';
            $walletLabel  = 'Main';
        }

        if ($available < $total) {
            return redirect()->back()->with(
                'error',
                "Sorry, you have insufficient funds in your {$walletLabel} Wallet to place this bid."
            );
        }

        // ── Place bid in a transaction to prevent race conditions ───────────
        $placeBid = null;

        DB::transaction(function () use ($request, $product, $user, $total, $walletSource, $balanceField, &$placeBid) {
            // Re-fetch and lock the user row
            $lockedUser = \App\Models\User::where('id', $user->id)->lockForUpdate()->first();

            // Re-check balance inside the lock
            $currentBalance = $lockedUser->{$balanceField} ?? 0;
            if ($currentBalance < $total) {
                // Will be caught below - set placeBid to false to signal failure
                $placeBid = false;
                return;
            }

            $placeBid = \App\Models\Bid::create([
                'user_id'       => $lockedUser->id,
                'store_name'    => $lockedUser->username,
                'product_id'    => $product->id,
                'market_id'     => $product->market->id,
                'amount'        => $request->amount,
                'quantity'      => $request->quantity,
                'status'        => 0,
                'type'          => 'manual_bid',
                'bid_time'      => now(),
                'wallet_source' => $walletSource,   // persisted for audit / refund routing
            ]);

            // Deduct from the correct wallet column
            $lockedUser->decrement($balanceField, $total);
        });

        if ($placeBid === false) {
            // Balance was insufficient when re-checked inside the lock
            return redirect()->back()->with(
                'error',
                "Sorry, you have insufficient funds in your {$walletLabel} Wallet to place this bid."
            );
        }

        if ($placeBid) {
            return redirect()->back()->with(
                'message',
                'Nice! Your bid has been placed successfully using your ' . $walletLabel . ' balance. '
                    . 'The bid process will be completed after 1 hours. '
                    . 'Your bid amount will be refunded to the same wallet if you do not win the auction. Good Luck!'
            );
        }

        return redirect()->back()->with('error', 'Oops, something went wrong.');
    }


    public function sellItem(Request $request, Ownership $ownership, Market $market)
    {
        // Prevent duplicate pending sells
        $existingSell = Sell::where('ownership_id', $ownership->id)
            ->where('status', 0)
            ->exists();

        if ($existingSell) {
            return redirect()->back()->with('error', 'You already have an active sale running for this item.');
        }

        $request->validate([
            'margin_percent' => ['required', 'numeric', 'min:0.1', 'max:10'],
            'recess_percent' => ['required', 'numeric', 'min:0', 'max:10'],
            'excess_percent' => ['required', 'numeric', 'min:0', 'max:10'],
        ]);

        $initialPrice = $ownership->value;
        $marginPercent = (float) $request->input('margin_percent');
        $recessPercent = (float) $request->input('recess_percent');
        $excessPercent = (float) $request->input('excess_percent');

        // Calculate asking price from margin percentage
        $amount = $initialPrice * (1 + $marginPercent / 100);

        // Protect user from setting a range that loses money.
        // If the recess floor drops below the cost price, reject the sell.
        $recessFloor = $amount - ($recessPercent / 100 * $amount);
        if ($recessFloor < $initialPrice) {
            return redirect()->back()->with(
                'error',
                'Your Recess is too wide. The minimum acceptable price ($' . number_format($recessFloor, 2) . ') is below what you paid for this product ($' . number_format($initialPrice, 2) . '). Reduce your Recess or increase your Profit Margin so you do not lose money on this trade.'
            );
        }

        $walletSource = $ownership->wallet_source ?? 'main';

        $sellOff = Sell::create([
            'user_id'        => auth()->user()->id,
            'ownership_id'   => $ownership->id,
            'product_id'     => $ownership->product?->id,
            'market_id'      => $market->id,
            'initial_price'  => $initialPrice,
            'amount'         => $amount,
            'quantity'        => $ownership->quantity,
            'status'         => 0,
            'type'           => 'manual_sell',
            'sell_time'      => now(),
            'margin_percent' => $marginPercent,
            'recess_percent' => $recessPercent,
            'excess_percent' => $excessPercent,
            'wallet_source'  => $walletSource,
        ]);

        if ($sellOff) {
            return redirect()->back()->with(
                'message',
                'Your sell order is locked in. Your product will be matched against live market activity over the next 24 hours. You will be notified once processed.'
            );
        } else {
            return redirect()->back()->with('error', 'Oops, something went wrong. Please try again.');
        }
    }

    public function aiBuy(Plan $plan)
    {
        if (auth()->user()->balance < $plan->price) {
            return redirect()->back()->with('error', 'Sorry, You have insufficient balance to make this purchase!');
        }

        $today = new DateTime();
        $thirtyDaysLater = $today->add(new DateInterval('P30D'));

        $timestamp = $thirtyDaysLater->getTimestamp();

        $purchase = Investment::create([
            'plan_id' => $plan->id,
            'balance' => 0,
            'user_id' => auth()->user()->id,
            'buy_date' => now(),
            'end_date' => date('Y-m-d H:i:s', $timestamp),
            'status' => 2,
        ]);

        $mail = new MailController();

        $mail->aiPurchase(auth()->user()->username, auth()->user()->first_name, auth()->user()->email, $plan->price, $plan->name, $plan->description, $plan->min_fund, $plan->max_fund);

        tap(auth()->user())->update([
            'balance' => auth()->user()->balance - $plan->price,
        ]);

        if (isset(auth()->user()->referrer) && auth()->user()->referrer->type != 'marketer') {
            $amount = 10 / 100 * $plan->price;
            $totalEarnings = auth()->user()->referrer->ai_bonus + $amount;
            User::where('id', auth()->user()->referrer->id)->update([
                'ai_bonus' => $totalEarnings,
            ]);

            $transaction = Transaction::create([
                'user_id' => auth()->user()->referrer->id,
                'amount' => $totalEarnings,
                'status' => 1,
                'type' => 'ai_bonus',
            ]);
        }

        if ($purchase) {
            return redirect()->route('home')->with('message', 'Congratulations, you have successfully purchased the ' . $plan->name . ' Plan valid for ' . $plan->period . ' days.');
        } else {
            return redirect()->back()->with('error', 'Oops, something went wrong. Please try again');
        }
    }

    public function aiFund(Request $request, Investment $investment)
    {
        if (auth()->user()->balance < $request->amount) {
            return redirect()->back()->with('error', 'Sorry, You have insufficient balance to fund your bot with this amount. Deposit funds into your main balance and try again!');
        }

        $plan = Plan::where('id', $investment->plan_id)->first();

        tap($investment)->update([
            'balance' => $investment->balance + $request->amount,
            'amount' => $request->amount,
            'funded' => 1,
            'trade_min' => $plan->limit_min,
            'trade_max' => $plan->limit_max,
        ]);

        tap(auth()->user())->update([
            'balance' => auth()->user()->balance - $request->amount,
        ]);

        $amount = number_format($request->amount, 2);

        return redirect()->route('ai-dashboard')->with('message', 'Congratulations, you have successfully funded your bot with $' . $amount . '. Happy Trading!');
    }

    public function aiWithdraw(Request $request, Investment $investment)
    {
        // if($investment->f_pfit > 0)
        // {
        //     return redirect()->back()->with('error', 'Sorry, an unknown error occured');
        // }

        if ($investment->balance < $request->amount) {
            return redirect()->back()->with('error', 'Sorry, You have insufficient balance to make a withdrawal of this amount!');
        }

        tap($investment)->update([
            'balance' => $investment->balance - $request->amount,
            'moved' => $investment->moved + $request->amount,
            'moved_record' => array_merge(
                $investment->moved_record ?? [],
                [[
                    'date' => now()->toDateString(),
                    'amount' => $request->amount,
                ]]
            ),
        ]);

        tap(auth()->user())->update([
            'balance' => auth()->user()->balance + $request->amount,
        ]);

        $amount = number_format($request->amount, 2);

        return redirect()->route('ai-dashboard')->with('message', 'Congratulations, you have successfully moved $' . $amount . ' into your main wallet!');
    }

    public function vendorApplied(Request $request)
    {
        $validator = Validator::make(
            $request->all(),
            [
                'products.*.image1' => 'required|image|mimes:jpeg,png,jpg|max:2048',
                'products.*.image2' => 'image|nullable|mimes:jpeg,png,jpg|max:2048',
                'products.*.image3' => 'image|nullable|mimes:jpeg,png,jpg|max:2048',
            ],
            [
                'required' => 'The image field is required.',
                'image' => 'The input must be an image of type jpeg, jpg, or png',
                'mimes' => 'The image must be a file of type: jpeg, png, jpg.',
                'max' => 'The image may not be greater than :max kilobytes.',
            ]
        );

        // Store the count of product forms in the session
        $request->session()->flash('productCount', count($request->input('products')));

        if ($validator->fails()) {
            return redirect()->back()->withErrors($validator)->withInput();
        }

        $products = $request->input('products');

        if ($validator->fails()) {
            return back()->withErrors($validator)->withInput();
        }

        $total = 0;
        foreach ($products as $productIndex => $product) {
            $total += $product['value'] * $product['quantity'];
        }

        if ($total < 10000) {
            return redirect()->back()->with('error', 'Sorry, the total value of your added products is less than the $10,000 requirement, increase your products to meet the requirement!');
        }

        foreach ($products as $productIndex => $product) {

            if ($request->file('products.' . $productIndex . '.image1') != null) {
                $image1 = $product['name'] . '-' . rand(10000, 99999) . '.' . $request->file('products.' . $productIndex . '.image1')->getClientOriginalExtension();
                #rename the file 
                #store to te storage/app/public/images folder
                $request->file('products.' . $productIndex . '.image1')->storeAs('products', $image1, 'public');
            } else {
                $image1 = null;
            }


            if ($request->file('products.' . $productIndex . '.image2') != null) {
                $image2 = $product['name'] . '-' . rand(10000, 99999) . '.' . $request->file('products.' . $productIndex . '.image2')->getClientOriginalExtension();
                #rename the file 
                #store to te storage/app/public/images folder
                $request->file('products.' . $productIndex . '.image2')->storeAs('products', $image2, 'public');
            } else {
                $image2 = null;
            }

            if ($request->file('products.' . $productIndex . '.image3') != null) {
                $image3 = $product['name'] . '-' . rand(10000, 99999) . '.' . $request->file('products.' . $productIndex . '.image3')->getClientOriginalExtension();
                #rename the file 
                #store to te storage/app/public/images folder
                $request->file('products.' . $productIndex . '.image3')->storeAs('products', $image3, 'public');
            } else {
                $image3 = null;
            }

            if (auth()->user()->vendor()->where('status', 'approved')->exists()) {
                $create = VendorProduct::create([
                    'name' => $product['name'],
                    'slug' => Str::random(9),
                    'value' => $product['value'],
                    'quantity' => $product['quantity'],
                    'description' => $product['description'],
                    'location' => $product['location'],
                    'vendor_id' => auth()->user()->vendor()->first()->id,
                    'category' => $product['category'],
                    'image1' => $image1,
                    'image2' => $image2,
                    'image3' => $image3,
                    'status' => 0,
                ]);
            } else {
                $vendor = Vendor::updateOrCreate(
                    ['user_id' => auth()->user()->id],
                    ['status' => 'pending']
                );

                $create = VendorProduct::create([
                    'name' => $product['name'],
                    'slug' => Str::random(9),
                    'value' => $product['value'],
                    'quantity' => $product['quantity'],
                    'description' => $product['description'],
                    'location' => $product['location'],
                    'vendor_id' => $vendor->id,
                    'category' => $product['category'],
                    'image1' => $image1,
                    'image2' => $image2,
                    'image3' => $image3,
                    'status' => 0,
                ]);
            }
        }

        if (auth()->user()->vendor()->where('status', 'approved')->exists()) {
            return redirect()->route('vendor-dashboard')->with('message', 'Vendor Product Request Sent! We will review your products and get back to you shortly.');
        } else {
            return redirect()->route('vendor-dashboard')->with('message', 'Congratulations, your Vendor Application Request has ben sent! We will review your products and get back to you shortly.');
        }
    }

    public function sendProduct(VendorProduct $product, Request $request)
    {
        tap($product)->update([
            'tracking_id' => $request->tracking_id,
            'dropoff' => $request->dropoff,
            'courier' => $request->courier,
            'status' => 2
        ]);

        return redirect()->route('vendor-dashboard')->with('message', 'Please wait while we confirm your product');
    }

    public function agentSend(Request $request)
    {
        $agentRequest = AgentRequest::create([
            'user_id' => auth()->user()->id,
            'medium' => $request->medium,
            'store' => $request->store,
            'details' => $request->details,
            'status' => 0,
        ]);

        return redirect()->route('vendor-dashboard')->with('message', 'Request sent, we\'ll contact you via the submitted mail shortly.');
    }

    public function grantApplication(Request $request)
    {
        $grant = new Grant();

        // Mass assign attributes from the request
        $grant->fill($request->all());

        // Save the model to the database
        $grant->save();

        return redirect()->route('grants')->with('message', 'Congratulations, Your Grant Application Request Sent! We will review your details and get back to you shortly.');
    }

    public function ictpToBalance(Request $request)
    {
        $lockedPrincipal = 50.00;

        $request->validate([
            'amount' => ['required', 'numeric', 'min:0.01'],
        ]);

        $requested = (float) $request->amount;

        try {
            DB::transaction(function () use ($requested, $lockedPrincipal) {

                $user = User::where('id', auth()->id())->lockForUpdate()->first();

                $ictpBalance  = (float) ($user->ictp_balance ?? 0);

                // Trading manual: ICTP balance must reach $100 before profits can be transferred.
                // ($50 principal + $50 profits minimum)
                if ($ictpBalance < 100.00)       throw new \Exception('BELOW_THRESHOLD');

                $withdrawable = max(0, $ictpBalance - $lockedPrincipal);

                if ($withdrawable <= 0)          throw new \Exception('NO_PROFIT');
                if ($requested > $withdrawable)  throw new \Exception('EXCEEDS_WITHDRAWABLE');

                $userShare    = round($requested * 0.60, 8);
                $companyShare = round($requested * 0.40, 8);

                $user->decrement('ictp_balance', $requested);
                $user->increment('balance', $userShare);

                Transaction::create([
                    'user_id' => $user->id,
                    'type'    => 'ictp_to_balance',
                    'amount'  => $userShare,
                    'notes'   => 'ICTP to Main Wallet, company share: ' . $companyShare,
                    'status'  => 1,
                ]);
            });
        } catch (\Exception $e) {
            $msg = match ($e->getMessage()) {
                'BELOW_THRESHOLD'      => 'Your ICTP balance must reach $100.00 before you can transfer profits. Keep trading to grow your balance.',
                'NO_PROFIT'            => 'You have no withdrawable ICTP profits. Your $50.00 principal is always locked.',
                'EXCEEDS_WITHDRAWABLE' => 'The amount you entered exceeds your withdrawable ICTP balance.',
                default                => 'Something went wrong. Please try again.',
            };
            return redirect()->back()->with('error', $msg);
        }

        return redirect()->route('home')
            ->with('message', 'Transfer successful! 60% of your requested amount has been credited to your Main Wallet. The $50.00 principal remains secured in your ICTP balance.');
    }
}
