<?php

namespace App\Http\Controllers\User;

use App\Constants\Status;
use App\Http\Controllers\Controller;
use App\Lib\Matrix;
use App\Models\Payment;
use App\Models\Plan;
use App\Models\UserNotification;
use App\Models\Transaction;
use App\Models\User;
use App\Rules\FileTypeValidate;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;

class PaymentsController extends Controller
{
    protected function getNextExpiresAt($xUnit = '3 hours')
    {
        $now = Carbon::now(); // Current timestamp
        $startOfDay = $now->copy()->setTime(10, 0); // 10 AM of the same day
        $endOfDay = $now->copy()->setTime(18, 0); // 6 PM of the same day

        if ($now->between($startOfDay, $endOfDay)) {
            // If current time is within professional hours, add x units
            $expiredAt = $now->copy()->add($xUnit);
        } else if ($now->isAfter($endOfDay)) {
            // Calculate the next professional start time
            $nextProfessionalTime = $now->copy()->addDay()->setTime(10, 0);

            // Add x units to the next professional time
            $expiredAt = $nextProfessionalTime->add($xUnit);
        } else {
            $expiredAt = $startOfDay->copy()->add($xUnit);
        }

        return $expiredAt;
    }
    public function storePayments(Request $request, $id = 0)
    {
        $this->validate($request, [
            'screen_short' => ['nullable', 'image', new FileTypeValidate(['jpg', 'jpeg', 'png'])],
            'utr_no' => 'required|string|max:255',
            'receiver_user_id' => 'required|integer|exists:users,id',
            'payment_mode' => ['required', 'string', Rule::in([Status::PaymentModeBank, Status::PaymentModeUpi])],
        ]);

        $user = auth()->user();

        $uplinkPayment = $id ? Payment::findOrFail($id) : new Payment();

        if ($id == 0 && (Payment::where('payer_user_id', $user->id)->where('receiver_user_id', $request->receiver_user_id)->exists())) {
            $notify[] = ['error', 'You have already sent a payment to this user'];
            return back()->withNotify($notify);
        }

        if ($request->hasFile('screen_short')) {
            try {
                $uplinkPayment->screen_short = fileUploader($request->screen_short, getFilePath('withdrawMethod'), getFileSize('withdrawMethod'), $uplinkPayment->screen_short);
            } catch (\Exception $exp) {
                $notify[] = ['error', 'Couldn\'t upload your QR code'];
                return back()->withNotify($notify);
            }
        }

        $plan = Plan::first();

        $uplinkPayment->payer_user_id = $user->id;
        $uplinkPayment->receiver_user_id = $request->receiver_user_id;
        $uplinkPayment->utr_no = $request->utr_no;
        $uplinkPayment->status = Status::Pending;
        $uplinkPayment->payment_mode = $request->payment_mode;
        $uplinkPayment->amount = $plan->donation;
        $uplinkPayment->expired_at = $this->getNextExpiresAt();
        $uplinkPayment->created_at = now();

        $uplinkPayment->save();
        $general = gs();
        $userNotification = new UserNotification();
        $userNotification->user_id = $request->receiver_user_id;
        $userNotification->title = $user->username . ' Sent You ' . $general->cur_text . $plan->donation;
        $userNotification->click_url = urlPath('user.notification');
        $userNotification->save();

        $notify[] = ['success', 'payment uploaded successfully'];
        return back()->withNotify($notify);
    }

    public function deletePayment(Request $request, $id)
    {
        $payment = Payment::findOrFail($id);
        $trx = $payment->trx;
        $user = $payment->payerUser;

        DB::transaction(function () use ($payment, $trx, $user) {
            Transaction::where('trx', $trx)->delete();

            $payment->delete();

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

        $notify[] = ['success', 'Payment deleted successfully'];
        return back()->withNotify($notify);
    }

    public function paymentReceived()
    {
        $data['pageTitle'] = 'Received Donations';
        $data['payments'] = Payment::where('receiver_user_id', auth()->id())
            ->with(['payerUser', 'receiverUser'])
            ->latest()
            ->paginate(getPaginate());
        return view($this->activeTemplate . 'payments.received', $data);
    }

    public function paymentPaid()
    {
        $data['pageTitle'] = 'Given Donations';

        $admin = User::firstWhere('username', 'admin');

        $data['payments'] = Payment::where('payer_user_id', auth()->id())
            ->with(['payerUser', 'receiverUser'])
            ->where('receiver_user_id', '!=', $admin->id)
            ->latest()
            ->get();
        return view($this->activeTemplate . 'payments.paid', $data);
    }

    public function updatePaymentStatus(Request $request, $id)
    {
        $payment = Payment::findOrFail($id);

        return DB::transaction(function () use ($request, $payment) {
            $user = auth()->user();
            return match ($request->status) {
                'accept' => $this->handleApprovedPayment($payment, $user),
                'reject' => $this->handleRejectedPayment($payment, $user),
                default => back()->withNotify(['error', 'Invalid status']),
            };
        });
    }

    protected function handleApprovedPayment(Payment $payment, User $user)
    {
        $general = gs();

        $user->balance += $payment->amount;
        $user->save();

        $trx = getTrx();

        $user_data = User::where('id', $user->id)->first();
        if ($user_data->debt_cleared_at === null) {
            if ($user_data->balance > $user_data->current_debt_value) {
                $user_data->debt_cleared_at = now();
                $user_data->save();
                $this->createDebtFeeUserNotification($user_data, 'Your Debt has been cleared ');
            }
        }

        $transaction = new Transaction();
        $transaction->user_id = auth()->id();
        $transaction->amount = $payment->amount;
        $transaction->post_balance = $user->balance;
        $transaction->charge = 0;
        $transaction->trx_type = '+';
        $transaction->details = 'Payment received from ' . $payment->payerUser->username;
        $transaction->remark = Status::DonationReceived;
        $transaction->payment_mode = $payment->payment_mode;
        $transaction->status = Status::Approved;
        $transaction->trx = $trx;
        $transaction->save();

        $payerUser = $payment->payerUser;

        $transaction = new Transaction();
        $transaction->user_id = $payerUser->id;
        $transaction->amount = $payment->amount;
        $transaction->post_balance = $payerUser->balance;
        $transaction->charge = 0;
        $transaction->trx_type = '-';
        $transaction->details = 'Payment made to ' . $user->username;
        $transaction->remark = Status::DonationMade;
        $transaction->payment_mode = $payment->payment_mode;
        $transaction->trx = $trx;
        $transaction->status = Status::Approved;
        $transaction->save();

        $payment->status = Status::Approved;
        $payment->payment_status_confirmed_at = now();
        $payment->trx = $trx;
        $payment->save();
        $this->handlePaymentSideEffect($payment);

        $this->createUserNotification($payment, $user, 'Confirmed your payment of ' . $general->cur_sym . $payment->amount);
        $notify[] = ['success', 'Payment accepted successfully'];
        return back()->withNotify($notify);
    }
    protected function handleRejectedPayment(Payment $payment, User $user)
    {
        $general = gs();

        $payment->status = Status::Rejected;
        $payment->payment_status_confirmed_at = null;
        $payment->save();

        $this->createUserNotification($payment, $user, 'Rejected your payment of ' . $general->cur_sym . $payment->amount);

        $notify[] = ['success', 'Payment rejected successfully'];
        return back()->withNotify($notify);
    }

    private function createUserNotification(Payment $payment, User $user, $message)
    {
        $userNotification = new UserNotification();
        $userNotification->user_id = $payment->payer_user_id;
        $userNotification->title = $user->username . ' ' . $message;
        $userNotification->click_url = urlPath('user.notification');
        $userNotification->save();
    }
    private function createDebtFeeUserNotification(User $user_data, $message)
    {
        $userNotification = new UserNotification();
        $userNotification->user_id = $user_data->id;
        $userNotification->title = $user_data->username . ' ' . $message;
        $userNotification->click_url = urlPath('user.notification');
        $userNotification->save();
    }

    protected function handlePaymentSideEffect($payment)
    {
        $payer = $payment->payerUser;
        $admin = User::firstWhere('username', 'admin');

        if (
            $payer
            ->paidPayments()
            ->where('receiver_user_id', '!=', $admin->id)
            ->where('status', Status::Approved)
            ->count() != 7
        ) {
            return;
        }

        $payer->network_status = Status::NetworkFullActivated;
        $payer->network_activated_at = now();
        $payer->save();

        $matrix = Matrix::set($payer);
        $matrix->addUserToNetwork();
    }
}
