<?php

namespace App\Http\Controllers\Api\Customer;

use App\Http\Controllers\Controller;
use App\Models\Order;
use App\Models\OrderStatusHistory;
use App\Models\Setting;
use App\Services\OrderFulfilmentService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;

class OrderController extends Controller
{
    /**
     * GET /api/customer/orders
     */
    public function index(Request $request): JsonResponse
    {
        $userId = Auth::guard('customer')->id();

        $query = Order::where('user_id', $userId)
            ->withCount('items')
            ->with(['items.vendor:id,store_name']);

        if ($request->filled('status')) {
            match ($request->status) {
                'active' => $query->whereNotIn('status', ['delivered', 'cancelled', 'returned']),
                'past'   => $query->whereIn('status', ['delivered', 'cancelled', 'returned']),
                default  => $query->where('status', $request->status),
            };
        }

        return response()->json([
            'data' => $query->latest()->paginate($request->integer('per_page', 20)),
        ]);
    }

    /**
     * GET /api/customer/orders/{order}
     * Full detail with items, vendors, delivery progress, status history.
     */
    public function show(Order $order): JsonResponse
    {
        $this->authorizeOwn($order);

        $order->load([
            'items.product:id,name_en,name_ur',
            'items.vendor:id,store_name,slug,phone',
            'deliveryAssignments' => fn($q) => $q->with(['partner:id,name,phone,vehicle_type,last_lat,last_lng', 'vendor:id,store_name']),
            'statusHistory' => fn($q) => $q->latest()->limit(20),
            'address',
        ]);

        // Flag for the "vendor is slow — keep waiting?" banner.
        $order->setAttribute(
            'awaiting_confirmation',
            $order->items->contains(fn($i) => $i->isAwaitingCustomer()),
        );

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

    /**
     * POST /api/customer/orders/{order}/cancel
     * Customer can cancel if no item has been picked up yet.
     */
    public function cancel(Request $request, Order $order, OrderFulfilmentService $fulfilment): JsonResponse
    {
        $this->authorizeOwn($order);

        $request->validate(['reason' => 'nullable|string|max:300']);

        abort_if(
            in_array($order->status, ['picked_up', 'on_the_way', 'delivered', 'cancelled']),
            422,
            'Order can no longer be cancelled.'
        );

        DB::transaction(function () use ($order, $request) {
            $order->update([
                'status'              => 'cancelled',
                'cancellation_reason' => $request->reason ?? 'Cancelled by customer.',
            ]);

            // Restore stock for non-rejected items
            foreach ($order->items as $item) {
                if (! in_array($item->status, ['rejected', 'cancelled']) && $item->product?->track_stock) {
                    $item->product->increment('stock_quantity', $item->quantity);
                }
                $item->update(['status' => 'cancelled']);
            }

            OrderStatusHistory::create([
                'order_id'   => $order->id,
                'status'     => 'cancelled',
                'note'       => $request->reason ?? 'Cancelled by customer.',
                'actor_type' => 'user',
                'actor_id'   => $order->user_id,
            ]);
        });

        // Refund to the in-app wallet if the order had already been paid online.
        $refunded = $fulfilment->refundOrder($order->fresh(), 'Cancelled by customer.');

        return response()->json([
            'message'  => $refunded
                ? 'Order cancelled. Your payment has been refunded to your wallet.'
                : 'Order cancelled.',
            'order'    => $order->fresh(),
            'refunded' => $refunded,
        ]);
    }

    /**
     * POST /api/customer/orders/{order}/keep-waiting
     * Customer answers the "vendor is slow — keep waiting?" prompt by extending
     * the acceptance window instead of cancelling.
     */
    public function keepWaiting(Order $order, OrderFulfilmentService $fulfilment): JsonResponse
    {
        $this->authorizeOwn($order);

        $accept = (int) (Setting::get('sla_accept_minutes') ?: 30);
        $count  = $fulfilment->keepWaiting($order, $accept);

        return response()->json([
            'message'  => $count > 0
                ? "Thanks for waiting — we've reminded the vendor."
                : 'There is nothing to extend on this order.',
            'extended' => $count,
            'order'    => $order->fresh(),
        ]);
    }

    /**
     * GET /api/customer/orders/{order}/track
     * Lightweight live-tracking payload.
     */
    public function track(Order $order): JsonResponse
    {
        $this->authorizeOwn($order);

        $order->load(['deliveryAssignments.partner:id,name,vehicle_type,last_lat,last_lng,last_location_at']);

        return response()->json([
            'order_number' => $order->order_number,
            'status'       => $order->status,
            'delivery_otp' => $order->delivery_otp,
            'delivery_lat' => $order->delivery_lat !== null ? (float) $order->delivery_lat : null,
            'delivery_lng' => $order->delivery_lng !== null ? (float) $order->delivery_lng : null,
            'assignments'  => $order->deliveryAssignments->map(fn($a) => [
                'vendor_id'   => $a->vendor_id,
                'status'      => $a->status,
                'partner'     => $a->partner ? [
                    'name'         => $a->partner->name,
                    'vehicle_type' => $a->partner->vehicle_type,
                    'lat'          => $a->partner->last_lat,
                    'lng'          => $a->partner->last_lng,
                    'last_seen'    => $a->partner->last_location_at,
                ] : null,
            ]),
        ]);
    }

    private function authorizeOwn(Order $order): void
    {
        abort_unless(
            $order->user_id === Auth::guard('customer')->id(),
            403,
            'You do not own this order.'
        );
    }
}
