<?php

namespace App\Http\Controllers;

use App\Models\User;
use App\Models\ReferralCommission;
use App\Models\ReferralPayout;
use App\Models\ReferralCommissionPayout;
use App\Http\Controllers\Traits\EmailTrait;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;

class ReferralController extends Controller
{
    use EmailTrait;
    /**
     * Referral Signup
     */
    public function signup(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required|string|max:255',
            'email' => 'required|string|email|max:255|unique:users',
            'mobile_number' => 'required|string|max:20',
            'password' => 'required|string|min:8|confirmed',
        ]);

        if ($validator->fails()) {
            return $this->errorWithData($validator->errors(), 'Validation failed', 422);
        }

        try {
            $referralUser = User::create([
                'name' => $request->name,
                'email' => $request->email,
                'mobile_number' => $request->mobile_number,
                'password' => Hash::make($request->password),
                'user_type' => 4, // Referral partner
                'status' => 'pending',
                'active_status' => 0,
                'is_enable_login' => 0,
                'created_by' => 'referral_signup',
                'del' => '0',
            ]);

            // Send instant emails
            // $userData = [
            //     'name' => $referralUser->name,
            //     'email' => $referralUser->email,
            //     'mobile_number' => $referralUser->mobile_number,
            //     'applied_at' => $referralUser->created_at,
            // ];

            // // Send email to referral user
            // $this->sendReferralSignupUserEmail($userData);

            // // Send email to admin
            // $this->sendReferralSignupAdminEmail($userData);

            // Send notification to admin about new referral signup
            $this->save_notifications(
                'New Referral Signup',
                'A new referral partner has signed up: ' . $referralUser->name . ' (' . $referralUser->email . ')',
                config('constants.employee_types.customer'),
                $referralUser->id,
                config('constants.employee_types.admin'),
                config('constants.superadmin'),
                'referral_signup'
            );

            $data = [
                'user_id' => $referralUser->id,
                'status' => $referralUser->status
            ];
            return $this->success($data, 'Referral signup successful. Your application is pending approval.');

        } catch (\Exception $e) {
            return $this->error($e->getMessage(), 500);
        }
    }

    public function dashboard(Request $request)
    {
        try {
            /** @var User $user */
            $user = Auth::user();
            
            if (!$user->isReferralUser()) {
                return $this->error('Unauthorized access', 403);
            }
            $leads = $user->referralLeads()->count();
            $convertedLeads = $user->referralLeads()->converted()->count();
            $pendingCommissions = $user->referralCommissions()->pending()->sum('commission_amount');
            $approvedCommissions = $user->referralCommissions()->approved()->sum('commission_amount');
            $totalEarnings = $user->referralCommissions()->whereIn('status', ['approved', 'paid'])->sum('commission_amount');
            $pendingPayouts = $user->referralPayouts()->requested()->sum('amount');
            $paidPayouts = $user->referralPayouts()->paid()->sum('amount');

            // Build referral commissions table with detailed information
            $referralCommissionsTable = $user->referralCommissions()
                ->with(['customer', 'commissionPayouts.payout'])
                ->latest()
                ->get()
                ->map(function ($commission) {
                    // Check if commission is included in any payout
                    $isInPayout = $commission->isIncludedInPayout();
                    $payoutStatus = 'Available for Payout';
                    $payoutId = null;
                    
                    if ($isInPayout) {
                        $commissionPayout = $commission->commissionPayouts()
                            ->whereIn('status', ['requested', 'completed'])
                            ->with('payout')
                            ->first();
                        
                        if ($commissionPayout) {
                            $payoutId = $commissionPayout->payout_id;
                            switch ($commissionPayout->status) {
                                case 'requested':
                                    $payoutStatus = 'In Payout Request';
                                    break;
                                case 'completed':
                                    $payoutStatus = 'Paid Out';
                                    break;
                            }
                        }
                    }

                    return [
                        'commission_id' => $commission->id,
                        'customer_name' => $commission->customer->name ?? 'N/A',
                        'customer_email' => $commission->customer->email ?? 'N/A',
                        'order_date' => $commission->created_at,
                        'order_amount' => number_format($commission->plan_price, 2),
                        'commission_rate' => $commission->commission_rate . '%',
                        'your_payout' => number_format($commission->commission_amount, 2),
                        'status' => ucfirst($commission->status),
                        'payout_status' => $payoutStatus,
                        'action' => $commission->status === 'approved' && !$isInPayout ? 'Available for Payout' : 
                                   ($commission->status === 'paid' ? 'Paid' : 'Pending Approval'),
                        'order_id' => $commission->order_id,
                        'payout_id' => $payoutId,
                    ];
                });

            // Recent payout requests
            $recentPayouts = $user->referralPayouts()
                ->with(['commissionPayouts.commission.customer'])
                ->latest()
                ->limit(5)
                ->get()
                ->map(function ($payout) {
                    return [
                        'id' => $payout->id,
                        'amount' => number_format($payout->amount, 2),
                        'status' => ucfirst($payout->status),
                        'payment_method' => $payout->payment_method,
                        'requested_at' => $payout->requested_at,
                        'processed_at' => $payout->processed_at ? $payout->processed_at : null,
                        'attachment_url' => $payout->attachment_url,
                        'notes' => $payout->notes,
                        'commission_count' => $payout->getCommissionCount(),
                        'commission_details' => $payout->commissionPayouts->map(function ($cp) {
                            return [
                                'commission_id' => $cp->commission_id,
                                'amount' => number_format($cp->commission_amount, 2),
                                'customer_name' => $cp->commission->customer->name ?? 'N/A',
                                'order_id' => $cp->commission->order_id,
                            ];
                        }),
                    ];
                });

            $data = [
                'stats' => [
                    'total_leads' => $leads,
                    'clicks' => $user->referral_clicks,
                    'converted_leads' => $convertedLeads,
                    'conversion_rate' => $leads > 0 ? round(($convertedLeads / $leads) * 100, 2) : 0,
                    'pending_commissions' => $pendingCommissions,
                    'approved_commissions' => $approvedCommissions,
                    'total_earnings' => $totalEarnings,
                    'pending_payouts' => $pendingPayouts,
                    'paid_payouts' => $paidPayouts,
                ],
                'referral_commissions_table' => $referralCommissionsTable,
                'recent_payouts' => $recentPayouts,
                'referral_code' => $user->referral_code,
                'referral_link' => env('FRONTEND_URL').'/signup?ref=' . $user->referral_code,
            ];
            $message = $user->status == 'active' ? 'Dashboard loaded successfully' : 'Your application is pending approval. Please wait for admin approval.';
            return $this->success($data, $message);

        } catch (\Exception $e) {
            return $this->error($e->getMessage(), 500);
        }
    }

    /**
     * Referral Payout Request with Commission Selection
     */
    public function requestPayout(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'commission_ids' => 'required|array|min:1',
            'commission_ids.*' => 'required|integer|exists:referral_commissions,id',
            'payment_method' => 'required|string',
            'payment_details' => 'required|array',
            'notes' => 'nullable|string|max:500',
        ]);

        if ($validator->fails()) {
            return $this->errorWithData($validator->errors(), 'Validation failed', 422);
        }

        try {
            $user = Auth::user();
            
            if (!$user->isReferralUser()) {
                return $this->error('Unauthorized access', 403);
            }

            // Validate that all commissions belong to the user and are available
            $commissions = ReferralCommission::whereIn('id', $request->commission_ids)
                ->where('referral_user_id', $user->id)
                ->where('status', 'approved')
                ->get();

            if ($commissions->count() !== count($request->commission_ids)) {
                return $this->error('One or more commissions are invalid or not available for payout', 400);
            }

            // Check if any commission is already included in another payout
            $alreadyIncluded = $commissions->filter(function ($commission) {
                return $commission->isIncludedInPayout();
            });

            if ($alreadyIncluded->count() > 0) {
                return $this->error('One or more commissions are already included in another payout request', 400);
            }

            // Calculate total amount
            $totalAmount = $commissions->sum('commission_amount');

            DB::beginTransaction();

            // Create payout request
            $payout = ReferralPayout::create([
                'referral_user_id' => $user->id,
                'amount' => $totalAmount,
                'status' => 'requested',
                'payment_method' => $request->payment_method,
                'payment_details' => $request->payment_details,
                'requested_at' => now(),
                'notes' => $request->notes,
            ]);

            // Link commissions to payout
            foreach ($commissions as $commission) {
                \App\Models\ReferralCommissionPayout::create([
                    'commission_id' => $commission->id,
                    'payout_id' => $payout->id,
                    'commission_amount' => $commission->commission_amount,
                    'status' => 'requested',
                    'included_at' => now(),
                ]);
            }

            // Send notification to admin about payout request
            $this->save_notifications(
                'New Payout Request',
                'Referral partner ' . $user->name . ' has requested a payout of $' . number_format($totalAmount, 2) . ' for ' . $commissions->count() . ' commission(s)',
                config('constants.employee_types.customer'),
                $user->id,
                config('constants.employee_types.admin'),
                config('constants.superadmin'),
                'referral_payout_requested'
            );

            DB::commit();

            return $this->success([
                'payout' => $payout->load('commissions'),
                'commission_count' => $commissions->count(),
                'total_amount' => $totalAmount
            ], 'Payout request submitted successfully');

        } catch (\Exception $e) {
            DB::rollBack();
            return $this->error($e->getMessage(), 500);
        }
    }

    /**
     * Get the real client IP address, handling proxies and Cloudflare
     */
    private function getRealIp(Request $request)
    {
        $headers = [
            'HTTP_X_FORWARDED_FOR',
            'HTTP_X_REAL_IP',
            'HTTP_X_FORWARDED',
            'HTTP_CF_CONNECTING_IP', // Cloudflare
            'HTTP_X_CLUSTER_CLIENT_IP', // Load balancers
        ];

        foreach ($headers as $header) {
            if ($request->server($header)) {
                $ip = trim($request->server($header));
                // Take the first IP if multiple (comma-separated)
                $ip = explode(',', $ip)[0];
                $ip = trim($ip);

                // Validate IP and exclude private/reserved ranges
                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
                    return $ip;
                }
            }
        }

        // Fallback to Laravel's default method
        return $request->ip();
    }

    /**
     * Track referral link clicks with IP uniqueness
     */
    public function trackClick(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'referral_code' => 'required|string|exists:users,referral_code',
        ]);

        if ($validator->fails()) {
            return $this->errorWithData($validator->errors(), 'Validation failed', 422);
        }

        try {
            $referralCode = $request->referral_code;
            $ipAddress = $this->getRealIp($request);
            $userAgent = $request->header('User-Agent');

            $existingClick = \App\Models\ReferralClick::where('referral_code', $referralCode)
                ->where('ip_address', $ipAddress)
                ->where('user_agent', $userAgent)
                ->first();

            if ($existingClick) {
                // IP has already clicked, don't record again
                return $this->success(['recorded' => true], 'Click already recorded for this IP');
            }

            // Record the new click
            \App\Models\ReferralClick::create([
                'referral_code' => $referralCode,
                'ip_address' => $ipAddress,
                'user_agent' => $userAgent,
                'clicked_at' => now(),
            ]);
            $user = User::where('referral_code', $referralCode)->first();
            $user->increment('referral_clicks');
            $user->save();
            return $this->success(['recorded' => true], 'Click recorded successfully');

        } catch (\Exception $e) {
            return $this->error($e->getMessage(), 500);
        }
    }
}