@use "sass:string";
@use "sass:math";
@use "sass:map";
@use "sass:list";
@use "sass:meta";
@use "../config/constants" as config-constants;
@use "./strings" as fn-strings;

@function to-number($value) {
    @if meta.type-of($value) == "number" {
        @return $value;
    } @else if meta.type-of($value) != "string" {
        @error "Value for `number` should be a number or a string.";
        @return $value;
    }

    $val: string.unquote(fn-strings.strip-quotes($value));

    $result: 0;
    $digits: 0;
    $minus: string.slice($value, 1, 1) == "-";
    $numbers: (
        "0": 0,
        "1": 1,
        "2": 2,
        "3": 3,
        "4": 4,
        "5": 5,
        "6": 6,
        "7": 7,
        "8": 8,
        "9": 9,
    );
    $number-chars-end: 0;

    @for $i from if($minus, 2, 1) through string.length($val) {
        $character: string.slice($val, $i, $i);

        @if list.index(map.keys($numbers), $character) or $character == "." {
            $number-chars-end: $i;

            @if $character == "." {
                $digits: 1;
            } @else if $digits == 0 {
                $result: $result * 10 + map.get($numbers, $character);
            } @else {
                $digits: $digits * 10;
                $result: $result + map.get($numbers, $character) / $digits;
            }
        } @else {
            // Non-numeric character found - check for unit
            $rest: string.slice($val, $i);

            // Look for valid unit
            @each $unit in config-constants.$units {
                @if $rest == $unit {
                    @return if($minus, -$result, $result) + string.unquote($unit);
                }
            }

            // No valid unit - return null for non-numeric strings
            @if $i == if($minus, 2, 1) {
                @return null; // First char is non-numeric
            }

            // Otherwise return just the parsed number
            @return if($minus, -$result, $result);
        }
    }

    @return if($minus, -$result, $result);
}
