<?php

namespace App\Http\Controllers\User;

use App\Models\Bill;
use App\Models\Country;
use App\Models\CryptoTransaction;
use App\Models\Message;
use App\Models\ReferBonus;
use App\Models\Ticket;
use App\Models\TradeGiftCard;
use App\Models\TransactionHistory;
use App\Models\User;
use App\Models\VirtualAccounts;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Image;
use App\Models\Module;
use App\Models\Wallet;
use App\Models\Deposit;
use App\Models\KycForm;
use App\Models\Transaction;
use App\Models\Withdrawals;
use App\Helpers\MediaHelper;
use Illuminate\Http\Request;
use App\Models\Generalsetting;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use App\Http\Resources\User\UserResource;
use App\Traits\RespondsWithHttp;
use KingFlamez\Rave\Facades\Rave as Flutterwave;

class UserController extends Controller
{
    use RespondsWithHttp;

    public function __construct(UserResource $resource)
    {
        $this->resource = $resource;
    }

    public function trnx()
    {
        return Transaction::where('user_id', auth()->id())->where('user_type', 1)->with('currency');
    }

    public function index(Request $request)
    {
        $user = auth()->user();
        if ($user->email_verified != 1) {
            return $this->respond($request, [], 'Please verify your email.', 'user.verify.email');
        }

        $wallet = $user->getMyWallet();
        if (empty($wallet)) {
            $countries = Country::query();
            $currency = $countries->where('name', $user->country)->value('currency_id');
            Wallet::create([
                'user_id' => $user->id,
                'user_type' => 1,
                'currency_id' => $currency,
                'balance' => 0
            ]);
            $wallet = $user->getMyWallet();
        }

        $transactions = $this->trnx()->latest()->take(8)->get();
        $trades = TradeGiftCard::where('user_id', auth()->id())->latest()->take(10)->get();
        $withdraws = Withdrawals::where('user_id', auth()->id())->latest()->take(10)->get();
        $bills = Bill::where('user_id', auth()->id())->latest()->take(10)->get();
        $cryptos = CryptoTransaction::where('user_id', auth()->id())->latest()->take(10)->get();
        $totalRefer = User::where('refer_by', $user->id)->count();
        $totalEarn = ReferBonus::where('owner_id', $user->id)->sum('amount');
        $accounts = VirtualAccounts::where('user_id', $user->id)->get();

        $amount = collect([]);
        $this->trnx()->where('remark', 'transfer_money')->get()->map(function ($q) use ($amount) {
            $amount->push((float) amountConv($q->amount, $q->currency));
        });
        $totalTransferMoney = $amount->sum();

        $exchange = collect([]);
        $this->trnx()->where('remark', 'money_exchange')->get()->map(function ($q) use ($exchange) {
            $exchange->push((float) amountConv($q->amount, $q->currency));
        });
        $totalExchange = $exchange->sum();

        $withdraw = collect([]);
        Withdrawals::where('user_id', auth()->id())->with('currency')->get()->map(function ($q) use ($withdraw) {
            $withdraw->push((float) amountConv($q->amount, $q->currency));
        });
        $totalWithdraw = $withdraw->sum();

        $fiatTrans = TransactionHistory::where('user_id', $user->id)->latest()->limit(10)->get();

        if ($this->expectsJson($request)) {
            return $this->respond($request, [
                'wallet' => $wallet,
                'transactions' => $transactions,
                'trades' => $trades,
                'withdraws' => $withdraws,
                'bills' => $bills,
                'cryptos' => $cryptos,
                'totalRefer' => $totalRefer,
                'totalEarn' => $totalEarn,
                'accounts' => $accounts,
                'totalTransferMoney' => $totalTransferMoney,
                'totalExchange' => $totalExchange,
                'totalWithdraw' => $totalWithdraw,
                'fiatTrans' => $fiatTrans
            ], 'Dashboard data retrieved.');
        }

        return view('user.dashboard', compact('wallet', 'transactions', 'totalTransferMoney', 'totalWithdraw', 'totalExchange', 'trades', 'withdraws', 'cryptos', 'totalRefer', 'bills', 'totalEarn', 'accounts', 'fiatTrans'));
    }

    public function profile(Request $request)
    {
        $user = auth()->user();
        if ($this->expectsJson($request)) {
            return $this->respond($request, ['user' => $user], 'Profile data retrieved.');
        }
        return view('user.profile', compact('user'));
    }

    public function profileSubmit(Request $request)
    {
        $request->validate([
            'name' => 'required',
            'phone' => 'required',
        ]);

        $user = auth()->user();
        $user->name = $request->name;
        $user->phone = $request->phone;
        $user->city = $request->city;
        $user->zip = $request->zip;
        $user->address = $request->address;

        if ($request->photo) {
            $user->photo = MediaHelper::handleMakeImage($request->photo, [300, 300]);
        }
        $user->update();

        return $this->respond($request, [], 'Profile has been updated');
    }

    public function changePass(Request $request)
    {
        $request->validate(['old_pass' => 'required', 'password' => 'required|min:6|confirmed']);
        $user = auth()->user();
        if (Hash::check($request->old_pass, $user->password)) {
            $password = bcrypt($request->password);
            $user->password = $password;
            $user->save();
            return $this->respond($request, [], 'Password has been changed');
        }
        return $this->respondWithError($request, 'The old password doesn\'t match!');
    }

    public function moduleOff(Request $request, $module)
    {
        $key = str_replace('_', '-', $module);
        $mod = Module::where('module', $key)->first();
        if ($mod && $mod->status == 1) {
            return redirect(url('user/' . $key));
        }
        if ($this->expectsJson($request)) {
            return $this->respond($request, [], 'Module is currently disabled.');
        }
        return view('user.module_off', compact('module'));
    }

    public function kycForm(Request $request)
    {
        $user = auth()->user();
        if ($user->kyc_status == 2) {
            return $this->respondWithError($request, 'You have already submitted the KYC data.');
        }
        if ($user->kyc_status == 1) {
            return $this->respondWithError($request, 'Your KYC data is already verified.');
        }
        $kycForm = KycForm::where('user_type', 1)->get();
        if ($this->expectsJson($request)) {
            return $this->respond($request, ['kycForm' => $kycForm], 'KYC form data retrieved.');
        }
        return view('user.kyc_form', compact('kycForm'));
    }

    public function kycFormSubmit(Request $request)
    {
        $data = $request->except('_token');
        $kycForm = KycForm::where('user_type', 1)->get();
        $rules = [];

        foreach ($kycForm as $value) {
            if ($value->required == 1) {
                if ($value->type == 2) {
                    $rules[$value->name] = 'required|image|mimes:png,jpg,jpeg|max:5120';
                } else {
                    $rules[$value->name] = 'required';
                }
            }
            if ($value->max_length > 0) {
                $rules[$value->name] = ['required', 'size:' . $value->max_length];
            }

            if ($value->type == 2) {
                $rules[$value->name] = 'image|mimes:png,jpg,jpeg|max:5120';
                if (request("$value->name")) {
                    $filename = MediaHelper::handleMakeImage(request("$value->name"));
                    unset($data[$value->name]);
                    $data['image'][$value->name] = $filename;
                }
            }

            if ($value->type == 3) {
                unset($data[$value->name]);
                $data['details'][$value->name] = request("$value->name");
            }
        }
        $rules['bvn'] = ['required', 'digits:11'];

        $request->validate($rules);

        $user = auth()->user();
        $dataFlutter = [
            'email' => $user->email,
            'is_permanent' => 'true',
            'bvn' => $request->bvn,
            'tx_ref' => "R2TU" . $user->id,
            'phonenumber' => $user->phone,
            'firstname' => $user->first_name,
            'lastname' => $user->surname,
            'narration' => "R2T-" . $user->name
        ];

        try {
            $account = Flutterwave::banks()->createAccount($dataFlutter);
            if ($account['status'] == 'success') {
                $accountData = $account['data'];
                $user->account_number = $accountData['account_number'];
                $user->bank_name = $accountData['bank_name'];
                $user->account_expired = $accountData['expiry_date'];
                $user->account_created = $accountData['created_at'];
                $user->account_tx_ref = "R2TU" . $user->id;
                $user->flw_ref = $accountData['flw_ref'];
            } else {
                return $this->respondWithError($request, 'Invalid BVN or KYC data. Please check your input.');
            }
        } catch (\Exception $e) {
            \Log::error('Flutterwave account creation failed: ' . $e->getMessage());
            return $this->respondWithError($request, 'Failed to create account. Please try again later.');
        }

        $user->bvn = $request->bvn;
        $user->kyc_info = $data;
        $user->kyc_status = 2;
        $user->save();

        Wallet::where('user_id', $user->id)->update(['flw_ref' => $user->account_tx_ref]);

        return $this->respond($request, [], 'KYC data has been submitted for review.', 'user.dashboard');
    }

    public function generateQR(Request $request)
    {
        if ($this->expectsJson($request)) {
            return $this->respond($request, [], 'QR code generation not available via API.');
        }
        return view('user.qr');
    }

    public function transactions(Request $request)
    {
        $remark = request('remark');
        $search = request('search');

        $transactions = Transaction::where('user_id', auth()->id())->where('user_type', 1)
            ->when($remark, function ($q) use ($remark) {
                return $q->where('remark', $remark);
            })
            ->when($search, function ($q) use ($search) {
                return $q->where('trnx', $search);
            })
            ->with('currency')->latest()->paginate(15);

        if ($this->expectsJson($request)) {
            return $this->respond($request, ['transactions' => $transactions, 'search' => $search], 'Transactions retrieved.');
        }
        return view('user.transactions', compact('transactions', 'search'));
    }

    public function trxDetails(Request $request, $id)
    {
        $transaction = Transaction::where('id', $id)->where('user_id', auth()->id())->first();
        if (!$transaction) {
            return $this->respondWithError($request, 'Transaction not found.');
        }
        if ($this->expectsJson($request)) {
            return $this->respond($request, ['transaction' => $transaction], 'Transaction details retrieved.');
        }
        return view('user.trx_details', compact('transaction'));
    }

    public function twoStep(Request $request)
    {
        if ($this->expectsJson($request)) {
            return $this->respond($request, [], 'Two-step settings not available via API.');
        }
        return view('user.twostep.two_step');
    }

    public function twoStepSendCode(Request $request)
    {
        $request->validate(['password' => 'required|confirmed']);
        $user = auth()->user();
        if (Hash::check($request->password, $user->password)) {
            $code = randNum();
            $user->two_fa_code = $code;
            $user->update();
            try {
                sendSMS($user->phone, trans('Your two step authentication OTP is: ') . $code, Generalsetting::value('contact_no'));
            } catch (\Exception $e) {
                \Log::error('SMS sending failed: ' . $e->getMessage());
            }
            return $this->respond($request, [], 'OTP code is sent to your phone.', 'user.two.step.verify');
        }
        return $this->respondWithError($request, 'The password doesn\'t match!');
    }

    public function twoStepVerifyForm(Request $request)
    {
        if ($this->expectsJson($request)) {
            return $this->respond($request, [], 'Two-step verification form not available via API.');
        }
        return view('user.twostep.verify');
    }

    public function twoStepVerifySubmit(Request $request)
    {
        $request->validate(['code' => 'required']);
        $user = auth()->user();
        if ($request->code != $user->two_fa_code) {
            return $this->respondWithError($request, 'Invalid OTP');
        }
        if ($user->two_fa_status == 1) {
            $user->two_fa_status = 0;
            $user->two_fa = 0;
            $msg = 'Your two step authentication is de-activated';
        } else {
            $user->two_fa_status = 1;
            $msg = 'Your two step authentication is activated';
        }
        $user->save();
        return $this->respond($request, [], $msg, 'user.two.step');
    }

    public function downloadQR(Request $request, $email)
    {
        if ($this->expectsJson($request)) {
            return $this->respond($request, [], 'QR code download not available via API.');
        }
        $file = generateQR($email);
        $file = file_get_contents($file);
        $image = Image::make($file);
        $extension = str_replace('image/', '', $image->mime);
        $filename = 'QrCode_' . $email . '_.' . $extension;
        $qrCode = $image->opacity(100)->fit(350, 350);
        $qrCode->encode('jpg');

        $headers = [
            'Content-Type' => $image->mime,
            'Content-Disposition' => 'attachment; filename=' . $filename,
        ];
        return response()->stream(function () use ($qrCode) {
            echo $qrCode;
        }, 200, $headers);
    }

    public function saveReferCode(Request $request)
    {
        $request->validate([
            'my_referer_code' => 'required|unique:users'
        ]);

        $user = User::where('id', auth()->user()->id)->first();
        $user->my_referer_code = $request->my_referer_code;
        $user->save();

        return $this->respond($request, [], 'Referral code saved successfully.');
    }

    public function wallet(Request $request)
    {
        $wallet = auth()->user()->getMyWallet();
        $accounts = VirtualAccounts::where('user_id', auth()->user()->id)->get();

        if ($this->expectsJson($request)) {
            return $this->respond($request, ['wallet' => $wallet, 'accounts' => $accounts], 'Wallet data retrieved.');
        }
        return view('user.wallets.wallet', compact('wallet', 'accounts'));
    }

    public function referbonusList(Request $request)
    {
        $refer = ReferBonus::where('owner_id', auth()->user()->id)->latest()->paginate(20);

        if ($this->expectsJson($request)) {
            return $this->respond($request, ['refer' => $refer], 'Referral bonuses retrieved.');
        }
        return view('user.referbonus.earning_list', compact('refer'));
    }

    public function notifications(Request $request)
    {
        $auth = auth()->user();
        $data['page_title'] = "Notifications";
        $data['notify'] = Post::whereNotify(1)->latest()->get();

        if ($this->expectsJson($request)) {
            return $this->respond($request, ['notifications' => $data['notify']], 'Notifications retrieved.');
        }
        return view('user.notifications', $data);
    }

    public function inbox(Request $request)
    {
        $auth = auth()->user();
        $data['page_title'] = "Inbox";
        $data['code'] = strtoupper(Str::random(6));
        $data['inbox'] = Message::where('user_id', $auth->id)->whereAdmin(1)->orderBy('created_at', 'desc')->paginate(7);

        if ($this->expectsJson($request)) {
            return $this->respond($request, ['inbox' => $data['inbox'], 'code' => $data['code']], 'Inbox retrieved.');
        }
        return view('user.inbox.inbox', $data);
    }

    public function tickets(Request $request)
    {
        $auth = auth()->user();
        $data['page_title'] = "Support Ticket";
        $data['inbox'] = Message::where('user_id', $auth->id)->whereAdmin(0)->orderBy('created_at', 'desc')->paginate(7);

        if ($this->expectsJson($request)) {
            return $this->respond($request, ['tickets' => $data['inbox']], 'Tickets retrieved.');
        }
        return view('user.ticket', $data);
    }

    public function createTicket(Request $request)
    {
        if ($this->expectsJson($request)) {
            return $this->respond($request, [], 'Ticket creation form not available via API.');
        }
        return view('user.create_ticket');
    }

    public function ticketview(Request $request, $id)
    {
        $auth = auth()->user();
        $data['page_title'] = "Ticket View";
        $data['tickets'] = Message::where('user_id', $auth->id)->whereCode($id)->orderBy('created_at', 'desc')->get();
        $data['ticket'] = Ticket::where('user_id', $auth->id)->whereCode($id)->first();

        $inbox = Message::where('user_id', $auth->id)->whereCode($id)->first();
        if ($inbox) {
            $inbox->status = 1;
            $inbox->save();
        }

        if ($this->expectsJson($request)) {
            return $this->respond($request, ['tickets' => $data['tickets'], 'ticket' => $data['ticket']], 'Ticket details retrieved.');
        }
        return view('user.ticket-view', $data);
    }

    public function inboxview(Request $request, $id)
    {
        $auth = auth()->user();
        $data['page_title'] = "Inbox View";
        $data['inbox'] = Message::where('user_id', $auth->id)->whereId($id)->first();
        $data['code'] = strtoupper(Str::random(6));

        if ($data['inbox']) {
            $data['inbox']->status = 1;
            $data['inbox']->save();
        }

        if ($this->expectsJson($request)) {
            return $this->respond($request, ['inbox' => $data['inbox'], 'code' => $data['code']], 'Inbox message retrieved.');
        }
        return view('user.inbox.inbox-view', $data);
    }

    public function inboxdelete(Request $request, $id)
    {
        $auth = auth()->user();
        $inbox = Message::where('user_id', $auth->id)->whereId($id)->first();
        if ($inbox) {
            $inbox->delete();
            return $this->respond($request, [], 'Message deleted successfully.');
        }
        return $this->respondWithError($request, 'Message not found.');
    }

    public function postticket(Request $request)
    {
        $code = strtoupper(Str::random(6));
        $data = [
            'user_id' => auth()->user()->id,
            'title' => $request->subject,
            'details' => $request->body,
            'desk' => $request->desk,
            'code' => $code,
            'status' => 0,
            'type' => 1
        ];

        if ($request->hasFile('image')) {
            $request->validate(['image' => 'image|mimes:jpeg,png,jpg,gif,svg']);
            $data['image'] = uniqid() . '.jpg';
            $request->image->move('uploads/messages', $data['image']);
        }

        Message::create($data);

        $data1 = [
            'user_id' => auth()->user()->id,
            'title' => $request->subject,
            'details' => $request->body,
            'desk' => $request->desk,
            'code' => $code,
            'status' => 0
        ];

        Ticket::create($data1);

        return $this->respond($request, [], 'Ticket created successfully.');
    }

    public function replyticket(Request $request)
    {
        $auth = auth()->user();
        $ticket = Ticket::where('user_id', $auth->id)->whereCode($request->code)->first();
        if (!$ticket) {
            return $this->respondWithError($request, 'Ticket not found.');
        }

        $data = [
            'user_id' => $auth->id,
            'title' => $ticket->title,
            'details' => $request->body,
            'desk' => $ticket->desk,
            'code' => $ticket->code,
            'status' => 0,
            'type' => 1
        ];

        if ($request->hasFile('image')) {
            $request->validate(['image' => 'image|mimes:jpeg,png,jpg,gif,svg']);
            $data['image'] = uniqid() . '.jpg';
            $request->image->move('uploads/messages', $data['image']);
        }

        Message::create($data);

        return $this->respond($request, [], 'Ticket replied successfully.');
    }
}