<?php

namespace App\Http\Requests\Admin;

use App\Models\Order;
use App\Services\LedgerService;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\ValidationException;

class UpdateOrderStatusRequest extends FormRequest
{
    public function authorize(): bool
    {
        $user = auth()->user();
        
        if (!$user) {
            return false;
        }
        
        // Check if user has admin or staff user_type (primary check)
        if ($user->isAdmin() || $user->isStaff()) {
            return true;
        }
        
        // Fallback: Check permission if available
        try {
            if (method_exists($user, 'can') && $user->can('orders.update')) {
                return true;
            }
        } catch (\Exception $e) {
            // Permission system might not be fully set up, ignore
        }
        
        return false;
    }

    public function rules(): array
    {
        return [
            'status' => [
                'required',
                'in:' . implode(',', [
                    Order::STATUS_AWAITING_PAYMENT,
                    Order::STATUS_PLACED,
                    Order::STATUS_CONFIRMED,
                    Order::STATUS_PACKED,
                    Order::STATUS_AWAITING_PICKUP,
                    Order::STATUS_SHIPPED,
                    Order::STATUS_DELIVERED,
                    Order::STATUS_CANCELLED,
                    Order::STATUS_RETURNED,
                ]),
            ],
        ];
    }

    /**
     * Configure the validator instance.
     */
    public function withValidator($validator): void
    {
        $validator->after(function ($validator) {
            $user = auth()->user();
            $order = $this->route('order');
            $newStatus = $this->input('status');
            
            if (!$order || !$newStatus) {
                return;
            }

            $currentStatus = $order->status;

            // Skip closed-day check for admins or users with reopen permission
            if (!$user || ($user->isAdmin() || $user->can('reports.day-ledger.reopen'))) {
                // Allowed - no check needed
            } else {
                try {
                    app(LedgerService::class)->assertDayOpen($order->created_at->toDateString());
                } catch (ValidationException $e) {
                    $message = $e->errors()['date'][0] ?? 'This day is closed. Reopen it before updating orders.';
                    $validator->errors()->add('status', $message);
                    return;
                }
            }
            
            // Allow admin to change status in any direction
            if ($user && $user->isAdmin()) {
                return;
            }

            // For non-admin users, check if status change is forward
            if (!$this->isStatusForward($currentStatus, $newStatus)) {
                $validator->errors()->add(
                    'status',
                    'Order status can only be moved forward.'
                );
            }
        });
    }

    /**
     * Check if status change is forward (or special case)
     */
    private function isStatusForward(string $currentStatus, string $newStatus): bool
    {
        // Special cases: cancelled can be set from any status, returned from delivered
        if ($newStatus === Order::STATUS_CANCELLED) {
            return true; // Can always cancel
        }
        if ($newStatus === Order::STATUS_RETURNED && $currentStatus === Order::STATUS_DELIVERED) {
            return true; // Can return from delivered
        }
        
        $sequence = $this->getStatusSequence();
        $currentOrder = $sequence[$currentStatus] ?? 0;
        $newOrder = $sequence[$newStatus] ?? 0;
        
        return $newOrder > $currentOrder;
    }

    /**
     * Get status sequence order for forward-only validation
     */
    private function getStatusSequence(): array
    {
        return [
            Order::STATUS_AWAITING_PAYMENT => 1,
            Order::STATUS_PLACED => 2,
            Order::STATUS_CONFIRMED => 3,
            Order::STATUS_PACKED => 4,
            Order::STATUS_AWAITING_PICKUP => 5,
            Order::STATUS_SHIPPED => 6,
            Order::STATUS_DELIVERED => 7,
            // cancelled and returned are special cases
        ];
    }
}
