<?php

namespace App\Http\Controllers\Api\Mobile\Rider;

use App\Http\Controllers\Controller;
use App\Models\DeliveryOrderOffer;
use App\Models\FundTransaction;
use App\Models\Order;
use App\Models\OrderStatus;
use App\Services\LocalDeliveryDispatchService;
use App\Services\RiderWalletService;
use Carbon\Carbon;
use Illuminate\Http\Request;

class OrderController extends Controller
{
    public function __construct(protected LocalDeliveryDispatchService $dispatch)
    {
    }

    public function pendingOffers(Request $request)
    {
        $rider = $request->user()->fresh();
        $this->dispatch->redistributeUnassignedOrders();
        $this->dispatch->expireStaleOffers();

        $localEnabled = $this->dispatch->isLocalDeliveryEnabled();

        if (!$localEnabled) {
            return response()->json([
                'status' => 'success',
                'data' => [],
                'message' => 'Local delivery is OFF in admin. Enable it under Local Delivery settings.',
                'meta' => $this->offerMeta($rider, 0, 5),
            ]);
        }

        if (!$rider->isApproved()) {
            return response()->json([
                'status' => 'success',
                'data' => [],
                'message' => 'Your rider account is not approved yet.',
                'meta' => $this->offerMeta($rider, 0, 5),
            ]);
        }

        if (!$this->dispatch->riderIsOnline($rider) || !$this->dispatch->riderAcceptsRequests($rider)) {
            return response()->json([
                'status' => 'success',
                'data' => [],
                'message' => 'Go online and enable Accept requests to see orders',
            ]);
        }

        $maxActive = $this->dispatch->maxActiveOrdersLimit();
        $activeCount = $this->dispatch->activeOrderCount($rider->id);
        if ($activeCount >= $maxActive) {
            return response()->json([
                'status' => 'success',
                'data' => [],
                'message' => 'Max active deliveries reached',
                'meta' => $this->offerMeta($rider, $activeCount, $maxActive),
            ]);
        }

        $this->dispatch->ensureOffersForRider($rider);
        $this->dispatch->refreshLiveOffersForRider($rider);

        $offers = DeliveryOrderOffer::with(['order' => fn ($q) => $q->with($this->orderRelations())])
            ->where('delivery_man_id', $rider->id)
            ->where('status', 'pending')
            ->where('expires_at', '>', Carbon::now())
            ->latest()
            ->get();

        return response()->json([
            'status' => 'success',
            'data' => $offers
                ->filter(fn ($o) => $o->order !== null)
                ->map(fn ($o) => $this->formatOffer($o))
                ->values(),
            'meta' => $this->offerMeta($rider, $activeCount, $maxActive),
        ]);
    }

    protected function offerMeta($rider, int $activeCount, int $maxActive): array
    {
        $online = $this->dispatch->countOnlineRiders();

        $dispatch = $this->dispatch;

        return [
            'online_riders' => $online,
            'can_pass' => $online > 1,
            'max_active_orders' => $maxActive,
            'active_orders' => $activeCount,
            'unlimited_active' => $maxActive >= LocalDeliveryDispatchService::MAX_ACTIVE_ORDERS_LOW_RIDERS,
            'riders_short' => $dispatch->isRidersShortForDemand(),
            'unassigned_orders' => $dispatch->countUnassignedLocalOrders(),
            'local_delivery_enabled' => $dispatch->isLocalDeliveryEnabled(),
            'rider_online' => $dispatch->riderIsOnline($rider),
            'rider_accepts' => $dispatch->riderAcceptsRequests($rider),
            'pending_offer_rows' => DeliveryOrderOffer::where('delivery_man_id', $rider->id)
                ->where('status', 'pending')
                ->count(),
        ];
    }

    public function active(Request $request)
    {
        $rider = $request->user();
        $slugs = ['assigned-to-delivery-man', 'rider-accepted', 'on-the-way'];
        $statusIds = OrderStatus::whereIn('slug', $slugs)->pluck('id')->filter()->all();

        $orders = Order::whereHas('shipping', fn ($q) => $q->where('delivery_man_id', $rider->id))
            ->whereIn('order_status', $statusIds ?: [0])
            ->with($this->orderRelations())
            ->latest()
            ->get();

        $maxActive = $this->dispatch->maxActiveOrdersLimit();
        $activeCount = $this->dispatch->activeOrderCount($rider->id);

        return response()->json([
            'status' => 'success',
            'data' => $orders->map(fn ($o) => $this->formatOrder($o))->values(),
            'meta' => [
                'max_active_orders' => $maxActive,
                'active_orders' => $activeCount,
                'unlimited_active' => $maxActive >= LocalDeliveryDispatchService::MAX_ACTIVE_ORDERS_LOW_RIDERS,
                'online_riders' => $this->dispatch->countOnlineRiders(),
            ],
        ]);
    }

    public function history(Request $request)
    {
        $rider = $request->user();
        $completedId = OrderStatus::where('slug', 'completed')->value('id');

        $orders = Order::whereHas('shipping', fn ($q) => $q->where('delivery_man_id', $rider->id))
            ->when($completedId, fn ($q) => $q->where('order_status', $completedId))
            ->with(['shipping', 'status'])
            ->latest()
            ->paginate(20);

        return response()->json([
            'status' => 'success',
            'data' => collect($orders->items())->map(fn ($o) => $this->formatOrder($o))->values(),
            'pagination' => [
                'current_page' => $orders->currentPage(),
                'last_page' => $orders->lastPage(),
                'total' => $orders->total(),
            ],
        ]);
    }

    public function accept(Request $request, $id)
    {
        $result = $this->dispatch->acceptOffer($request->user(), (int) $id);
        $code = $result['ok'] ? 200 : 400;
        return response()->json(['status' => $result['ok'] ? 'success' : 'error', 'message' => $result['message']], $code);
    }

    public function pass(Request $request, $id)
    {
        $result = $this->dispatch->passOffer($request->user(), (int) $id);
        $code = $result['ok'] ? 200 : 400;
        return response()->json(['status' => $result['ok'] ? 'success' : 'error', 'message' => $result['message']], $code);
    }

    public function pickup(Request $request, $id)
    {
        return $this->updateStatus($request, (int) $id, 'on-the-way', 'Delivery started');
    }

    public function deliver(Request $request, $id)
    {
        $rider = $request->user();
        $order = $this->riderOrder($rider->id, (int) $id);
        if (!$order) {
            return response()->json(['status' => 'error', 'message' => 'Order not found'], 404);
        }

        $order->load('payment');

        $status = OrderStatus::where('slug', 'completed')->first();
        if (!$status) {
            return response()->json(['status' => 'error', 'message' => 'Status not configured'], 500);
        }

        $order->order_status = $status->id;
        $order->save();

        app(\App\Services\PushNotificationService::class)->notifyOrderStatusChanged($order);

        app(RiderWalletService::class)->accrueFromDeliveredOrder($order, $rider);

        FundTransaction::create([
            'direction' => 'in',
            'source' => 'sale',
            'source_id' => $order->id,
            'amount' => $order->amount,
            'note' => 'Order completed by Rider #' . $order->invoice_id,
        ]);

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

    public function earnings(Request $request)
    {
        $rider = $request->user();
        $completedId = OrderStatus::where('slug', 'completed')->value('id');
        $wallet = app(\App\Services\RiderWalletService::class);

        $query = Order::whereHas('shipping', fn ($q) => $q->where('delivery_man_id', $rider->id))
            ->when($completedId, fn ($q) => $q->where('order_status', $completedId))
            ->with('payment');

        if ($request->filled('date')) {
            $query->whereDate('updated_at', $request->date);
        } elseif ($request->filled('from') && $request->filled('to')) {
            $query->whereBetween('updated_at', [
                $request->from . ' 00:00:00',
                $request->to . ' 23:59:59',
            ]);
        }

        $orders = $query->get();
        $codOrders = $orders->filter(fn ($o) => $o->payment?->payment_method === 'cod');
        $digitalOrders = $orders->filter(fn ($o) => $o->payment && $o->payment->payment_method !== 'cod');

        $sumShare = fn ($collection) => round($collection->sum(fn ($o) => $wallet->riderShareForOrder($o, $rider)), 2);

        $allTimeCod = Order::whereHas('shipping', fn ($q) => $q->where('delivery_man_id', $rider->id))
            ->when($completedId, fn ($q) => $q->where('order_status', $completedId))
            ->with('payment')
            ->get()
            ->filter(fn ($o) => $o->payment?->payment_method === 'cod');

        $todayCod = $allTimeCod->filter(fn ($o) => $o->updated_at && $o->updated_at->isToday());

        $summary = $wallet->walletSummary($rider);
        $pendingCollection = \App\Models\RiderRevenueCollection::where('delivery_man_id', $rider->id)
            ->where('status', 'pending')
            ->latest()
            ->first();

        return response()->json([
            'status' => 'success',
            'data' => [
                'completed_deliveries' => $orders->count(),
                'cod_deliveries' => $codOrders->count(),
                'digital_deliveries' => $digitalOrders->count(),
                'total_income' => $sumShare($allTimeCod),
                'today_income' => $sumShare($todayCod),
                'period_income' => $sumShare($codOrders),
                'your_earnings' => $sumShare($codOrders),
                'total_order_value' => round($orders->sum('amount'), 2),
                'total_delivery_fees' => round($orders->sum('shipping_charge'), 2),
                'platform_commission_percent' => (float) $rider->platform_commission_percent,
                'digital_wallet_balance' => $summary['digital_wallet_balance'],
                'due_product_amount' => $summary['due_product_amount'],
                'due_commission_amount' => $summary['due_commission_amount'],
                'due_to_platform' => $summary['total_due_to_platform'],
                'pending_collection' => $pendingCollection ? [
                    'id' => $pendingCollection->id,
                    'product_amount' => (float) $pendingCollection->product_amount,
                    'commission_amount' => (float) $pendingCollection->commission_amount,
                    'total_amount' => (float) $pendingCollection->total_amount,
                    'otp' => $pendingCollection->otp,
                    'otp_expires_at' => $pendingCollection->otp_expires_at ? $pendingCollection->otp_expires_at->format('Y-m-d H:i:s') : null,
                    'note' => $pendingCollection->note,
                    'created_at' => $pendingCollection->created_at ? $pendingCollection->created_at->format('Y-m-d H:i:s') : null,
                ] : null,
            ],
        ]);
    }

    protected function updateStatus(Request $request, int $orderId, string $slug, string $message)
    {
        $rider = $request->user();
        $order = $this->riderOrder($rider->id, $orderId);
        if (!$order) {
            return response()->json(['status' => 'error', 'message' => 'Order not found'], 404);
        }

        $status = OrderStatus::where('slug', $slug)->first();
        if (!$status) {
            return response()->json(['status' => 'error', 'message' => 'Status not found'], 500);
        }

        $order->order_status = $status->id;
        $order->save();

        app(\App\Services\PushNotificationService::class)->notifyOrderStatusChanged($order);

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

    protected function riderOrder(int $riderId, int $orderId): ?Order
    {
        return Order::where('id', $orderId)
            ->whereHas('shipping', fn ($q) => $q->where('delivery_man_id', $riderId))
            ->first();
    }

    protected function formatOffer(DeliveryOrderOffer $offer): array
    {
        $order = $offer->order;
        $secondsLeft = 0;
        if ($offer->expires_at) {
            $secondsLeft = max(0, (int) Carbon::now()->diffInSeconds($offer->expires_at, false));
        }

        $zoneId = (int) ($order->shipping?->local_delivery_zone_id ?? 0);
        $zoneRiders = $zoneId > 0 ? $this->dispatch->eligibleRiders($zoneId)->count() : 0;

        return [
            'offer_id' => $offer->id,
            'order_id' => $order->id,
            'seconds_left' => $secondsLeft,
            'can_pass' => $this->dispatch->countOnlineEligibleRiders() > 1 && $zoneRiders > 1,
            'order' => $this->formatOrder($order),
        ];
    }

    protected function orderRelations(): array
    {
        return [
            'shipping',
            'status',
            'payment',
            'orderdetails.product.image',
            'orderdetails.size',
            'orderdetails.color',
            'orderdetails.image',
        ];
    }

    protected function formatOrder(Order $order): array
    {
        $shipping = $order->shipping;
        $coords = $this->parseMapCoordinates($shipping?->map);

        return [
            'id' => $order->id,
            'invoice_id' => $order->invoice_id,
            'amount' => $order->amount,
            'shipping_charge' => $order->shipping_charge,
            'status' => $order->status?->name,
            'status_slug' => $order->status?->slug,
            'payment_method' => $order->payment?->payment_method,
            'customer' => [
                'name' => $shipping?->name,
                'phone' => $shipping?->phone,
                'address' => $shipping?->address,
                'area' => $shipping?->area,
                'map' => $shipping?->map,
                'latitude' => $coords['lat'],
                'longitude' => $coords['lng'],
            ],
            'items' => collect($order->orderdetails ?? [])
                ->map(fn ($item) => $this->formatOrderItem($item))
                ->values()
                ->all(),
            'item_count' => (int) ($order->orderdetails?->count() ?? 0),
            'total_items' => (int) ($order->orderdetails?->sum('qty') ?? 0),
            'created_at' => $order->created_at?->format('Y-m-d H:i'),
        ];
    }

    protected function formatOrderItem($item): array
    {
        $image = null;
        if ($item->product && $item->product->image) {
            $image = url($item->product->image->image);
        } elseif ($item->image) {
            $image = url($item->image->image);
        }

        return [
            'id' => $item->id,
            'product_id' => $item->product_id,
            'product_name' => $item->product_name,
            'product_code' => $item->product?->product_code,
            'quantity' => (int) $item->qty,
            'price' => (float) $item->sale_price,
            'subtotal' => (float) ($item->qty * $item->sale_price),
            'size' => $item->size?->name,
            'color' => $item->color?->name,
            'product_image' => $image,
        ];
    }

    protected function parseMapCoordinates(?string $map): array
    {
        if (!$map) {
            return ['lat' => null, 'lng' => null];
        }
        if (preg_match('/(-?\d+\.\d+)\s*,\s*(-?\d+\.\d+)/', $map, $m)) {
            return ['lat' => (float) $m[1], 'lng' => (float) $m[2]];
        }

        return ['lat' => null, 'lng' => null];
    }
}
