<?php
namespace boru\boruai\Models;

class ToolProperty {
    private $name;
    private $type;
    private $description;
    private $required = true;
    private $enum = [];
    /** @var ToolProperty[] */
    private $subProperties = [];

    // Extra JSON-schema-ish fields (all optional)
    private $default = null;
    private $hasDefault = false;
    private $format = null;
    private $minLength = null;
    private $maxLength = null;
    private $minimum = null;
    private $maximum = null;

    public function __construct($input=[]) {

        $this->name = isset($input["name"]) ? $input["name"] : null;
        $this->type = isset($input["type"]) ? $input["type"] : null;
        $this->description = isset($input["description"]) ? $input["description"] : null;
        $this->required = isset($input["required"]) ? $input["required"] : true;
        $this->enum = isset($input["enum"]) ? $input["enum"] : [];
        // Support nested properties for object/anyOf (existing behavior)
        if (isset($input["properties"]) && is_array($input["properties"])) {
            $this->subProperties = [];
            foreach ($input["properties"] as $name => $prop) {
                if ($prop instanceof ToolProperty) {
                    $this->subProperties[$prop->name()] = $prop;
                } else {
                    $tp = new ToolProperty($prop);
                    // Make sure name is set
                    if ($tp->name() === null) {
                        $tp->name($name);
                    }
                    $this->subProperties[$tp->name()] = $tp;
                }
            }
        } else {
            $this->subProperties = isset($input["properties"]) ? $input["properties"] : [];
        }

        // Extra fields (all optional)
        if (array_key_exists("default", $input)) {
            $this->default    = $input["default"];
            $this->hasDefault = true;
        }
        if (isset($input["format"])) {
            $this->format = $input["format"];
        }
        if (isset($input["minLength"])) {
            $this->minLength = (int)$input["minLength"];
        }
        if (isset($input["maxLength"])) {
            $this->maxLength = (int)$input["maxLength"];
        }
        if (isset($input["minimum"])) {
            $this->minimum = $input["minimum"];
        }
        if (isset($input["maximum"])) {
            $this->maximum = $input["maximum"];
        }
    }
    
    public function name($name=null) {
        if($name !== null) {
            $this->name = $name;
            return $this;
        }
        return $this->name;
    }

    public function type($type=null) {
        if($type !== null) {
            $this->type = $type;
            return $this;
        }
        return $this->type;
    }

    public function description($description=null) {
        if($description !== null) {
            $this->description = $description;
            return $this;
        }
        return $this->description;
    }

    public function required($required=null) {
        if($required !== null) {
            $this->required = $required ? true : false;
            return $this;
        }
        return $this->required;
    }

    public function enum($values=[]) {
        $this->enum = $values;
        return $this;
    }

    // New fluent helpers (optional but nice)
    public function defaultValue($value) {
        $this->default    = $value;
        $this->hasDefault = true;
        return $this;
    }

    public function format($format = null) {
        if ($format !== null) {
            $this->format = $format;
            return $this;
        }
        return $this->format;
    }

    public function minLength($len = null) {
        if ($len !== null) {
            $this->minLength = (int)$len;
            return $this;
        }
        return $this->minLength;
    }

    public function maxLength($len = null) {
        if ($len !== null) {
            $this->maxLength = (int)$len;
            return $this;
        }
        return $this->maxLength;
    }

    public function minimum($val = null) {
        if ($val !== null) {
            $this->minimum = $val;
            return $this;
        }
        return $this->minimum;
    }

    public function maximum($val = null) {
        if ($val !== null) {
            $this->maximum = $val;
            return $this;
        }
        return $this->maximum;
    }

    /**
     * For object/anyOf properties you may want a way to add nested properties.
     */
    public function addSubProperty(ToolProperty $prop) {
        $this->subProperties[$prop->name()] = $prop;
        return $this;
    }

    /**
     * Compile to OpenAI/JSON-schema-like array.
     */
    public function compile($root = true) {
        // anyOf support: treat subProperties as list of alternate schemas
        if ($this->type == "anyOf") {
            $anyOf = [];
            foreach ($this->subProperties as $subProperty) {
                $anyOf[] = $subProperty->compile(false);
            }
            return [
                "anyOf" => $anyOf
            ];
        }

        // object support: nested properties
        if ($this->type == "object") {
            $props    = [];
            $required = [];

            foreach ($this->subProperties as $sub) {
                $props[$sub->name()] = $sub->compile(false);
                if ($sub->required()) {
                    $required[] = $sub->name();
                }
            }

            $array = [
                "type"       => "object",
                "properties" => $props,
            ];
            if (!empty($required)) {
                $array["required"] = $required;
            }

            // no description? keep compatibility: you can still set one
            if ($this->description !== null) {
                $array["description"] = $this->description;
            }

            return $array;
        }

        // scalar / enum / string / number / boolean etc.
        $array = [
            "type"        => $this->type,
            "description" => $this->description,
        ];

        if (count($this->enum) > 0) {
            $array["enum"] = $this->enum;
        }

        if ($this->hasDefault) {
            $array["default"] = $this->default;
        }
        if ($this->format !== null) {
            $array["format"] = $this->format;
        }
        if ($this->minLength !== null) {
            $array["minLength"] = $this->minLength;
        }
        if ($this->maxLength !== null) {
            $array["maxLength"] = $this->maxLength;
        }
        if ($this->minimum !== null) {
            $array["minimum"] = $this->minimum;
        }
        if ($this->maximum !== null) {
            $array["maximum"] = $this->maximum;
        }

        return $array;
    }
}