<?php

namespace App\Http\Controllers;

use App\Constants\Status;
use App\Lib\Matrix;
use App\Models\Gateway;
use App\Models\Level;
use App\Models\Payment;
use App\Models\Plan;
use App\Models\PlanPurchase;
use App\Models\Transaction;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Razorpay\Api\Api;
use Razorpay\Api\Errors\SignatureVerificationError;

class PlanController extends Controller
{
    public function plan()
    {
        $pageTitle = 'Plan Subscribe';
        $plans = Plan::where('status', Status::ENABLE)
            ->orderby('id', 'asc')
            ->paginate(getPaginate());
        $levels = Level::orderBy('level', 'asc')->get();

        return view($this->activeTemplate . 'plan', compact('pageTitle', 'plans', 'levels'));
    }

    public function planOrder($id)
    {
        $plan = Plan::with('level')->findOrFail($id);
        $user = User::with('referral')->find(auth()->id());

        $notify[] = ['success', 'The plan has been subscribed'];
        return back()->withNotify($notify);
    }

    public function purchasePlan($id)
    {
        DB::transaction(function () use ($id) {
            $plan = Plan::findOrFail($id);
            $user = auth()->user();
            $trx = getTrx();

            PlanPurchase::create([
                'user_id' => $user->id,
                'plan_id' => $plan->id,
                'price' => $plan->price,
                'status' => Status::Approved,
                'trx' => $trx,
            ]);

            $user->plan_id = $plan->id;
            $user->network_status = Status::NetworkPlanPurchased;
            $user->save();
        });
        $notify[] = ['success', 'The plan has been purchased'];
        return back()->withNotify($notify);
    }

    public function initiate(Request $request)
    {
        $paymentMethod = Gateway::firstWhere('alias', 'Razorpay');
        $params = json_decode($paymentMethod->gateway_parameters, true);
        $plan = Plan::first();

        try {
            $transaction = DB::transaction(function () use ($plan, $params) {
                $trx = getTrx();
                $api = new Api($params['key_id']['value'], $params['key_secret']['value']);

                $orderData = $api->order->create([
                    'receipt' => $trx,
                    'amount' => $plan->discounted_plan_price * 100,
                    'currency' => 'INR',
                ]);

                Transaction::where('user_id', auth()->id())
                    ->where('remark', Status::PlanPurchased)
                    ->where('status', Status::Pending)
                    ->delete();

                return Transaction::create([
                    'user_id' => auth()->id(),
                    'trx' => $trx,
                    'details' => 'Plan purchased by online payment',
                    'remark' => Status::PlanPurchased,
                    'status' => Status::Pending,
                    'payment_mode' => Status::PaymentModeGateway,
                    'charge' => 0,
                    'post_balance' => auth()->user()->balance,
                    'trx_type' => '+',
                    'amount' => $plan->discounted_plan_price,
                    'metadata' => $orderData->toArray(),
                ]);
            });

            return view($this->activeTemplate . 'user.payment', [
                'key' => $params['key_id']['value'],
                'transaction' => $transaction,
                'pageTitle' => 'Plan purchase initiated.',
                'plan' => $plan,
            ]);
        } catch (\Throwable $th) {
            return back()->withNotify([['error', 'Payment can not be initiated.']]);
        }
    }

    public function paymentStatus(Request $request)
    {
        $paymentMethod = Gateway::firstWhere('alias', 'Razorpay');
        $params = json_decode($paymentMethod->gateway_parameters, true);

        $orderId = $request->input('razorpay_order_id');
        $paymentId = $request->input('razorpay_payment_id');
        $signature = $request->input('razorpay_signature');

        $sig = hash_hmac('sha256', $orderId . '|' . $paymentId, $params['key_secret']['value']);
        $trx = Transaction::where('trx', $request->trx)->first();
        if ($sig == $signature) {
            $this->approvePlanPurchase($trx, $paymentId);
            $notify[] = ['success', 'The plan has been purchased'];
            return redirect()->route('user.home')->withNotify($notify);
        } else {
            $this->rejectPlanPurchase($trx);
            $trx->status = Status::Rejected;
            $trx->save();
        }

        $notify[] = ['error', 'Transaction failed'];
        return redirect()->route('user.home')->withNotify($notify);
    }

    protected function approvePlanPurchase(Transaction $trx, string $paymentId)
    {
        $trx->status = Status::Approved;
        $trx->save();

        $user = $trx->user;
        $plan = Plan::first();

        $user->plan_id = $plan->id;
        $user->network_status = Status::NetworkPlanPurchased;
        $user->save();

        Payment::create([
            'payer_user_id' => $user->id,
            'receiver_user_id' => User::where('username', 'admin')->first()->id,
            'utr_no' => $paymentId,
            'amount' => $plan->discounted_plan_price,
            'status' => Status::Approved,
            'payment_mode' =>  $trx->payment_mode,
            'trx' =>  $trx->trx,
        ]);
    }

    protected function rejectPlanPurchase($trx)
    {
        $trx->status = Status::Rejected;
        $trx->save();

        $user = $trx->user;
        $user->network_status = Status::NetworkPending;
        $user->save();
    }

    public function webhook(Request $request)
    {
        try {
            $paymentMethod = Gateway::firstWhere('alias', 'Razorpay');
            $params = json_decode($paymentMethod->gateway_parameters, true);
            $api = new Api($params['key_id']['value'], $params['key_secret']['value']);
            $api->utility->verifyWebhookSignature(
                $request->getContent(),
                $request->header('X-Razorpay-Signature'),
                $params['webhook_secret']['value']
            );
            $success = true;
        } catch (SignatureVerificationError $e) {
            $success = false;
            Log::channel('daily')->error($e->getMessage());
            return ['success' => false];
        }

        if (!$success) {
            return response()->json(['success' => false], 400);
        }

        if ($request->get('event') == 'payment.captured') {
            $orderId = data_get($request->payload, 'payment.entity.order_id');
            $transaction = Transaction::whereJsonContains('metadata->id', $orderId)->first();

            if ($transaction->status == Status::Approved) return ['success' => true];

            $this->approvePlanPurchase($transaction, data_get($request->payload, 'payment.entity.id'));
        }

        if ($request->get('event') == 'payment.failed') {
            $this->rejectPlanPurchase($transaction);
            return ['success' => false];
        }

        return ['success' => true];
    }
}
