<?php

namespace App\Providers;

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Route;

class RouteServiceProvider extends ServiceProvider
{
    /**
     * The path to your application's "home" route.
     *
     * Typically, users are redirected here after authentication.
     *
     * @var string
     */
    public const HOME = '/dashboard';

    /**
     * Define your route model bindings, pattern filters, and other route configuration.
     */
    public function boot(): void
    {
        RateLimiter::for('api', function (Request $request) {
            // Very high rate limit for authenticated users - POS systems need many requests
            if ($request->user()) {
                // Authenticated users: 5000 requests per minute per user (effectively unlimited for normal use)
                return Limit::perMinute(5000)->by($request->user()->id);
            }
            // Unauthenticated users: 120 requests per minute per IP
            return Limit::perMinute(120)->by($request->ip());
        });
        
        // Create a separate rate limiter for admin/authenticated routes with even higher limits
        RateLimiter::for('api-auth', function (Request $request) {
            if ($request->user()) {
                // Very high limit for authenticated admin/API routes
                return Limit::perMinute(10000)->by($request->user()->id);
            }
            return Limit::perMinute(60)->by($request->ip());
        });

        // Configure route model binding for 'order' parameter to use PosOrder model
        // ALWAYS check for replacement orders before aborting - never show "Order not found" if replacement exists
        Route::bind('order', function ($value, $route) {
            $request = request();
            
            // Helper function to find replacement order
            // This handles multiple scenarios:
            // 1. Direct replacement via replaced_order_id
            // 2. Active order with same order_number (for multiple updates)
            $findReplacement = function($orderId) use ($request) {
                $deletedOrder = \App\Models\PosOrder::withTrashed()->find($orderId);
                if ($deletedOrder && $deletedOrder->trashed()) {
                    // First, try to find direct replacement via replaced_order_id
                    $replacement = \App\Models\PosOrder::withoutTrashed()
                        ->where('replaced_order_id', $deletedOrder->id)
                        ->first();
                    
                    if ($replacement) {
                        \Log::info('RouteServiceProvider: Found direct replacement order', [
                            'old_order_id' => $deletedOrder->id,
                            'new_order_id' => $replacement->id,
                            'order_number' => $replacement->order_number,
                            'method' => $request->method(),
                            'route' => $request->path()
                        ]);
                        return $replacement;
                    }
                    
                    // If no direct replacement, try to find any active order with the same order_number
                    // This handles cases where orders were updated multiple times
                    $activeOrderWithSameNumber = \App\Models\PosOrder::withoutTrashed()
                        ->where('order_number', $deletedOrder->order_number)
                        ->where('branch_id', $deletedOrder->branch_id)
                        ->where('id', '!=', $deletedOrder->id)
                        ->orderBy('created_at', 'desc') // Get the most recent one
                        ->first();
                    
                    if ($activeOrderWithSameNumber) {
                        \Log::info('RouteServiceProvider: Found active order with same order_number', [
                            'old_order_id' => $deletedOrder->id,
                            'new_order_id' => $activeOrderWithSameNumber->id,
                            'order_number' => $activeOrderWithSameNumber->order_number,
                            'method' => $request->method(),
                            'route' => $request->path()
                        ]);
                        return $activeOrderWithSameNumber;
                    }
                }
                return null;
            };
            
            // For PUT/PATCH requests (updates), try to find non-deleted order first
            // If not found, check for replacement
            if (in_array($request->method(), ['PUT', 'PATCH'])) {
                $order = \App\Models\PosOrder::withoutTrashed()->find($value);
                if ($order) {
                    return $order;
                }
                
                // Check for replacement order
                $replacement = $findReplacement($value);
                if ($replacement) {
                    return $replacement;
                }
                
                // Only abort if truly not found and no replacement exists
                \Log::warning('RouteServiceProvider: Order not found for PUT/PATCH', [
                    'order_id' => $value,
                    'route' => $request->path(),
                    'method' => $request->method()
                ]);
                abort(404, 'Order not found');
            }
            // For POST requests (like processPayment), allow non-deleted orders
            // If order is soft-deleted, try to find its replacement and use that instead
            if (in_array($request->method(), ['POST'])) {
                // First try to find non-deleted order
                $order = \App\Models\PosOrder::withoutTrashed()->find($value);
                if ($order) {
                    return $order;
                }
                
                // Check for replacement order
                $replacement = $findReplacement($value);
                if ($replacement) {
                    return $replacement;
                }
                
                // Only abort if truly not found and no replacement exists
                \Log::warning('RouteServiceProvider: Order not found for POST', [
                    'order_id' => $value,
                    'route' => $request->path(),
                    'method' => $request->method()
                ]);
                abort(404, 'Order not found');
            }
            // For GET/DELETE requests, include soft-deleted records (for viewing receipts, invoices, etc.)
            // But if order is soft-deleted and has a replacement, return the replacement instead
            $order = \App\Models\PosOrder::withTrashed()->find($value);
            if (!$order) {
                \Log::warning('RouteServiceProvider: Order not found at all', [
                    'order_id' => $value,
                    'route' => $request->path(),
                    'method' => $request->method()
                ]);
                abort(404, 'Order not found');
            }
            
            // If order is soft-deleted, check if it has a replacement
            if ($order->trashed() || $order->deleted_at) {
                // First, try direct replacement
                $replacement = \App\Models\PosOrder::withoutTrashed()
                    ->where('replaced_order_id', $order->id)
                    ->first();
                
                if ($replacement) {
                    // Return the replacement order instead - this allows operations on the new order
                    \Log::info('RouteServiceProvider: Redirecting GET request from soft-deleted order to replacement', [
                        'old_order_id' => $order->id,
                        'new_order_id' => $replacement->id,
                        'order_number' => $replacement->order_number,
                        'route' => $request->path()
                    ]);
                    return $replacement;
                }
                
                // If no direct replacement, try to find any active order with the same order_number
                $activeOrderWithSameNumber = \App\Models\PosOrder::withoutTrashed()
                    ->where('order_number', $order->order_number)
                    ->where('branch_id', $order->branch_id)
                    ->where('id', '!=', $order->id)
                    ->orderBy('created_at', 'desc') // Get the most recent one
                    ->first();
                
                if ($activeOrderWithSameNumber) {
                    \Log::info('RouteServiceProvider: Redirecting GET request to active order with same order_number', [
                        'old_order_id' => $order->id,
                        'new_order_id' => $activeOrderWithSameNumber->id,
                        'order_number' => $activeOrderWithSameNumber->order_number,
                        'route' => $request->path()
                    ]);
                    return $activeOrderWithSameNumber;
                }
            }
            
            return $order;
        });

        $this->routes(function () {
            Route::middleware('api')
                ->prefix('api')
                ->group(base_path('routes/api.php'));

            Route::middleware('web')
                ->group(base_path('routes/web.php'));
        });
    }
}

