<?php

namespace App\Http\Controllers\Api\V1\Client\Profile;

use App\Enums\DepositStatusEnum;
use App\Exceptions\CustomWebException;
use App\Http\Controllers\Controller;
use App\Http\Requests\Api\DepositRequest;
use App\Models\PaymentMethod;
use App\Services\Coin\CoinService;
use App\Services\Payment\Interfaces\PaymentInterface;
use App\Traits\Formatter;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;

class DepositController extends Controller
{
    use Formatter;

    /**
     * @OA\Get(
     *     path="/api/v1/profile/deposits",
     *     summary="Get deposits list",
     *     description="Get deposits list by user",
     *     tags={"Profile/Deposit"},
     *
     *     @OA\Response(
     *         response=200,
     *         description="Deposits list fetched successfully",
     *
     *         @OA\JsonContent(
     *             type="object",
     *
     *             @OA\Property(property="statusCode", type="number", example=200),
     *             @OA\Property(property="data", type="array",
     *
     *                 @OA\Items(
     *                     type="object",
     *
     *                     @OA\Property(property="code", type="string"),
     *                     @OA\Property(property="symbol_position", type="string"),
     *                     @OA\Property(property="symbol", type="string"),
     *                     @OA\Property(property="rate", type="number")
     *                 )
     *             )
     *         )
     *     )
     * )
     */
    public function index()
    {
        /**
         * @var \App\Models\User $user
         */
        $user = Auth::guard('client')->user();

        $deposits = $user->deposits()->with(['payment:id,amount,payable,currency,conversion_rate,charge,currency'])->paginate();

        return $this->withSuccess($deposits);
    }

    /**
     * @OA\Post(
     *     path="/api/v1/profile/deposits",
     *     summary="deposit to wallet",
     *     description="deposit to wallet",
     *     tags={"Profile/Deposit"},
     *
     *     @OA\RequestBody(
     *         required=true,
     *
     *         @OA\JsonContent(
     *             required={"gateway", "amount", "currency"},
     *
     *             @OA\Property(
     *                 property="gateway",
     *                 type="string",
     *                 description="The payment gateway to use for the deposit."
     *             ),
     *             @OA\Property(
     *                 property="amount",
     *                 type="number",
     *                 description="The amount to deposit."
     *             ),
     *             @OA\Property(
     *                 property="currency",
     *                 type="string",
     *                 description="The currency code for the deposit."
     *             ),
     *             example={
     *                 "gateway": "stripe",
     *                 "amount": 100,
     *                 "currency": "USD"
     *             }
     *         )
     *     ),
     *
     *     @OA\Response(
     *         response=200,
     *         description="get payment payment link or show payment form",
     *
     *         @OA\JsonContent(
     *             type="object",
     *
     *             @OA\Property(property="message", type="string", example="Fcm token updated successfully")
     *         )
     *     ),
     *
     *     @OA\Response(
     *         response=404,
     *         description="Not Found error.",
     *
     *         @OA\JsonContent(
     *
     *             @OA\Property(property="statusCode", type="number", example=404),
     *             @OA\Property(property="message", type="string", example="The selected email is invalid.")
     *         )
     *     ),
     *
     *     @OA\Response(
     *         response=422,
     *         description="Validation error",
     *
     *         @OA\JsonContent(
     *
     *             @OA\Property(property="statusCode", type="number", example=422),
     *             @OA\Property(property="message", type="string", example="The given data was invalid."),
     *             @OA\Property(
     *                 property="errors",
     *                 type="object",
     *
     *                 @OA\AdditionalProperties(
     *
     *                     @OA\Property(type="array", @OA\Items(type="string"))
     *                 )
     *             )
     *         )
     *     ),
     *
     *     @OA\Response(
     *         response=500,
     *         description="Internal Server Error",
     *
     *         @OA\JsonContent(
     *
     *             @OA\Property(property="statusCode", type="number", example=500),
     *             @OA\Property(property="message", type="string", example="Something went wrong.")
     *         )
     *     )
     * )
     */
    public function store(DepositRequest $request, PaymentInterface $paymentInterface)
    {
        $validated = $request->validated();

        /**
         * @var \App\Models\User $user
         */
        $user = Auth::guard('client')->user();

        $gateway = PaymentMethod::where('slug', $validated['gateway'])->first();

        if (! $gateway) {
            throw new CustomWebException(__('Gateway not found'));
        }

        $amount = $validated['amount'];

        $coins = CoinService::calculateCoinsFromUSD($amount);

        $charge = $gateway->totalCharge($validated['amount']);

        if (! $gateway->isValidPaymentAmount($amount + $charge)) {
            throw new CustomWebException(__('Invalid amount'));
        }

        DB::beginTransaction();

        try {

            $payable = $paymentInterface->initialize($gateway, $amount, $charge, $validated['currency']);

            $data = $payable->pay($validated);

            $user->deposits()->updateOrCreate([
                'status' => DepositStatusEnum::PENDING,
                'track' => $data['payment']['payment_identifier'],
                'payment_id' => $data['payment']['id'],
            ], [
                'amount' => $amount,
                'coins' => $coins,
                'currency' => $validated['currency'],
                'charge' => $charge,
            ]);

            DB::commit();
        } catch (\Throwable $th) {
            DB::rollBack();
            throw new CustomWebException($th->getMessage());
        }

        return $this->withSuccess($data['response']);
    }

    public function calculateCoinByAmount(Request $request)
    {
        $validated = $request->validate([
            'amount' => 'required|numeric|min:1',
            'currency' => 'required|string|exists:currencies,code',
        ]);

        $totalCoins = CoinService::calculateCoinsFromUSD($validated['amount']);

        return $this->withSuccess($totalCoins);
    }
}
