<?php

namespace App\Http\Controllers;

use App\Enums\WithdrawalRequestStatus;
use App\Models\InvestmentSetting;
use App\Models\User;
use App\Models\UserWallet;
use App\Models\WithdrawalRequest;
use App\Services\EmailActionConfirmation;
use App\Support\InvestmentLedger;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
use Illuminate\Validation\ValidationException;
use Inertia\Inertia;

class BalancesWithdrawalRequestController extends Controller
{
    /**
     * Solicitud de retiro sobre el capital consolidado (todas las inversiones activas).
     */
    public function store(Request $request, EmailActionConfirmation $emailConfirmation): RedirectResponse
    {
        /** @var User $user */
        $user = $request->user();

        $validated = $request->validate([
            'amount' => ['required', 'numeric', 'min:0.01'],
            'user_wallet_id' => ['required', 'integer', Rule::exists('user_wallets', 'id')->where(fn ($q) => $q->where('user_id', $user->id))],
            'requester_note' => ['nullable', 'string', 'max:2000'],
        ]);

        $wallet = UserWallet::query()->whereKey($validated['user_wallet_id'])->where('user_id', $user->id)->firstOrFail();
        $amount = (float) $validated['amount'];

        try {
            DB::transaction(function () use ($user, $validated, $wallet, $amount, $emailConfirmation): void {
                $available = InvestmentLedger::totalWithdrawableForUser((int) $user->id);

                if ($available <= 0) {
                    throw ValidationException::withMessages([
                        'amount' => ['No tienes capital disponible para retirar (recuerda: el principal permanece bloqueado hasta el vencimiento).'],
                    ]);
                }

                if ($amount > $available + 0.0001) {
                    throw ValidationException::withMessages([
                        'amount' => ['La solicitud supera tu capital disponible consolidado.'],
                    ]);
                }

                $settings = InvestmentSetting::current();
                $minWithdrawal = (float) $settings->min_withdrawal_amount;

                if ($amount + 0.0001 < $minWithdrawal) {
                    throw ValidationException::withMessages([
                        'amount' => ['El monto no alcanza el mínimo de retiro configurado ('.number_format($minWithdrawal, 2, '.', '').' US$).'],
                    ]);
                }

                $breakdown = InvestmentLedger::withdrawalFeeBreakdownForGross($amount, $settings);

                if ($amount <= $breakdown['fee'] + 0.0001) {
                    throw ValidationException::withMessages([
                        'amount' => ['El monto es demasiado bajo para cubrir la comisión configurada por retiro.'],
                    ]);
                }

                $hasPending = WithdrawalRequest::query()
                    ->where('user_id', $user->id)
                    ->whereIn('status', [WithdrawalRequestStatus::Pending, WithdrawalRequestStatus::PendingEmail])
                    ->lockForUpdate()
                    ->exists();

                if ($hasPending) {
                    throw ValidationException::withMessages([
                        'amount' => ['Ya tienes una solicitud de retiro en curso. Espera confirmación por correo o a que el equipo la resuelva.'],
                    ]);
                }

                /** @var WithdrawalRequest $created */
                $created = WithdrawalRequest::query()->create([
                    'investment_id' => null,
                    'user_id' => $user->id,
                    'amount' => $amount,
                    'fee_total' => $breakdown['fee'],
                    'net_amount' => $breakdown['net'],
                    'requester_note' => filled($validated['requester_note'] ?? null)
                        ? trim((string) $validated['requester_note'])
                        : null,
                    'destination_currency_network' => $wallet->currency_network,
                    'destination_address' => $wallet->address,
                    'destination_label' => $wallet->label,
                    'status' => WithdrawalRequestStatus::PendingEmail,
                    'admin_note' => null,
                    'payout_txid' => null,
                    'processed_by' => null,
                    'processed_at' => null,
                ]);

                $emailConfirmation->sendWithdrawal($created);
            });
        } catch (ValidationException $validationException) {
            return redirect()
                ->back()
                ->withErrors($validationException->errors());
        }

        Inertia::flash('toast', [
            'type' => 'success',
            'message' => 'Te enviamos un correo: confirma el retiro con el enlace para que el equipo pueda revisarlo.',
        ]);

        return redirect()->route('balances.index');
    }
}
