<?php

namespace App\Casts;

use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use InvalidArgumentException;

class Postcode implements CastsAttributes {
    /**
     * Cast the stored value from the database to a Postcode object.
     * @param mixed $value The raw database value.
     * @return Postcode|null
     */
    public function get($model, $key, $value, $attributes): ?\App\ValueObjects\Postcode {
        if (is_null($value)) {
            return null;
        }

        // The value from the database should already be sanitized, but we run it through
        // the Postcode constructor to create the Value Object.
        try {
            return new \App\ValueObjects\Postcode($value);
        } catch (InvalidArgumentException $e) {
            // Handle error (e.g., log it) if database data is unexpectedly invalid
            return null;
        }
    }

    /**
     * Prepare the Postcode object (or raw input) for storage in the database.
     * @param mixed $value The value provided by the user (string or Postcode object).
     * @return string|null
     */
    public function set($model, $key, $value, $attributes): ?string {
        if (is_null($value)) {
            return null;
        }

        if ($value instanceof \App\ValueObjects\Postcode) {
            return $value->getRaw();
        }

        try {
            return (new \App\ValueObjects\Postcode((string)$value))->getRaw();
        } catch (InvalidArgumentException $e) {
            return null;
        }
    }
}
