<?php

namespace App\Http\Controllers\Api\V1\Delivery;

use App\Http\Controllers\Controller;
use App\Http\Resources\OrderResource;
use App\Models\DeliveryAgent;
use App\Models\DeliveryAssignment;
use App\Models\DeliveryEarning;
use App\Models\DeliveryTracking;
use App\Models\Order;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;

class DeliveryController extends Controller
{
    public function profile(): JsonResponse
    {
        $user = Auth::guard('sanctum')->user();
        $agent = $user->deliveryAgent;

        return response()->json([
            'success' => true,
            'data' => [
                'user' => [
                    'id' => $user->id,
                    'name' => $user->name,
                    'email' => $user->email,
                    'phone' => $user->phone,
                ],
                'agent' => [
                    'agent_code' => $agent->agent_code,
                    'vehicle_type' => $agent->vehicle_type,
                    'vehicle_number' => $agent->vehicle_number,
                    'address' => $agent->address,
                    'city' => $agent->city,
                    'state' => $agent->state,
                    'pincode' => $agent->pincode,
                    'status' => $agent->status,
                    'availability_status' => $agent->availability_status,
                    'is_online' => $agent->is_online,
                    'total_deliveries' => $agent->total_deliveries,
                    'total_earnings' => $agent->total_earnings,
                    'rating' => $agent->rating,
                    'rating_count' => $agent->rating_count,
                ],
                'wallet' => $agent->wallet ? [
                    'balance' => $agent->wallet->balance,
                    'pending_balance' => $agent->wallet->pending_balance,
                    'total_withdrawn' => $agent->wallet->total_withdrawn,
                ] : null,
            ],
        ]);
    }

    public function updateStatus(Request $request): JsonResponse
    {
        $request->validate([
            'availability_status' => 'required|in:online,offline,busy',
        ]);

        $agent = Auth::guard('sanctum')->user()->deliveryAgent;
        $agent->update([
            'availability_status' => $request->availability_status,
            'is_online' => $request->availability_status !== 'offline',
            'last_active_at' => now(),
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Status updated successfully',
            'data' => [
                'availability_status' => $agent->availability_status,
                'is_online' => $agent->is_online,
            ],
        ]);
    }

    public function orders(Request $request): JsonResponse
    {
        $agent = Auth::guard('sanctum')->user()->deliveryAgent;
        $status = $request->get('status');

        $query = Order::whereHas('deliveryAssignment', function ($q) use ($agent) {
            $q->where('delivery_agent_id', $agent->id);
        })
        ->with(['user', 'items.product', 'deliveryAssignment']);

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

        $orders = $query->orderByDesc('created_at')->paginate(20);

        return response()->json([
            'success' => true,
            'data' => OrderResource::collection($orders->items()),
            'pagination' => [
                'current_page' => $orders->currentPage(),
                'last_page' => $orders->lastPage(),
                'per_page' => $orders->perPage(),
                'total' => $orders->total(),
            ],
        ]);
    }

    public function newOrders(): JsonResponse
    {
        $agent = Auth::guard('sanctum')->user()->deliveryAgent;

        // Get orders that are confirmed but not yet assigned
        $orders = Order::where('status', 'paid')
            ->where('delivery_status', 'confirmed')
            ->whereNull('delivery_agent_id')
            ->whereDoesntHave('deliveryAssignment')
            ->with(['user', 'items.product'])
            ->orderByDesc('created_at')
            ->limit(20)
            ->get();

        return response()->json([
            'success' => true,
            'data' => OrderResource::collection($orders),
        ]);
    }

    public function showOrder(Order $order): JsonResponse
    {
        $agent = Auth::guard('sanctum')->user()->deliveryAgent;

        // Check if order is assigned to this agent or is available
        $assignment = $order->deliveryAssignment;
        if ($assignment && $assignment->delivery_agent_id !== $agent->id) {
            return response()->json([
                'message' => 'Order not found or not assigned to you.',
            ], 404);
        }

        $order->load(['user', 'items.product.images', 'deliveryAssignment', 'deliveryAgent']);

        return response()->json([
            'success' => true,
            'data' => new OrderResource($order),
        ]);
    }

    public function acceptOrder(Request $request, Order $order): JsonResponse
    {
        $agent = Auth::guard('sanctum')->user()->deliveryAgent;

        if (! $agent->isAvailable()) {
            return response()->json([
                'message' => 'You must be online to accept orders.',
            ], 400);
        }

        // Check if order is already assigned
        if ($order->delivery_agent_id) {
            return response()->json([
                'message' => 'Order is already assigned.',
            ], 400);
        }

        DB::transaction(function () use ($order, $agent) {
            // Create assignment
            $assignment = DeliveryAssignment::create([
                'order_id' => $order->id,
                'delivery_agent_id' => $agent->id,
                'status' => 'accepted',
                'assigned_at' => now(),
                'accepted_at' => now(),
                'delivery_fee' => $order->delivery_fee ?? 50.00, // Default fee
                'delivery_otp' => str_pad((string) rand(1000, 9999), 4, '0', STR_PAD_LEFT),
            ]);

            // Update order
            $order->update([
                'delivery_status' => 'accepted',
                'delivery_agent_id' => $agent->id,
                'assigned_at' => now(),
                'accepted_at' => now(),
            ]);

            // Update agent availability
            $agent->update([
                'availability_status' => 'busy',
            ]);
        });

        return response()->json([
            'success' => true,
            'message' => 'Order accepted successfully',
        ]);
    }

    public function rejectOrder(Request $request, Order $order): JsonResponse
    {
        $request->validate([
            'reason' => 'nullable|string|max:500',
        ]);

        $agent = Auth::guard('sanctum')->user()->deliveryAgent;
        $assignment = $order->deliveryAssignment;

        if (! $assignment || $assignment->delivery_agent_id !== $agent->id) {
            return response()->json([
                'message' => 'Order not found or not assigned to you.',
            ], 404);
        }

        if ($assignment->status !== 'assigned') {
            return response()->json([
                'message' => 'Order cannot be rejected at this stage.',
            ], 400);
        }

        $assignment->update([
            'status' => 'rejected',
            'rejected_at' => now(),
            'rejection_reason' => $request->reason,
        ]);

        $order->update([
            'delivery_status' => 'confirmed',
            'delivery_agent_id' => null,
        ]);

        $agent->update([
            'availability_status' => 'online',
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Order rejected successfully',
        ]);
    }

    public function updateOrderStatus(Request $request, Order $order): JsonResponse
    {
        $request->validate([
            'status' => 'required|in:reached_store,picked_up,on_the_way,reached_customer,delivered',
            'otp' => 'required_if:status,delivered|string|size:4',
        ]);

        $agent = Auth::guard('sanctum')->user()->deliveryAgent;
        $assignment = $order->deliveryAssignment;

        if (! $assignment || $assignment->delivery_agent_id !== $agent->id) {
            return response()->json([
                'message' => 'Order not found or not assigned to you.',
            ], 404);
        }

        // Verify OTP for delivery
        if ($request->status === 'delivered') {
            if ($assignment->delivery_otp !== $request->otp) {
                return response()->json([
                    'message' => 'Invalid OTP.',
                ], 400);
            }
        }

        DB::transaction(function () use ($assignment, $request, $order, $agent) {
            $assignment->updateStatus($request->status);

            // If delivered, create earning and update agent stats
            if ($request->status === 'delivered') {
                DeliveryEarning::create([
                    'delivery_assignment_id' => $assignment->id,
                    'delivery_agent_id' => $agent->id,
                    'delivery_fee' => $assignment->delivery_fee,
                    'bonus' => $assignment->bonus,
                    'status' => 'pending',
                ]);

                $agent->increment('total_deliveries');
                $agent->increment('total_earnings', $assignment->delivery_fee + $assignment->bonus);

                $agent->wallet->credit($assignment->delivery_fee + $assignment->bonus, 'pending_balance');

                $order->update([
                    'status' => 'delivered',
                    'delivered_at' => now(),
                ]);

                $agent->update([
                    'availability_status' => 'online',
                ]);
            }
        });

        return response()->json([
            'success' => true,
            'message' => 'Order status updated successfully',
        ]);
    }

    public function updateLocation(Request $request): JsonResponse
    {
        $request->validate([
            'latitude' => 'required|numeric',
            'longitude' => 'required|numeric',
            'address' => 'nullable|string',
            'speed' => 'nullable|numeric',
            'heading' => 'nullable|numeric',
            'accuracy' => 'nullable|integer',
            'order_id' => 'nullable|exists:orders,id',
        ]);

        $agent = Auth::guard('sanctum')->user()->deliveryAgent;

        // Update agent location
        $agent->updateLocation($request->latitude, $request->longitude);

        // If order_id provided, track for that order
        if ($request->order_id) {
            $order = Order::find($request->order_id);
            $assignment = $order?->deliveryAssignment;

            if ($assignment && $assignment->delivery_agent_id === $agent->id) {
                DeliveryTracking::create([
                    'delivery_assignment_id' => $assignment->id,
                    'latitude' => $request->latitude,
                    'longitude' => $request->longitude,
                    'address' => $request->address,
                    'speed' => $request->speed,
                    'heading' => $request->heading,
                    'accuracy' => $request->accuracy,
                    'tracked_at' => now(),
                ]);
            }
        }

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

    public function earnings(Request $request): JsonResponse
    {
        $agent = Auth::guard('sanctum')->user()->deliveryAgent;
        $status = $request->get('status', 'all');

        $query = DeliveryEarning::where('delivery_agent_id', $agent->id)
            ->with(['assignment.order']);

        if ($status !== 'all') {
            $query->where('status', $status);
        }

        $earnings = $query->orderByDesc('created_at')->paginate(20);

        return response()->json([
            'success' => true,
            'data' => $earnings->map(function ($earning) {
                return [
                    'id' => $earning->id,
                    'order_number' => $earning->assignment->order->order_number ?? 'N/A',
                    'delivery_fee' => $earning->delivery_fee,
                    'bonus' => $earning->bonus,
                    'penalty' => $earning->penalty,
                    'total_amount' => $earning->total_amount,
                    'status' => $earning->status,
                    'created_at' => $earning->created_at->toIso8601String(),
                    'credited_at' => $earning->credited_at?->toIso8601String(),
                ];
            }),
            'pagination' => [
                'current_page' => $earnings->currentPage(),
                'last_page' => $earnings->lastPage(),
                'per_page' => $earnings->perPage(),
                'total' => $earnings->total(),
            ],
        ]);
    }

    public function history(Request $request): JsonResponse
    {
        $agent = Auth::guard('sanctum')->user()->deliveryAgent;
        $status = $request->get('status');

        $query = Order::whereHas('deliveryAssignment', function ($q) use ($agent) {
            $q->where('delivery_agent_id', $agent->id)
                ->whereIn('status', ['delivered', 'cancelled']);
        })
        ->with(['user', 'items.product', 'deliveryAssignment']);

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

        $orders = $query->orderByDesc('created_at')->paginate(20);

        return response()->json([
            'success' => true,
            'data' => OrderResource::collection($orders->items()),
            'pagination' => [
                'current_page' => $orders->currentPage(),
                'last_page' => $orders->lastPage(),
                'per_page' => $orders->perPage(),
                'total' => $orders->total(),
            ],
        ]);
    }
}
