<?php

namespace App\Casts;

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

class FileSize implements CastsAttributes {
    /**
     * Cast the given value from the database.
     *
     * @param array<string, mixed> $attributes
     */
    public function get(Model $model, string $key, mixed $value, array $attributes): string {
        $bytes = (int)$value;
        $units = ['B', 'KB', 'MB', 'GB', 'TB'];

        // Handle zero bytes case
        if ($bytes === 0) {
            return '0 B';
        }

        // Calculate the exponent (power of 1024)
        $power = floor(log($bytes, 1024));

        // Ensure we don't exceed the defined units
        if ($power < 0 || $power >= count($units)) {
            // Fallback to bytes if calculation is unexpected
            return $bytes . ' B';
        }

        // Get the size in the correct unit and round to two decimal places
        $size = round($bytes / pow(1024, $power), 2);

        // Return the formatted string
        return $size . ' ' . $units[$power];
    }

    /**
     * Prepare the given value for storage in the database.
     *
     * @param array<string, mixed> $attributes
     */
    public function set(Model $model, string $key, mixed $value, array $attributes): int {
        // Ensure that any value being set is stored as an integer (bytes)
        if (!is_numeric($value)) {
            throw new InvalidArgumentException("The {$key} attribute must be an integer (bytes).");
        }

        return (int)$value;
    }
}