<?php

namespace App\Http\Controllers\API\DeliveryBoy;

use App\Http\Controllers\Controller;
use App\Models\Order;
use App\Models\Delivery;
use App\Models\DeliveryAssignment;
use Illuminate\Http\Request;

class DeliveryBoyController extends Controller
{
    public function availableOrders(Request $request)
    {
        try {
            $userId = $request->user()->id;
            \Log::info('Available orders request', ['user_id' => $userId]);
            
            $deliveryBoy = \App\Models\DeliveryBoy::where('user_id', $userId)->first();
            
            \Log::info('Delivery boy found', ['delivery_boy' => $deliveryBoy]);
            
            if (!$deliveryBoy) {
                \Log::warning('No delivery boy found for user', ['user_id' => $userId]);
                return response()->json(['data' => []]);
            }
            
            // Get pending notifications for this delivery boy
            $notifications = \DB::table('delivery_notifications')
                ->join('orders', 'delivery_notifications.order_id', '=', 'orders.id')
                ->leftJoin('restaurants', 'orders.restaurant_id', '=', 'restaurants.id')
                ->leftJoin('users', 'orders.user_id', '=', 'users.id')
                ->where('delivery_notifications.delivery_boy_id', $deliveryBoy->id)
                ->where('delivery_notifications.status', 'pending')
                ->where('orders.status', 'ready')
                ->select(
                    'orders.id',
                    'orders.order_number',
                    'orders.delivery_address',
                    'orders.delivery_latitude',
                    'orders.delivery_longitude',
                    'orders.delivery_phone',
                    'orders.total',
                    'orders.delivery_fee',
                    'orders.payment_method',
                    'orders.created_at',
                    'restaurants.name as restaurant_name',
                    'restaurants.address as restaurant_address',
                    'restaurants.latitude as restaurant_latitude',
                    'restaurants.longitude as restaurant_longitude',
                    'users.name as user_name',
                    'users.phone as user_phone',
                    'delivery_notifications.distance'
                )
                ->orderBy('orders.created_at', 'desc')
                ->get()
                ->map(function ($order) {
                    return [
                        'id' => $order->id,
                        'order_number' => $order->order_number,
                        'restaurant' => [
                            'name' => $order->restaurant_name ?? 'N/A',
                            'address' => $order->restaurant_address ?? 'N/A',
                            'latitude' => $order->restaurant_latitude,
                            'longitude' => $order->restaurant_longitude,
                        ],
                        'user' => [
                            'name' => $order->user_name ?? 'N/A',
                            'phone' => $order->user_phone ?? $order->delivery_phone ?? 'N/A',
                        ],
                        'delivery_address' => $order->delivery_address,
                        'delivery_latitude' => $order->delivery_latitude,
                        'delivery_longitude' => $order->delivery_longitude,
                        'delivery_phone' => $order->delivery_phone,
                        'total_amount' => $order->total,
                        'delivery_fee' => $order->delivery_fee,
                        'distance' => $order->distance ? round($order->distance, 1) : null,
                        'distance_km' => $order->distance ? round($order->distance, 1) : null,
                        'payment_method' => $order->payment_method,
                        'created_at' => $order->created_at,
                    ];
                });

            return response()->json(['data' => $notifications]);
        } catch (\Exception $e) {
            \Log::error('Available orders error: ' . $e->getMessage());
            return response()->json(['data' => [], 'error' => $e->getMessage()], 500);
        }
    }

    public function acceptOrder(Request $request, $orderId)
    {
        $order = Order::with('restaurant')->findOrFail($orderId);
        
        if ($order->status !== 'ready') {
            return response()->json(['message' => 'Order is not ready for pickup'], 400);
        }

        if ($order->delivery) {
            return response()->json(['message' => 'Order already assigned'], 400);
        }

        $deliveryBoy = \App\Models\DeliveryBoy::where('user_id', $request->user()->id)->first();
        
        if (!$deliveryBoy) {
            return response()->json(['message' => 'Delivery boy not found'], 404);
        }

        // Update notification status to accepted
        \DB::table('delivery_notifications')
            ->where('order_id', $orderId)
            ->where('delivery_boy_id', $deliveryBoy->id)
            ->update(['status' => 'accepted', 'updated_at' => now()]);
        
        // Mark other notifications as expired
        \DB::table('delivery_notifications')
            ->where('order_id', $orderId)
            ->where('delivery_boy_id', '!=', $deliveryBoy->id)
            ->update(['status' => 'expired', 'updated_at' => now()]);

        Delivery::create([
            'order_id' => $order->id,
            'delivery_boy_id' => $deliveryBoy->id,
            'status' => 'assigned',
            'assigned_at' => now(),
            'pickup_latitude' => $order->restaurant->latitude ?? 0,
            'pickup_longitude' => $order->restaurant->longitude ?? 0,
            'pickup_address' => $order->restaurant->address ?? '',
            'delivery_latitude' => $order->delivery_latitude ?? 0,
            'delivery_longitude' => $order->delivery_longitude ?? 0,
            'delivery_address' => $order->delivery_address ?? '',
            'distance_km' => $order->distance_km ?? 0,
            'delivery_fee' => $order->delivery_fee ?? 0,
        ]);

        $order->update(['status' => 'picked_up']);

        return response()->json([
            'message' => 'Order accepted successfully',
            'order' => $order->load('delivery', 'restaurant', 'items')
        ]);
    }

    public function rejectOrder(Request $request, $orderId)
    {
        $deliveryBoy = \App\Models\DeliveryBoy::where('user_id', $request->user()->id)->first();
        
        if (!$deliveryBoy) {
            return response()->json(['message' => 'Delivery boy not found'], 404);
        }

        // Update notification status to rejected
        \DB::table('delivery_notifications')
            ->where('order_id', $orderId)
            ->where('delivery_boy_id', $deliveryBoy->id)
            ->update(['status' => 'rejected', 'updated_at' => now()]);
        
        return response()->json(['message' => 'Order rejected']);
    }

    public function myOrders(Request $request)
    {
        $status = $request->query('status', 'active');
        
        $deliveryBoy = \App\Models\DeliveryBoy::where('user_id', $request->user()->id)->first();
        
        if (!$deliveryBoy) {
            return response()->json(['data' => []]);
        }
        
        $query = Delivery::with(['order.restaurant', 'order.items', 'order.user'])
            ->where('delivery_boy_id', $deliveryBoy->id);

        if ($status === 'active') {
            $query->whereIn('status', ['assigned', 'picked_up', 'on_the_way']);
        } elseif ($status === 'delivered') {
            $query->whereIn('status', ['delivered', 'cancelled']);
        } else {
            $query->where('status', $status);
        }

        $deliveries = $query->latest()->get()->map(function ($delivery) {
            $order = $delivery->order;
            return [
                'id' => $delivery->id,
                'order_id' => $delivery->order_id,
                'order_number' => $order->order_number,
                'status' => $delivery->status,
                'restaurant' => [
                    'name' => $order->restaurant->name ?? 'N/A',
                    'address' => $order->restaurant->address ?? 'N/A',
                    'latitude' => $order->restaurant->latitude,
                    'longitude' => $order->restaurant->longitude,
                ],
                'user' => [
                    'name' => $order->user->name ?? 'N/A',
                    'phone' => $order->user->phone ?? $order->delivery_phone ?? 'N/A',
                ],
                'delivery_address' => $order->delivery_address,
                'delivery_latitude' => $order->delivery_latitude,
                'delivery_longitude' => $order->delivery_longitude,
                'delivery_phone' => $order->delivery_phone,
                'total' => $order->total,
                'delivery_fee' => $order->delivery_fee,
                'payment_method' => $order->payment_method,
                'items_count' => $order->items->count(),
                'assigned_at' => $delivery->assigned_at,
                'picked_up_at' => $delivery->picked_up_at,
                'delivered_at' => $delivery->delivered_at,
                'created_at' => $order->created_at,
                'ready_at' => $order->ready_at,
            ];
        });

        return response()->json(['data' => $deliveries]);
    }

    public function toggleStatus(Request $request)
    {
        $request->validate([
            'is_available' => 'required|boolean',
        ]);

        $deliveryBoy = \App\Models\DeliveryBoy::where('user_id', $request->user()->id)->first();
        
        if (!$deliveryBoy) {
            return response()->json(['message' => 'Delivery boy not found'], 404);
        }

        $deliveryBoy->update([
            'is_available' => $request->is_available,
            'status' => $request->is_available ? 'online' : 'offline',
        ]);
        
        return response()->json(['message' => 'Status updated', 'is_available' => $deliveryBoy->is_available]);
    }

    public function updateLocation(Request $request)
    {
        $request->validate([
            'latitude' => 'required|numeric',
            'longitude' => 'required|numeric',
        ]);

        $deliveryBoy = \App\Models\DeliveryBoy::where('user_id', $request->user()->id)->first();
        
        if (!$deliveryBoy) {
            return response()->json(['message' => 'Delivery boy not found'], 404);
        }

        $deliveryBoy->update([
            'latitude' => $request->latitude,
            'longitude' => $request->longitude,
        ]);

        return response()->json(['message' => 'Location updated']);
    }

    public function getHeatmapData(Request $request)
    {
        $deliveryBoy = \App\Models\DeliveryBoy::where('user_id', $request->user()->id)->first();
        
        if (!$deliveryBoy) {
            return response()->json(['message' => 'Delivery boy not found'], 404);
        }

        $heatmapPoints = [];
        $restaurantMarkers = [];
        
        // Get restaurant locations with accepted order count
        $restaurants = \DB::table('restaurants')
            ->leftJoin('orders', function($join) {
                $join->on('restaurants.id', '=', 'orders.restaurant_id')
                     ->whereIn('orders.status', ['accepted', 'preparing', 'ready', 'picked_up', 'delivered']);
            })
            ->where('restaurants.latitude', '!=', null)
            ->where('restaurants.longitude', '!=', null)
            ->select(
                'restaurants.id',
                'restaurants.name',
                'restaurants.latitude as lat',
                'restaurants.longitude as lng',
                \DB::raw('COUNT(orders.id) as order_count')
            )
            ->groupBy('restaurants.id', 'restaurants.name', 'restaurants.latitude', 'restaurants.longitude')
            ->get();
        
        foreach ($restaurants as $restaurant) {
            $orderCount = (int) $restaurant->order_count;
            
            // Add to heatmap
            $heatmapPoints[] = [
                'lat' => (float) $restaurant->lat,
                'lng' => (float) $restaurant->lng,
                'weight' => max(1, $orderCount)
            ];
            
            // Add restaurant marker with order count
            $restaurantMarkers[] = [
                'id' => $restaurant->id,
                'name' => $restaurant->name,
                'lat' => (float) $restaurant->lat,
                'lng' => (float) $restaurant->lng,
                'order_count' => $orderCount
            ];
        }
        
        // Get delivery locations from orders
        $deliveryLocations = \DB::table('orders')
            ->where('delivery_latitude', '!=', null)
            ->where('delivery_longitude', '!=', null)
            ->select(
                'delivery_latitude as lat',
                'delivery_longitude as lng',
                \DB::raw('COUNT(*) as weight')
            )
            ->groupBy('delivery_latitude', 'delivery_longitude')
            ->get();
        
        foreach ($deliveryLocations as $location) {
            $heatmapPoints[] = [
                'lat' => (float) $location->lat,
                'lng' => (float) $location->lng,
                'weight' => (int) $location->weight
            ];
        }

        return response()->json([
            'heatmap' => $heatmapPoints,
            'restaurants' => $restaurantMarkers
        ]);
    }

    public function updateDeliveryStatus(Request $request, $deliveryId)
    {
        $request->validate([
            'status' => 'required|in:picked_up,on_the_way,delivered',
        ]);

        $deliveryBoy = \App\Models\DeliveryBoy::where('user_id', $request->user()->id)->first();
        
        if (!$deliveryBoy) {
            return response()->json(['message' => 'Delivery boy not found'], 404);
        }

        $delivery = Delivery::where('id', $deliveryId)
            ->where('delivery_boy_id', $deliveryBoy->id)
            ->firstOrFail();

        $delivery->update(['status' => $request->status]);

        if ($request->status === 'picked_up') {
            $delivery->update(['picked_up_at' => now()]);
            $delivery->order->update(['status' => 'picked_up']);
        } elseif ($request->status === 'delivered') {
            $delivery->update(['delivered_at' => now()]);
            $delivery->order->update(['status' => 'delivered', 'delivered_at' => now()]);
            
            // Update delivery boy stats
            $deliveryBoy->increment('total_deliveries');
            $deliveryBoy->increment('successful_deliveries');
            
            // Calculate commission - commission_rate is platform commission (e.g., 10%)
            // Delivery boy gets the remaining amount (e.g., 90%)
            $deliveryFee = $delivery->order->delivery_fee ?? 0;
            $platformCommissionRate = $deliveryBoy->commission_rate ?? 10; // Default 10% platform commission
            $deliveryBoyRate = 100 - $platformCommissionRate; // Delivery boy gets remaining %
            $deliveryBoyEarning = ($deliveryFee * $deliveryBoyRate) / 100;
            
            // If cash on delivery, add to wallet balance
            if ($delivery->order->payment_method === 'cash') {
                $deliveryBoy->increment('wallet_balance', $deliveryBoyEarning);
            }
            
            // Record earning
            \DB::table('delivery_boy_earnings')->insert([
                'delivery_boy_id' => $deliveryBoy->id,
                'order_id' => $delivery->order_id,
                'delivery_id' => $delivery->id,
                'earning_type' => 'commission',
                'amount' => $deliveryBoyEarning,
                'commission_rate' => $deliveryBoyRate,
                'description' => 'Delivery earning for order #' . $delivery->order->order_number . ' (Platform commission: ' . $platformCommissionRate . '%)',
                'status' => $delivery->order->payment_method === 'cash' ? 'paid' : 'pending',
                'created_at' => now(),
                'updated_at' => now(),
            ]);
        }

        return response()->json([
            'message' => 'Status updated successfully',
            'delivery' => $delivery->load('order')
        ]);
    }

    public function earnings(Request $request)
    {
        $deliveryBoy = \App\Models\DeliveryBoy::where('user_id', $request->user()->id)->first();
        
        \Log::info('Earnings request for user:', ['user_id' => $request->user()->id, 'delivery_boy' => $deliveryBoy]);
        
        if (!$deliveryBoy) {
            \Log::warning('Delivery boy not found for user:', ['user_id' => $request->user()->id]);
            return response()->json([
                'today' => 0,
                'week' => 0,
                'month' => 0,
                'total' => 0,
                'deliveries' => 0,
                'month_deliveries' => 0,
            ]);
        }
        
        $deliveryBoyId = $deliveryBoy->id;
        
        // Check if there are any earnings
        $earningsCount = \DB::table('delivery_boy_earnings')
            ->where('delivery_boy_id', $deliveryBoyId)
            ->count();
        
        \Log::info('Earnings count:', ['delivery_boy_id' => $deliveryBoyId, 'count' => $earningsCount]);
        
        $period = $request->query('period', 'all');
        $startDate = $request->query('start_date');
        $endDate = $request->query('end_date');
        
        // Use delivery_boy_earnings table for commission calculation
        $query = \DB::table('delivery_boy_earnings')
            ->where('delivery_boy_id', $deliveryBoyId)
            ->where('status', '!=', 'cancelled');
        
        if ($startDate && $endDate) {
            $query->whereBetween('created_at', [$startDate . ' 00:00:00', $endDate . ' 23:59:59']);
            $total = $query->sum('amount');
            $deliveries = Delivery::where('delivery_boy_id', $deliveryBoyId)
                ->where('status', 'delivered')
                ->whereBetween('delivered_at', [$startDate . ' 00:00:00', $endDate . ' 23:59:59'])
                ->count();
        } elseif ($period === 'today') {
            $total = (clone $query)->whereDate('created_at', today())->sum('amount');
            $deliveries = Delivery::where('delivery_boy_id', $deliveryBoyId)
                ->where('status', 'delivered')
                ->whereDate('delivered_at', today())
                ->count();
        } elseif ($period === 'week') {
            $total = (clone $query)->whereBetween('created_at', [now()->startOfWeek(), now()->endOfWeek()])->sum('amount');
            $deliveries = Delivery::where('delivery_boy_id', $deliveryBoyId)
                ->where('status', 'delivered')
                ->whereBetween('delivered_at', [now()->startOfWeek(), now()->endOfWeek()])
                ->count();
        } elseif ($period === 'month') {
            $total = (clone $query)->whereMonth('created_at', now()->month)
                ->whereYear('created_at', now()->year)
                ->sum('amount');
            $deliveries = Delivery::where('delivery_boy_id', $deliveryBoyId)
                ->where('status', 'delivered')
                ->whereMonth('delivered_at', now()->month)
                ->whereYear('delivered_at', now()->year)
                ->count();
        } else {
            $total = $query->sum('amount');
            $deliveries = Delivery::where('delivery_boy_id', $deliveryBoyId)
                ->where('status', 'delivered')
                ->count();
        }

        $today = \DB::table('delivery_boy_earnings')
            ->where('delivery_boy_id', $deliveryBoyId)
            ->where('status', '!=', 'cancelled')
            ->whereDate('created_at', today())
            ->sum('amount');

        $week = \DB::table('delivery_boy_earnings')
            ->where('delivery_boy_id', $deliveryBoyId)
            ->where('status', '!=', 'cancelled')
            ->whereBetween('created_at', [now()->startOfWeek(), now()->endOfWeek()])
            ->sum('amount');

        $month = \DB::table('delivery_boy_earnings')
            ->where('delivery_boy_id', $deliveryBoyId)
            ->where('status', '!=', 'cancelled')
            ->whereMonth('created_at', now()->month)
            ->whereYear('created_at', now()->year)
            ->sum('amount');

        $monthDeliveries = Delivery::where('delivery_boy_id', $deliveryBoyId)
            ->where('status', 'delivered')
            ->whereMonth('delivered_at', now()->month)
            ->whereYear('delivered_at', now()->year)
            ->count();

        return response()->json([
            'today' => round($today ?? 0, 2),
            'week' => round($week ?? 0, 2),
            'month' => round($month ?? 0, 2),
            'total' => round($total ?? 0, 2),
            'deliveries' => $deliveries,
            'month_deliveries' => $monthDeliveries,
            'wallet_balance' => round($deliveryBoy->wallet_balance ?? 0, 2),
        ]);
    }

    public function earningsDetails(Request $request)
    {
        $deliveryBoy = \App\Models\DeliveryBoy::where('user_id', $request->user()->id)->first();
        
        if (!$deliveryBoy) {
            return response()->json(['data' => [], 'stats' => []]);
        }

        $status = $request->query('status');
        $dateFrom = $request->query('date_from');
        $dateTo = $request->query('date_to');
        $type = $request->query('type');

        $query = \DB::table('delivery_boy_earnings')
            ->leftJoin('orders', 'delivery_boy_earnings.order_id', '=', 'orders.id')
            ->where('delivery_boy_earnings.delivery_boy_id', $deliveryBoy->id)
            ->select(
                'delivery_boy_earnings.*',
                'orders.order_number'
            );

        if ($status) {
            $query->where('delivery_boy_earnings.status', $status);
        }

        if ($type) {
            $query->where('delivery_boy_earnings.earning_type', $type);
        }

        if ($dateFrom) {
            $query->whereDate('delivery_boy_earnings.created_at', '>=', $dateFrom);
        }

        if ($dateTo) {
            $query->whereDate('delivery_boy_earnings.created_at', '<=', $dateTo);
        }

        $earnings = $query->orderBy('delivery_boy_earnings.created_at', 'desc')->get();

        $stats = [
            'total' => $earnings->where('status', '!=', 'cancelled')->sum('amount'),
            'pending' => $earnings->where('status', 'pending')->sum('amount'),
            'paid' => $earnings->where('status', 'paid')->sum('amount'),
            'count' => $earnings->where('status', '!=', 'cancelled')->count(),
        ];

        return response()->json([
            'data' => $earnings,
            'stats' => $stats,
        ]);
    }
    
    public function markNotificationViewed(Request $request, $notificationId)
    {
        $deliveryBoy = \App\Models\DeliveryBoy::where('user_id', $request->user()->id)->first();
        
        if (!$deliveryBoy) {
            return response()->json(['message' => 'Delivery boy not found'], 404);
        }

        \DB::table('delivery_notifications')
            ->where('id', $notificationId)
            ->where('delivery_boy_id', $deliveryBoy->id)
            ->update(['status' => 'viewed', 'updated_at' => now()]);
        
        return response()->json(['message' => 'Notification marked as viewed']);
    }
    
    public function notifications(Request $request)
    {
        $deliveryBoy = \App\Models\DeliveryBoy::where('user_id', $request->user()->id)->first();
        
        if (!$deliveryBoy) {
            return response()->json(['data' => []]);
        }
        
        $notifications = \DB::table('delivery_notifications')
            ->join('orders', 'delivery_notifications.order_id', '=', 'orders.id')
            ->leftJoin('restaurants', 'orders.restaurant_id', '=', 'restaurants.id')
            ->where('delivery_notifications.delivery_boy_id', $deliveryBoy->id)
            ->select(
                'delivery_notifications.*',
                'orders.order_number',
                'orders.delivery_fee',
                'restaurants.name as restaurant_name'
            )
            ->orderBy('delivery_notifications.created_at', 'desc')
            ->limit(50)
            ->get();
        
        return response()->json(['data' => $notifications]);
    }
}
