<?php

namespace App\Http\Controllers;

use Stripe\Stripe;
use App\Models\Job;
use App\Models\Page;
use App\Models\User;
use App\Models\Event;
use App\Models\Group;
use App\Models\Deposit;
use App\Models\Withdraw;
use Stripe\PaymentIntent;
use App\Models\Transaction;
use App\Models\ReportModule;
use Illuminate\Http\Request;
use App\Models\Marketplace\Product;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Stripe\Exception\InvalidRequestException;

class UserController extends Controller
{
    /**
     * Display wallet overview
     */
    public function wallet(Request $request)
    {
        $user = auth()->user();
        $balance = getUserWallet($user->id);
        $recentTransactions = Transaction::where('user_id', $user->id)
            ->orderBy('created_at', 'desc')
            ->limit(5)
            ->get();

        return view('front_end.pages.wallet.wallet', compact('user', 'balance', 'recentTransactions'));
    }

    /**
     * Show deposit form
     */
    public function deposit(Request $request)
    {
        $user = auth()->user();
        $stripeKey = config('services.stripe.publishable_key');

        return view('wallet.deposit', compact('user', 'stripeKey'));
    }

    /**
     * Add balance to wallet
     */
    public function addBalance(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'amount' => 'required|numeric|min:1',
            'payment_method' => 'required|in:stripe,paypal',
            'payment_intent_id' => 'required_if:payment_method,stripe',
            'transaction_id' => 'required_if:payment_method,paypal'
        ]);

        if ($validator->fails()) {
            return response()->json([
                'status' => 'error',
                'message' => $validator->errors()->first()
            ], 422);
        }

        $user = auth()->user();
        $amount = $request->amount;
        $paymentMethod = $request->payment_method;

        try {
            if ($paymentMethod === 'stripe') {
                return $this->processStripePayment($request, $user, $amount);
            } elseif ($paymentMethod === 'paypal') {
                return $this->processPaypalPayment($request, $user, $amount);
            }
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Payment processing failed: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * Process Stripe payment
     */
    private function processStripePayment(Request $request, $user, $amount)
    {
        Stripe::setApiKey(config('services.stripe.secret_key'));

        try {
            $paymentIntent = PaymentIntent::retrieve($request->payment_intent_id);

            if ($paymentIntent->status === 'succeeded') {
                $this->depositAmountInWallet($user->id, $amount, 2, $request->payment_intent_id, 'USD');

                return response()->json([
                    'status' => 'success',
                    'message' => 'Balance added successfully',
                    'data' => [
                        'amount' => $amount,
                        'new_balance' => getUserWallet($user->id)
                    ]
                ]);
            } else {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Payment not completed'
                ], 400);
            }
        } catch (InvalidRequestException $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Invalid payment intent'
            ], 400);
        }
    }

    /**
     * Process PayPal payment
     */
    private function processPaypalPayment(Request $request, $user, $amount)
    {
        // Verify PayPal transaction
        $transaction = $this->getPaypalTransactionDetails($request->transaction_id);

        if ($transaction && $transaction['payer']['status'] === 'VERIFIED') {
            $this->depositAmountInWallet($user->id, $amount, 1, $request->transaction_id, 'USD');

            return response()->json([
                'status' => 'success',
                'message' => 'Balance added successfully',
                'data' => [
                    'amount' => $amount,
                    'new_balance' => getUserWallet($user->id)
                ]
            ]);
        } else {
            return response()->json([
                'status' => 'error',
                'message' => 'PayPal transaction verification failed'
            ], 400);
        }
    }

    /**
     * Stripe success callback
     */
    public function stripeSuccess(Request $request)
    {
        return response()->json([
            'status' => 'success',
            'message' => 'Payment completed successfully'
        ]);
    }

    /**
     * Stripe cancel callback
     */
    public function stripeCancel(Request $request)
    {
        return response()->json([
            'status' => 'error',
            'message' => 'Payment was cancelled'
        ]);
    }

    /**
     * Get deposit list
     */
    public function depositList(Request $request)
    {
        $user = auth()->user();
        $deposits = Deposit::where('user_id', $user->id)
            ->orderBy('created_at', 'desc')
            ->paginate(15);

        return view('wallet.deposit-list', compact('user', 'deposits'));
    }

    /**
     * Show withdraw form
     */
    public function withdraw(Request $request)
    {
        $user = auth()->user();
        $balance = getUserWallet($user->id);
        $withdrawMethods = [
            ['id' => 1, 'name' => 'PayPal', 'min_amount' => 10],
            ['id' => 2, 'name' => 'Bank Transfer', 'min_amount' => 50]
        ];

        return view('wallet.withdraw', compact('user', 'balance', 'withdrawMethods'));
    }

    /**
     * Process withdrawal request
     */
    public function withdrawRequest(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'amount' => 'required|numeric|min:10',
            'withdraw_method_id' => 'required|in:1,2',
            'payment_details' => 'required|array',
            'notes' => 'nullable|string|max:500'
        ]);

        if ($validator->fails()) {
            return back()->withErrors($validator)->withInput();
        }

        $user = auth()->user();
        $amount = $request->amount;
        $balance = getUserWallet($user->id);

        // Check sufficient balance
        if ($amount > $balance) {
            return back()->withErrors(['amount' => 'Insufficient balance'])->withInput();
        }

        // Check minimum amount based on method
        $minAmount = $request->withdraw_method_id == 1 ? 10 : 50;
        if ($amount < $minAmount) {
            return back()->withErrors(['amount' => "Minimum withdrawal amount for this method is \${$minAmount}"])->withInput();
        }

        try {
            $withdrawal = new Withdraw();
            $withdrawal->user_id = $user->id;
            $withdrawal->withdraw_method_id = $request->withdraw_method_id;
            $withdrawal->amount = $amount;
            $withdrawal->currency = 'USD';
            $withdrawal->charge = 0;
            $withdrawal->final_amo = $amount;
            $withdrawal->withdraw_status = 0; // Pending
            $withdrawal->notes = $request->notes;
            $withdrawal->save();

            // Create transaction record
            $transaction = new Transaction();
            $transaction->user_id = $user->id;
            $transaction->flag = 'D';
            $transaction->amount = $amount;
            $transaction->description = 'Withdrawal request - ' . ($request->withdraw_method_id == 1 ? 'PayPal' : 'Bank Transfer');
            $transaction->save();

            return redirect()->route('wallet.index')->with('success', 'Withdrawal request submitted successfully. It will be processed within 2-5 business days.');
        } catch (\Exception $e) {
            return back()->withErrors(['error' => 'Failed to submit withdrawal request: ' . $e->getMessage()])->withInput();
        }
    }

    /**
     * Show withdraw list
     */
    public function withdraw_list(Request $request)
    {
        $user = auth()->user();
        $withdrawals = Withdraw::where('user_id', $user->id)
            ->orderBy('created_at', 'desc')
            ->paginate(15);

        return view('wallet.withdraw-list', compact('user', 'withdrawals'));
    }

    /**
     * Show transfer amount form
     */
    public function transferAmount(Request $request)
    {
        $user = auth()->user();
        $balance = getUserWallet($user->id);

        return view('wallet.transfer', compact('user', 'balance'));
    }

    /**
     * Process transfer amount to another user
     */
    public function processTransfer(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'to_user_id' => 'required|exists:users,id',
            'amount' => 'required|numeric|min:1',
            'password' => 'required'
        ]);

        if ($validator->fails()) {
            return back()->withErrors($validator)->withInput();
        }

        $user = auth()->user();
        $toUserId = $request->to_user_id;
        $amount = $request->amount;

        // Verify password
        if (!Hash::check($request->password, $user->password)) {
            return back()->withErrors(['password' => 'Incorrect password'])->withInput();
        }

        // Check if user is trying to transfer to themselves
        if ($toUserId == $user->id) {
            return back()->withErrors(['to_user_id' => 'Cannot transfer amount to yourself'])->withInput();
        }

        // Check sufficient balance
        $userBalance = getUserWallet($user->id);
        if ($amount > $userBalance) {
            return back()->withErrors(['amount' => 'Insufficient balance. Available: ' . $userBalance])->withInput();
        }

        // Check user level requirement
        if ($user->level == 1) {
            return back()->withErrors(['level' => 'Please upgrade your package to transfer funds'])->withInput();
        }

        // Verify recipient user exists
        $recipient = User::find($toUserId);
        if (!$recipient) {
            return back()->withErrors(['to_user_id' => 'Recipient user not found'])->withInput();
        }

        try {
            // Debit from sender
            $debitTransaction = new Transaction();
            $debitTransaction->user_id = $user->id;
            $debitTransaction->flag = 'D';
            $debitTransaction->amount = $amount;
            $debitTransaction->description = 'Amount transferred to ' . $recipient->name;
            $debitTransaction->save();

            // Credit to recipient
            $creditTransaction = new Transaction();
            $creditTransaction->flag = 'C';
            $creditTransaction->user_id = $toUserId;
            $creditTransaction->amount = $amount;
            $creditTransaction->description = 'Amount received from ' . $user->name;
            $creditTransaction->save();

            return redirect()->route('wallet.index')->with('success', 'Amount transferred successfully to ' . $recipient->name);
        } catch (\Exception $e) {
            return back()->withErrors(['error' => 'Transfer failed: ' . $e->getMessage()])->withInput();
        }
    }

    /**
     * Get users for transfer
     */
    public function get_users(Request $request)
    {
        $user = auth()->user();
        $search = $request->get('search', '');

        $users = User::where('id', '!=', $user->id)
            ->where(function ($query) use ($search) {
                $query->where('name', 'like', "%{$search}%")
                    ->orWhere('email', 'like', "%{$search}%")
                    ->orWhere('username', 'like', "%{$search}%");
            })
            ->select('id', 'name', 'email', 'username', 'profile_picture')
            ->limit(20)
            ->get();

        return response()->json([
            'status' => 'success',
            'data' => $users
        ]);
    }

    /**
     * Deposit amount in wallet
     */
    private function depositAmountInWallet($userId, $amount, $methodId, $transactionId, $currency = 'USD')
    {
        $deposit = new Deposit();
        $deposit->user_id = $userId;
        $deposit->withdraw_method_id = $methodId;
        $deposit->amount = $amount;
        $deposit->currency = strtoupper($currency);
        $deposit->charge = 0;
        $deposit->final_amo = $amount;
        $deposit->deposit_status = 1;
        $deposit->transaction_id = $transactionId;
        $deposit->save();

        $transaction = new Transaction();
        $transaction->user_id = $userId;
        $transaction->flag = 'C';
        $transaction->amount = $amount;
        $transaction->description = 'Amount deposited';
        $transaction->save();
    }

    /**
     * Get PayPal transaction details
     */
    private function getPaypalTransactionDetails($transactionId)
    {
        // This would typically call PayPal's API to verify the transaction
        // For now, returning a mock response
        return [
            'payer' => ['status' => 'VERIFIED'],
            'transactions' => [
                [
                    'amount' => ['total' => '100.00'],
                    'related_resources' => [
                        [
                            'sale' => [
                                'transaction_fee' => ['value' => '3.20']
                            ]
                        ]
                    ]
                ]
            ]
        ];
    }
    public function reportModule(Request $request)
    {
        // Centralized validation
        $validator = Validator::make($request->all(), [
            'module_id' => 'required',
            'module_name' => 'required',
            'reason' => 'required',
        ], [
            'module_id.required' => __('Api.moduleid_required'),
            'module_name.required' => __('Api.modulename_required'),
            'reason.required' => __('Api.reason_required'),
        ]);

        // If validation fails
        if ($validator->fails()) {
            return response()->json([
                'status' => 400,
                'message' => $validator->errors()->first(),
            ], 200);
        }

        // Extract validated data
        $module_id = $request->input('module_id');
        $module_name = $request->input('module_name');
        $reason = $request->input('reason');
        $user = $request->user();  // Get authenticated user

        // Check if the report has already been submitted
        $checkAlreadyReport = ReportModule::where([
            'user_id' => $user->id,
            'module_id' => $module_id,
            'module_name' => $module_name,
        ])->first();

        if ($checkAlreadyReport) {
            return response()->json([
                'status' => 400,
                'message' => __('Api.already_reported'),
            ], 200);
        }

        // Handle different module types in a single function
        switch ($module_name) {
            case 'product':
                $module = Product::find($module_id);
                $user_column = 'user_id';
                $not_found_message = __('Api.product_not_found');
                $cannot_report_message = __('Api.cannot_report_your_own_product');
                break;

            case 'event':
                $module = Event::find($module_id);
                $user_column = 'user_id';
                $not_found_message = __('Api.event_not_found');
                $cannot_report_message = __('Api.cannot_report_your_own_event');
                break;

            case 'page':
                $module = Page::find($module_id);
                $user_column = 'user_id';
                $not_found_message = __('Api.page_not_found');
                $cannot_report_message = __('Api.cannot_report_your_own_page');
                break;

            case 'group':
                $module = Group::find($module_id);
                $user_column = 'user_id';
                $not_found_message = __('Api.group_not_found');
                $cannot_report_message = __('Api.cannot_report_your_own_group');
                break;

            case 'job':
                $module = Job::find($module_id);
                $user_column = 'user_id';
                $not_found_message = __('Api.job_not_found');
                $cannot_report_message = __('Api.cannot_report_your_own_job');
                break;

            // case 'space':
            //     $module = Space::find($module_id);
            //     $user_column = 'user_id';
            //     $not_found_message = __('Api.space_not_found');
            //     $cannot_report_message = __('Api.cannot_report_your_own_space');
            //     break;

            default:
                return response()->json([
                    'status' => 400,
                    'message' => __('Api.module_not_found'),
                ], 200);
        }

        // Check if the module exists
        if (!$module) {
            return response()->json([
                'status' => 400,
                'message' => $not_found_message,
            ], 200);
        }

        // Prevent users from reporting their own content
        if ($module->{$user_column} == $user->id) {
            return response()->json([
                'status' => 400,
                'message' => $cannot_report_message,
            ], 200);
        }

        // Save the report to the database
        ReportModule::create([
            'module_name' => $module_name,
            'module_id' => $module_id,
            'reason' => $reason,
            'user_id' => $user->id,
            'status' => ReportModule::STATUS_PENDING,
        ]);

        // Return success message
        return response()->json([
            'status' => 200,
            'message' => __('Api.reported_successfully'),
        ], 200);
    }

    /**
     * Display user detail page
     */
    public function userDetail(Request $request, $username)
    {
        // Find user by username
        $user = User::where('username', $username)->first();

        // If user not found, return 404
        if (!$user) {
            abort(404, 'User not found');
        }

        $loggedInUser = auth()->user();
        $loggedInUserId = $loggedInUser ? $loggedInUser->id : null;

        // Check if the user is blocked
        if ($loggedInUserId && $user->isBlockedBy($loggedInUserId)) {
            abort(403, 'You are not authorized to view this profile.');
        }

        // Get user statistics
        $friendsCount = \App\Models\Friend::where(function($query) use ($user) {
            $query->where('friend_one', $user->id)
                  ->orWhere('friend_two', $user->id);
        })->where('status', 1)->count();

        $followersCount = $user->followers()->count();
        $followingCount = \App\Models\Follower::where('follower_id', $user->id)->count();

        // Get mutual friends count if logged in
        $mutualFriendsCount = 0;
        if ($loggedInUserId && $loggedInUserId !== $user->id) {
            $mutualFriendsCount = \App\Models\Friend::getMutualFriendsCount($user->id, $loggedInUserId);
        }

        // Check relationships
        $isFollowing = false;
        $isFriend = false;
        $friendRequestStatus = null;

        if ($loggedInUserId && $loggedInUserId !== $user->id) {
            $isFollowing = \App\Models\Follower::isFollowing($loggedInUserId, $user->id);
            $isFriend = \App\Models\Friend::isFriend($loggedInUserId, $user->id);
            $friendRequestStatus = \App\Models\Friend::pendingRequestStatus($loggedInUserId, $user->id);
        }

        // Get user's recent posts
        $posts = \App\Models\Post::where('user_id', $user->id)
            ->where('status', 1)
            ->orderBy('created_at', 'desc')
            ->limit(10)
            ->get();

        // Get user's friends
        $friends = User::whereIn('id', function ($query) use ($user) {
            $query->select('friend_two')
                ->from('friends')
                ->where('friend_one', $user->id)
                ->where('status', 1);
        })
            ->orWhereIn('id', function ($query) use ($user) {
                $query->select('friend_one')
                    ->from('friends')
                    ->where('friend_two', $user->id)
                    ->where('status', 1);
            })
            ->limit(6)
            ->get();

        // Get user's photos (posts with media/images)
        $photos = \App\Models\Post::where('user_id', $user->id)
            ->where('status', 1)
            ->whereHas('media', function($query) {
                $query->where('image_or_video', 1); // Only images
            })
            ->with(['media' => function($query) {
                $query->where('image_or_video', 1)->orderBy('created_at', 'desc');
            }])
            ->orderBy('created_at', 'desc')
            ->limit(50)
            ->get();

        return view('front_end.pages.profile.user_detail', compact(
            'user',
            'friendsCount',
            'followersCount',
            'followingCount',
            'mutualFriendsCount',
            'isFollowing',
            'isFriend',
            'friendRequestStatus',
            'posts',
            'friends',
            'photos',
            'loggedInUserId'
        ));
    }

    /**
     * Display user detail page by numeric ID
     */
    public function userDetailById(Request $request, $id)
    {
        $user = User::find($id);

        if (!$user) {
            abort(404, 'User not found');
        }

        return $this->userDetail($request, $user->username);
    }

    /**
     * Display own profile page
     */
    public function myProfile(Request $request)
    {
        $user = auth()->user();

        if (!$user) {
            return redirect()->route('login');
        }

        // Redirect to user detail page with their username
        return redirect()->route('user.detail', ['username' => $user->username]);
    }
}
