<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;
use Illuminate\Support\Facades\Auth;

class PermittedIn implements Rule
{
    protected $optionsWithPermissions;
    protected $rejectedValue;
    protected $allowedOptions = [];

    /**
     * Create a new rule instance.
     *
     * @param array $optionsWithPermissions
     */
    public function __construct(array $optionsWithPermissions)
    {
        $this->optionsWithPermissions = $optionsWithPermissions;
    }

    /**
     * Static constructor for cleaner syntax
     *
     * @param array $optionsWithPermissions
     * @return static
     */
    public static function make(array $optionsWithPermissions)
    {
        return new static($optionsWithPermissions);
    }

    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        try {
            // First check if the value is a valid option
            if (!array_key_exists($value, $this->optionsWithPermissions)) {
                $this->rejectedValue = $value;
                return false;
            }

            // Get the required permission for this value
            $requiredPermission = $this->optionsWithPermissions[$value];
            
            // If no permission required (null), it passes
            if ($requiredPermission === null) {
                return true;
            }

            // Check if user has the required permission
            $user = Auth::user();
            if (!$user || !$user->canDo($requiredPermission)) {
                $this->rejectedValue = $value;
                
                // Build allowed options for error message
                foreach ($this->optionsWithPermissions as $option => $permission) {
                    if ($permission === null || ($user && $user->canDo($permission))) {
                        $this->allowedOptions[] = $option;
                    }
                }
                
                return false;
            }

            return true;
        } catch (\Exception $ex) {
            return false;
        }
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        if ($this->rejectedValue && !array_key_exists($this->rejectedValue, $this->optionsWithPermissions)) {
            return 'The selected :attribute is invalid.';
        }

        if (empty($this->allowedOptions)) {
            // Build allowed options if not already built
            $user = Auth::user();
            foreach ($this->optionsWithPermissions as $option => $permission) {
                if ($permission === null || ($user && $user->canDo($permission))) {
                    $this->allowedOptions[] = $option;
                }
            }
        }

        if (empty($this->allowedOptions)) {
            return 'You do not have permission to use any of the available options for :attribute.';
        }

        $requiredPermission = $this->optionsWithPermissions[$this->rejectedValue] ?? null;
        return 'You do not have permission to use "' . $this->rejectedValue . '" for :attribute. ' .
               ($requiredPermission !== null ? 'Missing permission: ' . $requiredPermission . '. ' : '') .
               'Allowed values: ' . implode(', ', $this->allowedOptions) . '.';
    }
}