<?php

namespace App\Http\Controllers;

use App\Models\Deposit;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

/**
 * DepositConfirmController
 *
 * Called by the FRONTEND immediately after the on-chain tx is submitted.
 *
 * Responsibilities:
 *   1. Validate the incoming payload
 *   2. Check deposits are not paused
 *   3. Update the user's deposit wallet address if it changed
 *   4. Save a PENDING Deposit record so the user sees it immediately
 *
 * NOT responsible for:
 *   - Verifying the tx on-chain (that's the blockchain webhook's job)
 *   - Crediting the user's balance (also the webhook's job)
 *   - Marking the deposit as complete (also the webhook's job)
 *
 * Flow:
 *   Frontend submits tx
 *     → POST /deposit/confirm  (this controller)
 *     → Deposit saved as status=null (pending)
 *     → User sees "Pending" in deposit history immediately
 *
 *   Blockchain webhook fires when tx is confirmed on-chain
 *     → POST /api/webhook/deposit  (DepositWebhookController)
 *     → Verifies tx on-chain via RPC
 *     → Finds the pending Deposit by payment_id (tx_hash)
 *     → Credits balance, marks status=1 (completed)
 */
class DepositConfirmController extends Controller
{
    public function confirm(Request $request): \Illuminate\Http\JsonResponse
    {
        // ── 1. Origin check ───────────────────────────────────────────────────
        // Only allow calls from your own frontend, not arbitrary clients.
        if ($request->header('Origin') !== config('app.url')) {
            abort(403, 'Unauthorized Origin');
        }

        // ── 2. Input validation ───────────────────────────────────────────────
        $data = $request->validate([
            'chain'      => ['required', 'string', 'in:ethereum,solana'],
            'tx_hash'    => ['required', 'string', 'max:255'],
            'from'       => ['required', 'string', 'max:255'],
            'amount_raw' => ['required', 'string', 'regex:/^\d+$/'],  // digits only, no floats
        ]);

        $chain     = $data['chain'];
        $txHash    = $data['tx_hash'];
        $fromAddr  = $chain === 'ethereum'
            ? strtolower(trim($data['from']))   // ETH addresses are case-insensitive
            : trim($data['from']);               // Solana base58 is case-sensitive
        $amountRaw = $data['amount_raw'];

        // Derive human-readable USD amount from raw units (USDT = 6 decimals)
        // This is approximate — the webhook will use the on-chain amount as truth.
        $usdAmount = round(
            (float) bcdiv($amountRaw, (string) pow(10, 6), 10),
            2
        );

        // ── 3. Deposit pause check ─────────────────────────────────────────────
        // $paused = \App\Models\SiteDetail::where('title', 'is_deposit_paused')->value('description');
        // if ($paused == 1) {
        //     return response()->json(['error' => 'Deposits are currently paused.'], 403);
        // }

        // ── 4. Duplicate tx_hash check ─────────────────────────────────────────
        // If this tx_hash was already submitted (user double-clicked or retried),
        // don't create a second pending record.
        if (Deposit::where('payment_id', $txHash)->exists()) {
            return response()->json([
                'status'  => 'already_submitted',
                'message' => 'This transaction is already being tracked.',
            ], 200);
        }

        // ── 5. Update wallet address + save pending deposit ────────────────────
        try {
            DB::transaction(function () use ($chain, $txHash, $fromAddr, $usdAmount, $amountRaw) {

                // Lock the authenticated user row
                $user = User::where('id', auth()->id())
                    ->lockForUpdate()
                    ->first();

                if (!$user) {
                    throw new \RuntimeException('Authenticated user not found.');
                }

                // Determine which wallet column to check/update for this chain
                $walletColumn = $chain === 'ethereum' ? 'eth_deposit_wallet' : 'sol_deposit_wallet';

                // If the wallet address is new or changed, update it.
                // This is how we learn which wallet belongs to this user —
                // the webhook will later look up users by this column.
                $currentWallet = $chain === 'ethereum'
                    ? strtolower(trim($user->{$walletColumn} ?? ''))
                    : trim($user->{$walletColumn} ?? '');

                if ($currentWallet !== $fromAddr) {
                    $user->{$walletColumn} = $fromAddr;
                    $user->save();

                    Log::info("Deposit wallet updated for user #{$user->id}.", [
                        'chain'    => $chain,
                        'column'   => $walletColumn,
                        'old'      => $currentWallet ?: '(none)',
                        'new'      => $fromAddr,
                    ]);
                }

                // Save a pending Deposit record.
                // status = null means pending — the webhook will set it to 1 (success) or 2 (failed).
                // The webhook finds this record via payment_id = tx_hash.
                Deposit::create([
                    'user_id'    => $user->id,
                    'payment_id' => $txHash,
                    'amount'     => $usdAmount,   // approximate; webhook overwrites with on-chain truth
                    'network'    => $chain === 'ethereum' ? 'ERC20' : 'SOL',
                    'type'       => 'crypto_auto',
                    'status'     => null,          // null = pending, 1 = confirmed, 2 = failed
                ]);

                Log::info("Pending deposit registered for user #{$user->id}.", [
                    'chain'      => $chain,
                    'tx_hash'    => $txHash,
                    'amount_usd' => $usdAmount,
                ]);
            });
        } catch (\Throwable $e) {
            Log::error('DepositConfirmController: failed to save pending deposit.', [
                'tx_hash' => $txHash,
                'error'   => $e->getMessage(),
                'trace'   => $e->getTraceAsString(),
            ]);
            return response()->json([
                'error' => 'Could not register deposit. Please contact support with your tx hash.',
            ], 500);
        }

        // Return immediately — the user sees "Pending" in their history.
        // The webhook will update it when the on-chain confirmation arrives.
        return response()->json([
            'status'  => 'pending',
            'message' => 'Deposit submitted. It will be confirmed automatically once the transaction is verified on-chain.',
        ], 200);
    }
}
