<?php

namespace App\Support;

class Address
{
    /* @var ?string */
    public ?string $street;
    
    /* @var ?string */
    public ?string $unit;
    
    /* @var ?string */
    public ?string $city;
    
    /* @var ?string */
    public ?string $state;
    
    /* @var ?string */
    public ?string $postalCode;
    
    /* @var ?string */
    public ?string $country;

    /**
     * The Address helpser constructor.
     *
     * @since 1.0.0
     *
     * @param array $inputs
     *
     * @return void
     */
    public function __construct(array $inputs): void
    {
        $this->processAddress($inputs);
    }

    /**
     * Process user inputs to our Address object.
     *
     * @since 1.0.0
     *
     * @param array $inputs
     *
     * @return void
     */
    public function processAddress(array $inputs): void
    {
        // TODO: attempt to determine how the address is formulated
        //       could be just numerical indexed, or could be
        //       named keys but not sure of names

        $this->street = $this->resolveStreet($inputs);
    }

    /*
    |--------------------------------------------------------------------------
    | Helpers
    |--------------------------------------------------------------------------
    |
    */

    /**
     * Attempt to determine what the street address
     * is in the given data.
     *
     * @since 1.0.0
     *
     * @param array $inputs
     *
     * @return string|null
     */
    private function resolveStreet(array $inputs): ?string
    {
        $street = '';
        if (array_key_exists('street', $inputs)) {
            $street = $inputs['street'];
        } elseif (array_key_exists('street_1', $inputs)) {
            $street = $inputs['street_1'];
        } elseif (array_key_exists('street_address', $inputs)) {
            $street = $inputs['street_address'];
        } elseif (array_key_exists('line_1', $inputs)) {
            $street = $inputs['line_1'];
        } elseif (! empty($inputs[0])) {
            $street = $inputs[0];
        } elseif (array_key_exists('0', $inputs)) {
            $street = $inputs['0'];
        }

        if (empty($street)) {
            $street = null;
        }

        return $street;
    }

    /**
     * Attempt to determine what the street address
     * unit is in the given data.
     *
     * @since 1.0.0
     *
     * @param array $inputs
     *
     * @return string|null
     */
    private function resolveUnit(array $inputs): ?string
    {
        $unit = null;
        if (array_key_exists('unit', $inputs)) {
            $unit = $inputs['unit'];
        } elseif (array_key_exists('street_2', $inputs)) {
            $unit = $inputs['street_2'];
        } elseif (array_key_exists('line_2', $inputs)) {
            $unit = $inputs['line_2'];
        } elseif (! empty($inputs[1])) {
            $unit = $inputs[1];
        } elseif (array_key_exists('1', $inputs)) {
            $unit = $inputs['1'];
        }

        if (empty($unit)) {
            $unit = null;
        }

        return $unit;
    }

    /**
     * Attempt to determine what the city is in the given data.
     *
     * @since 1.0.0
     *
     * @param array $inputs
     *
     * @return string|null
     */
    private function resolveCity(array $inputs): ?string
    {
        $city = '';
        if (array_key_exists('city', $inputs)) {
            $city = $inputs['city'];
        } elseif (array_key_exists(2, $inputs)) {
            $city = $inputs[2];
        } elseif (array_key_exists('2', $inputs)) {
            $city = $inputs['2'];
        }

        if (empty($city)) {
            $city = null;
        }

        return $city;
    }

    /**
     * Attempt to determine what the state is in the given data.
     *
     * @since 1.0.0
     *
     * @param array $inputs
     *
     * @return string|null
     */
    private function resolveState(array $inputs): ?string
    {
        $numericKey = 3;
        if (empty($this->unit)) {
            $numericKey--;
        }

        $state = '';
        if (array_key_exists('state', $inputs)) {
            $state = $inputs['state'];
        } elseif (array_key_exists('st', $inputs)) {
            $state = $inputs['st'];
        } elseif (array_key_exists($numericKey, $inputs)) {
            $state = $inputs[$numericKey];
        } elseif (array_key_exists("$numericKey", $inputs)) {
            $state = $inputs["$numericKey"];
        }

        if (empty($state)) {
            $state = null;
        }

        return $state;
    }

    /**
     * Attempt to determine what the postal code is in the given data.
     *
     * @since 1.0.0
     *
     * @param array $inputs
     *
     * @return string|null
     */
    private function resolvePostalCode(array $inputs): ?string
    {
        $numericKey = 4;
        if (empty($this->unit)) {
            $numericKey--;
        }

        $postalCode = '';
        if (array_key_exists('postal_code', $inputs)) {
            $postalCode = $inputs['postal_code'];
        } elseif (array_key_exists('postalCode', $inputs)) {
            $postalCode = $inputs['postalCode'];
        } elseif (array_key_exists('postal', $inputs)) {
            $postalCode = $inputs['postal'];
        } elseif (array_key_exists('zipcode', $inputs)) {
            $postalCode = $inputs['zipcode'];
        } elseif (array_key_exists('zip_code', $inputs)) {
            $postalCode = $inputs['zip_code'];
        } elseif (array_key_exists('zipCode', $inputs)) {
            $postalCode = $inputs['zipCode'];
        } elseif (array_key_exists('zip', $inputs)) {
            $postalCode = $inputs['zip'];
        } elseif (array_key_exists($numericKey, $inputs)) {
            $postalCode = $inputs[$numericKey];
        } elseif (array_key_exists("$numericKey", $inputs)) {
            $postalCode = $inputs["$numericKey"];
        }

        if (empty($postalCode)) {
            $postalCode = null;
        }

        return $postalCode;
    }

    /**
     * Attempt to determine what the country is in the given data.
     *
     * @since 1.0.0
     *
     * @param array $inputs
     *
     * @return string|null
     */
    private function resolveCountry(array $inputs): ?string
    {
        $numericKey = 5;
        if (empty($this->unit)) {
            $numericKey--;
        }

        $country = '';
        if (array_key_exists('country', $inputs)) {
            $country = $inputs['country'];
        } elseif (array_key_exists('st', $inputs)) {
            $country = $inputs['st'];
        } elseif (array_key_exists($numericKey, $inputs)) {
            $country = $inputs[$numericKey];
        } elseif (array_key_exists("$numericKey", $inputs)) {
            $country = $inputs["$numericKey"];
        }

        if (empty($country)) {
            $country = null;
        }

        return $country;
    }

    /**
     * Magic method to convert this object to a string.
     *
     * @since 1.0.0
     *
     * @return string
     */
    public function __toString(): string
    {
        $fullAddress = $this->street;
        if (! empty($this->unit)) {
            $fullAddress .= " {$this->unit}";
        }

        if (! empty($this->city)) {
            $fullAddress .= ", {$this->city}";
        }

        if (! empty($this->state)) {
            $fullAddress .= ", {$this->state}";
        }

        if (! empty($this->postalCode)) {
            $fullAddress .= $this->postalCode;
        }

        if (! empty($this->country)) {
            $fullAddress .= ", {$this->country}";
        }



        return $fullAddress;
    }
}
