<?php

namespace App\Http\Controllers\User;

use App\Constants\Status;
use App\Exports\ActiveMembersExport;
use App\Exports\InactiveMemberExport;
use App\Exports\MyRewardsExport;
use App\Exports\NetworkExport;
use App\Exports\PartiallyActiveMembersExport;
use App\Exports\RewardsExport;
use App\Http\Controllers\Controller;
use App\Lib\FormProcessor;
use App\Lib\GoogleAuthenticator;
use App\Lib\UserNetwork;
use App\Models\AdminNotification;
use App\Models\Commission;
use App\Models\Coupon;
use App\Models\Form;
use App\Models\Payment;
use App\Models\Plan;
use App\Models\Reward;
use App\Models\Transaction;
use App\Models\User;
use App\Models\UserNotification;
use Illuminate\Http\Request;
use Barryvdh\DomPDF\Facade\Pdf;
use App\Exports\TransactionsExport;
use App\Models\AdminNoteList;
use App\Models\NoticeBoard;
use Illuminate\Pagination\LengthAwarePaginator;
use Maatwebsite\Excel\Facades\Excel;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Response;

class UserController extends Controller
{
    public function home()
    {
        $user = auth()->user();
        $pageTitle = 'Dashboard';
        $admin = User::firstWhere('username', 'admin');

        $transaction = $user->transactions()->count();
        $receivedDonation = Payment::where('receiver_user_id', $user->id)
            ->where('status', Status::Approved)
            ->sum('amount');
        $paidDonation = Payment::where('payer_user_id', $user->id)
            ->whereNot('receiver_user_id', $admin->id)
            ->where('status', Status::Approved)
            ->sum('amount');
        $totalReward = Transaction::where('remark', Status::CommissionReward)->where('user_id', auth()->id())->sum('amount');
        $plan = Plan::first();

        $username = $user->username;
        $balance = $user->balance;

        $referralUsers = app(UserNetwork::class)->getDonarList($user);

        $notice = NoticeBoard::first();

        $payments = Payment::where('payer_user_id', auth()->id())->whereIn('receiver_user_id', $referralUsers->pluck('id'))->get();
        $earnedRewards = Reward::where('user_id', auth()->id())
            ->where('status', Status::Approved)
            ->get();
        return view($this->activeTemplate . 'user.dashboard', compact('pageTitle', 'transaction', 'username', 'plan', 'balance', 'user', 'payments', 'referralUsers', 'receivedDonation', 'paidDonation', 'totalReward', 'earnedRewards', 'notice'));
    }

    public function depositHistory(Request $request)
    {
        $pageTitle = 'Deposit History';
        $deposits = auth()
            ->user()
            ->deposits()
            ->searchable(['trx', 'user:username,system_id'])
            ->with(['gateway'])
            ->orderBy('id', 'desc')
            ->paginate(getPaginate());
        return view($this->activeTemplate . 'user.deposit_history', compact('pageTitle', 'deposits'));
    }

    public function show2faForm()
    {
        $general = gs();
        $ga = new GoogleAuthenticator();
        $user = auth()->user();
        $secret = $ga->createSecret();
        $qrCodeUrl = $ga->getQRCodeGoogleUrl($user->username . '@' . $general->site_name, $secret);
        $pageTitle = '2FA Setting';
        return view($this->activeTemplate . 'user.twofactor', compact('pageTitle', 'secret', 'qrCodeUrl'));
    }

    public function create2fa(Request $request)
    {
        $user = auth()->user();
        $this->validate($request, [
            'key' => 'required',
            'code' => 'required',
        ]);
        $response = verifyG2fa($user, $request->code, $request->key);
        if ($response) {
            $user->tsc = $request->key;
            $user->ts = 1;
            $user->save();
            $notify[] = ['success', 'Google authenticator activated successfully'];
            return back()->withNotify($notify);
        } else {
            $notify[] = ['error', 'Wrong verification code'];
            return back()->withNotify($notify);
        }
    }

    public function disable2fa(Request $request)
    {
        $this->validate($request, [
            'code' => 'required',
        ]);

        $user = auth()->user();
        $response = verifyG2fa($user, $request->code);
        if ($response) {
            $user->tsc = null;
            $user->ts = 0;
            $user->save();
            $notify[] = ['success', 'Two factor authenticator deactivated successfully'];
        } else {
            $notify[] = ['error', 'Wrong verification code'];
        }
        return back()->withNotify($notify);
    }

    public function transactions(Request $request)
    {
        $pageTitle = 'Transactions';
        $remarks = [Status::DonationReceived, Status::DonationMade, Status::CommissionReward, Status::PlanPurchased];

        $transactions = Transaction::where('user_id', auth()->id())
            ->searchable(['trx', 'user:username,system_id'])
            ->filter(['remark'])
            ->dateFilter()
            ->orderBy('id', 'desc')
            ->paginate(getPaginate());

        return view($this->activeTemplate . 'user.transactions', compact('pageTitle', 'transactions', 'remarks'));
    }

    public function generatePdf(Request $request)
    {
        $user = auth()->user();
        $transactions = Transaction::where('user_id', $user->id)
            ->searchable(['trx', 'user:username,system_id'])
            ->filter(['remark'])
            ->dateFilter()
            ->orderBy('id', 'desc')
            ->get();
        $pdf = PDF::loadView($this->activeTemplate . 'user.pdf_blades.transactions_pdf', compact('transactions', 'user'));
        $filename = 'transactions-report-' . date('Y-m-d') . '.pdf';
        return $pdf->download($filename);
    }

    public function kycForm()
    {
        $pageTitle = 'KYC Form';
        $form = Form::where('act', 'kyc')->first();
        return view($this->activeTemplate . 'user.kyc.form', compact('pageTitle', 'form'));
    }

    public function kycData()
    {
        $user = auth()->user();
        $pageTitle = 'KYC Data';
        return view($this->activeTemplate . 'user.kyc.info', compact('pageTitle', 'user'));
    }

    public function kycSubmit(Request $request)
    {
        $form = Form::where('act', 'kyc')->first();
        $formData = $form->form_data;
        $user = auth()->user();
        $formProcessor = new FormProcessor();
        $validationRule = $formProcessor->valueValidation($formData, $user->kyc_data);

        $request->validate($validationRule);
        $userData = $formProcessor->processFormData($request, $formData, $user->kyc_data);

        $user->kyc_data = $userData;
        $user->kv = 2;
        $user->save();

        $notify[] = ['success', 'KYC data submitted successfully'];
        return to_route('user.home')->withNotify($notify);
    }

    public function attachmentDownload($fileHash)
    {
        $filePath = decrypt($fileHash);
        $extension = pathinfo($filePath, PATHINFO_EXTENSION);
        $general = gs();
        $title = slug($general->site_name) . '- attachments.' . $extension;
        $mimetype = mime_content_type($filePath);
        header('Content-Disposition: attachment; filename="' . $title);
        header('Content-Type: ' . $mimetype);
        return readfile($filePath);
    }

    public function userData()
    {
        $user = auth()->user();
        if ($user->profile_complete == 1) {
            return to_route('user.home');
        }
        $pageTitle = 'User Data';
        return view($this->activeTemplate . 'user.user_data', compact('pageTitle', 'user'));
    }

    public function userDataSubmit(Request $request)
    {
        $user = auth()->user();
        if ($user->profile_complete == 1) {
            return to_route('user.home');
        }
        $request->validate([
            'firstname' => 'required',
            'lastname' => 'required',
        ]);
        $user->firstname = $request->firstname;
        $user->lastname = $request->lastname;
        $user->address = [
            'country' => @$user->address->country,
            'address' => $request->address,
            'state' => $request->state,
            'zip' => $request->zip,
            'city' => $request->city,
        ];
        $user->profile_complete = 1;
        $user->save();

        $notify[] = ['success', 'Registration process completed successfully'];
        return to_route('user.kyc.form')->withNotify($notify);
    }

    public function balanceTransfer()
    {
        $general = gs();
        if ($general->balance_transfer != 1) {
            $notify[] = ['warning', "Balance transfer doesn't available this time"];
            return redirect()->route('user.home')->withNotify($notify);
        }
        $pageTitle = 'Balance Transfer';
        return view($this->activeTemplate . 'user.balance_transfer', compact('pageTitle'));
    }

    public function balanceTransferUser(Request $request)
    {
        $general = gs();
        if ($general->balance_transfer != 1) {
            $notify[] = ['warning', "Balance transfer doesn't available this time"];
            return redirect()->route('home')->withNotify($notify);
        }
        $this->validate($request, [
            'amount' => 'required|numeric|gt:0',
            'username' => 'required',
        ]);
        $user = auth()->user();
        $toUser = User::where('status', Status::VERIFIED)
            ->where('username', $request->username)
            ->first();
        if (!$toUser) {
            $notify[] = ['error', 'Receiver not found'];
            return back()->withNotify($notify);
        }
        if ($user->id == $toUser->id) {
            $notify[] = ['error', 'You can not transfer balance to self account.'];
            return back()->withNotify($notify);
        }
        $charge = ($request->amount / 100) * $general->balance_transfer_percent_charge + $general->balance_transfer_fixed_charge;
        $total = $request->amount + $charge;

        if ($total > $user->balance) {
            $notify[] = ['error', 'Your account balance ' . getAmount($user->balance) . ' ' . $general->cur_text . ' not enough for balance transfer'];
            return back()->withNotify($notify);
        }
        $user->balance -= $total;
        $user->save();

        $transaction = new Transaction();
        $transaction->user_id = $user->id;
        $transaction->amount = $total;
        $transaction->post_balance = $user->balance;
        $transaction->charge = $charge;
        $transaction->trx_type = '-';
        $transaction->details = 'Balance Transferred To ' . $toUser->username;
        $transaction->remark = 'balance_send';
        $transaction->trx = getTrx();
        $transaction->save();

        notify($user, 'BAL_TRANSFER_SENDER', [
            'trx' => $transaction->trx,
            'amount' => getAmount($request->amount),
            'charge' => getAmount($charge),
            'after_charge' => getAmount($total),
            'post_balance' => getAmount($user->balance),
        ]);

        $toUser->balance += $request->amount;
        $toUser->save();

        $tranUser = new Transaction();
        $tranUser->user_id = $toUser->id;
        $tranUser->amount = $request->amount;
        $tranUser->post_balance = $toUser->balance;
        $tranUser->trx_type = '+';
        $tranUser->details = 'Balance Transferred From ' . $user->username;
        $tranUser->trx = $transaction->trx;
        $tranUser->remark = 'balance_receive';
        $tranUser->status = Status::Approved;
        $tranUser->save();

        notify($toUser, 'BAL_TRANSFER_RECEIVER', [
            'trx' => $tranUser->trx,
            'amount' => getAmount($tranUser->amount),
            'post_balance' => getAmount($toUser->balance),
        ]);

        $adminNotification = new AdminNotification();
        $adminNotification->user_id = $user->id;
        $adminNotification->admin_id = 1;
        $adminNotification->title = 'Balance Transferred To ' . $toUser->username;
        $adminNotification->click_url = urlPath('admin.report.transaction');
        $adminNotification->save();

        $adminNotification = new AdminNotification();
        $adminNotification->user_id = $user->id;
        $adminNotification->admin_id = 1;
        $adminNotification->title = 'Balance Transferred From ' . $user->username;
        $adminNotification->click_url = urlPath('admin.report.transaction');
        $adminNotification->save();

        $notify[] = ['success', 'Balance has been transfer'];
        return back()->withNotify($notify);
    }

    protected function collectionPaginate($items)
    {
        $perPage = getPaginate();
        $currentPage = LengthAwarePaginator::resolveCurrentPage();
        $currentItems = $items->forPage($currentPage, $perPage);

        $paginatedItems = new LengthAwarePaginator($currentItems, $items->count(), $perPage, $currentPage, ['path' => LengthAwarePaginator::resolveCurrentPath()]);

        return $paginatedItems;
    }

    public function referralLog(Request $request)
    {
        $pageTitle = 'My Network';
        $user = auth()->user();

        $networkService = app(UserNetwork::class);
        $networkData = $networkService->getUsersLevelWise($user);

        $networkData = $networkService->filterNetworkData($networkData);
        $activeMembers = $networkData->where('network_status', Status::NetworkFullActivated)->count();
        $partiallyActiveMembers = $networkService->getPartiallyActiveUsersLevel($user)->count();
        $inactiveMembers = $networkData->where('network_status', Status::NetworkPending)->count();
        $network = $this->collectionPaginate($networkData);

        return view($this->activeTemplate . 'user.referral', compact(
            'pageTitle',
            'user',
            'network',
            'activeMembers',
            'inactiveMembers',
            'partiallyActiveMembers'
        ));
    }

    public function myNetworkTree(Request $request)
    {
        $pageTitle = 'My Network Tree';
        $user = auth()->user();
        return view($this->activeTemplate . 'user.network_tree', compact('pageTitle', 'user'));
    }


    public function myNetworkReport(Request $request)
    {
        $pageTitle = 'My Network Report';
        $user = auth()->user();

        $networkService = app(UserNetwork::class);
        $networkReport = $networkService->getLevelWiseUserCount($user);

        return view($this->activeTemplate . 'user.network-report', compact('pageTitle', 'user', 'networkReport'));
    }

    public function activeMember(Request $request)
    {
        $pageTitle = 'Active Members';
        $user = auth()->user();

        $networkService = app(UserNetwork::class);
        $networkData = $networkService->getActiveUsersLevel($user);
        $networkData = $networkService->filterNetworkData($networkData);
        $network = $this->collectionPaginate($networkData);

        $user = auth()->user();
        return view($this->activeTemplate . 'user.active_member', compact('pageTitle', 'user', 'network'));
    }
    public function partiallyActiveMembers(Request $request)
    {
        $pageTitle = 'Partially Active Members';
        $user = auth()->user();

        $networkService = app(UserNetwork::class);
        $networkData = $networkService->getPartiallyActiveUsersLevel($user);
        $networkData = $networkService->filterNetworkData($networkData);
        $network = $this->collectionPaginate($networkData);

        $user = auth()->user();
        return view($this->activeTemplate . 'user.partially_active_member', compact('pageTitle', 'user', 'network'));
    }

    public function inactiveMember(Request $request)
    {
        $pageTitle = 'Inactive Members';
        $user = auth()->user();

        $userNetworkService = app(UserNetwork::class);
        $networkData = app(UserNetwork::class)->getInactiveUsersLevel($user);
        $networkData = $userNetworkService->getInactiveUsersLevel($user);
        $networkData = $userNetworkService->filterNetworkData($networkData);

        $network = $this->collectionPaginate($networkData);

        return view($this->activeTemplate . 'user.inactive_member', compact('pageTitle', 'user', 'network'));
    }

    public function rewardMember(Request $request)
    {
        $pageTitle = 'List Of Reward Members';
        $user = auth()->user();
        $networkService = app(UserNetwork::class);

        $networkData = $networkService->getRewardedUserList($user);
        $networkData = $networkService->filterRewardData($networkData);

        $network = $this->collectionPaginate($networkData);

        $user = auth()->user();
        return view($this->activeTemplate . 'user.reward_member', compact('pageTitle', 'user', 'network'));
    }

    public function referralCommission()
    {
        $pageTitle = 'My Referral Commissions';
        $commissions = Commission::where('user_id', auth()->id())->where('mark', 1)->with('fromUser')->orderBy('id', 'desc')->paginate(getPaginate());
        return view($this->activeTemplate . 'user.commission', compact('pageTitle', 'commissions'));
    }

    public function levelCommission()
    {
        $pageTitle = 'My Level Commissions';
        $commissions = Commission::where('user_id', auth()->id())->where('mark', 2)->with('fromUser')->orderBy('id', 'desc')->paginate(getPaginate());
        return view($this->activeTemplate . 'user.commission', compact('pageTitle', 'commissions'));
    }

    private function showBelow($id)
    {
        $newArray = [];
        $underReferral = User::where('position_id', $id)->get();
        foreach ($underReferral as $value) {
            array_push($newArray, $value->id);
        }
        return $newArray;
    }

    public function userNotification()
    {
        $pageTitle = 'User Notifications';
        $user = auth()->user();
        $notifications = UserNotification::with('user')
            ->where('user_id', $user->id)
            ->orderBy('id', 'desc')
            ->paginate(getPaginate());
        return view($this->activeTemplate . 'user.notification', compact('pageTitle', 'notifications'));
    }

    public function markAsRead(Request $request)
    {
        $notification = UserNotification::findOrFail($request->id);
        $notification->is_read = 1;
        $notification->save();
        return response()->json(['success' => true]);
    }

    public function markAllAsRead(Request $request)
    {
        $user = auth()->user();
        $notifications = UserNotification::where('user_id', $user->id)->get();
        foreach ($notifications as $notification) {
            $notification->is_read = 1;
            $notification->save();
        }
        return response()->json(['success' => true]);
    }

    public function coupon()
    {
        $pageTitle = 'My Coupon';
        $user = auth()->user();
        $coupons = Coupon::where('user_id', $user->id)
            ->where(function ($query) {
                $query->where('status', Status::CouponActive)->orWhereNotNull('used_at');
            })
            ->orderBy('id', 'desc')
            ->paginate(getPaginate());
        return view($this->activeTemplate . 'user.coupon', compact('pageTitle', 'coupons'));
    }

    public function exportTransactionsExcel(Request $request)
    {
        return Excel::download(new TransactionsExport(), 'transactions.csv');
    }

    public function noticeBoard(Request $request)
    {
        $pageTitle = 'Notice Board';
        $notice = NoticeBoard::where('status', 1)->first();
        if (!$notice) {
            $notice = null;
            $pageTitle = 'There is no notice on the notice board.';
        }

        return view($this->activeTemplate . 'user.noticeBoard', compact('pageTitle', 'notice'));
    }

    public function particularNotice($id)
    {
        $pageTitle = 'Notice Details';
        $notice = NoticeBoard::findOrFail($id);
        return view($this->activeTemplate . 'user.particularNotice', compact('pageTitle', 'notice'));
    }
    public function app_link()
    {
        $pageTitle = 'Download Application';
        $plan = Plan::first();
        return view($this->activeTemplate . 'user.app_link', compact('pageTitle', 'plan'));
    }

    public function downloadAppLink(Request $request)
    {
        $user = auth()->user();

        $user->update([
            'app_downloaded_at' => now()
        ]);

        return redirect()->route('user.home')->with('message', 'Operation completed successfully');
    }
    public function downloadReceipt(Request $request, $id)
    {
        $user = User::findOrFail($id);
        $transection = Transaction::where('user_id', $user->id)->first();
        $plan = Plan::findOrFail($user->plan_id);
        $general = gs();
        return view($this->activeTemplate . 'user.downloadReceipt', compact('user', 'plan', 'transection', 'general'));
    }

    public function exportMyNetwork(Request $request)
    {
        $fileName = 'My-network-Report- ' . date('Y-m-d') . '.csv';
        return Excel::download(new NetworkExport(), $fileName);
    }
    public function exportInactiveMember(Request $request)
    {
        $fileName = 'InactiveMember-Report- ' . date('Y-m-d') . '.csv';
        return Excel::download(new InactiveMemberExport(), $fileName);
    }
    public function exportPartiallyActiveMember(Request $request)
    {
        $fileName = 'PartiallyActiveMember-Report- ' . date('Y-m-d') . '.csv';
        return Excel::download(new PartiallyActiveMembersExport(), $fileName);
    }
    public function exportActiveMember(Request $request)
    {
        $fileName = 'activeMember-Report- ' . date('Y-m-d') . '.csv';
        return Excel::download(new ActiveMembersExport(), $fileName);
    }
    public function exportReward(Request $request)
    {
        $fileName = 'reward-Report- ' . date('Y-m-d') . '.csv';
        return Excel::download(new RewardsExport(), $fileName);
    }

    public function generateMyNetworkPdf(Request $request)
    {
        $user = auth()->user();
        $pageTitle = 'My Network';
        $user = auth()->user();

        $networkService = app(UserNetwork::class);
        $networkData = $networkService->getUsersLevelWise($user);
        $network = $networkService->filterNetworkData($networkData);

        $pdf = PDF::loadView($this->activeTemplate . 'user.pdf_blades.my_network', compact('network', 'user', 'pageTitle'));
        $filename = 'network-report-' . date('Y-m-d') . '.pdf';
        return $pdf->download($filename);
    }
    public function generateActiveMemberPdf(Request $request)
    {
        $user = auth()->user();
        $pageTitle = 'Active Members in Network';
        $user = auth()->user();

        $networkService = app(UserNetwork::class);
        $networkData = $networkService->getActiveUsersLevel($user);
        $network = $networkService->filterNetworkData($networkData);

        $pdf = PDF::loadView($this->activeTemplate . 'user.pdf_blades.my_network', compact('network', 'user', 'pageTitle'));
        $filename = 'Active-Members-report' . date('Y-m-d') . '.pdf';
        return $pdf->download($filename);
    }
    public function generatePartiallyActiveMemberPdf(Request $request)
    {
        $user = auth()->user();
        $pageTitle = 'Partially Active Members in Network';
        $user = auth()->user();

        $cacheKey = 'user:' . $user->id . ':network';
        $networkService = app(UserNetwork::class);
        $networkData = $networkService->getPartiallyActiveUsersLevel($user);
        $network = $networkService->filterNetworkData($networkData);

        $pdf = PDF::loadView($this->activeTemplate . 'user.pdf_blades.my_network', compact('network', 'user', 'pageTitle'));
        $filename = 'Partially-Active-Members-report' . date('Y-m-d') . '.pdf';
        return $pdf->download($filename);
    }
    public function generateInactiveMemberPdf(Request $request)
    {
        $user = auth()->user();
        $pageTitle = 'Inactive Members in Network';
        $user = auth()->user();

        $cacheKey = 'user:' . $user->id . ':network';

        $networkService = app(UserNetwork::class);
        $networkData = $networkService->getInactiveUsersLevel($user);
        $network = $networkService->filterNetworkData($networkData);

        $pdf = PDF::loadView($this->activeTemplate . 'user.pdf_blades.my_network', compact('network', 'user', 'pageTitle'));
        $filename = 'Inactive-Members-report' . date('Y-m-d') . '.pdf';
        return $pdf->download($filename);
    }
    public function generateRewardPdf(Request $request)
    {
        $user = auth()->user();
        $pageTitle = 'Rewards in Network';
        $user = auth()->user();

        $networkService = app(UserNetwork::class);
        $networkData = $networkService->getRewardedUserList($user);
        $network = $networkService->filterRewardData($networkData);

        $pdf = PDF::loadView($this->activeTemplate . 'user.pdf_blades.rewards_pdf', compact('network', 'user', 'pageTitle'));
        $filename = 'Rewarded-Members-report' . date('Y-m-d') . '.pdf';
        return $pdf->download($filename);
    }

    public function myRewardReport(Request $request)
    {
        $pageTitle = 'My Rewards Report';
        $user = auth()->user();

        $rewards = Reward::with('user', 'transaction')->where('user_id', auth()->id())->paginate();
        return view($this->activeTemplate . 'user.reward_report', compact('pageTitle', 'user', 'rewards'));
    }

    public function myRewardPdf(Request $request)
    {
        $network = Reward::with('user', 'transaction')->where('user_id', auth()->id())->paginate();
        $user = auth()->user();
        $pageTitle = 'Export My Reward Report';
        $pdf = PDF::loadView($this->activeTemplate . 'user.pdf_blades.rewards_pdf', compact('network', 'user', 'pageTitle'));
        $filename = 'My-Rewarded-report' . date('Y-m-d') . '.pdf';
        return $pdf->download($filename);
    }

    public function myRewardExcel(Request $request)
    {
        $fileName = 'my-reward-Report- ' . date('Y-m-d') . '.csv';
        return Excel::download(new MyRewardsExport(), $fileName);
    }

    public function downloadPdfList(Request $request)
    {
        $pageTitle = 'List of Files';
        $pdflist = AdminNoteList::searchable(['name'])->where('status', 1)->dateFilter()->orderBy('id', 'desc')->paginate(getPaginate());
        return view($this->activeTemplate . 'user.downloadPdf', compact('pageTitle','pdflist'));
    }

    public function downloadFile($id)
    {
        // Fetch the record from the database by ID
        $record = AdminNoteList::findOrFail($id);

        // Construct the file path
        $filePath = getFilePath('withdrawMethod') . '/' . $record->file;

        // Check if the file exists
        if (File::exists($filePath)) {
            // Return the file as a download
            return Response::download($filePath, $record->file);
        }

        // Return a 404 error if the file does not exist
        abort(404, 'File not found');
    }

}
