<?php

namespace App\Http\Controllers\Table;

use App\Models\Storage;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Blade;
use LibreNMS\Util\Html;
use LibreNMS\Util\Number;
use LibreNMS\Util\Url;

/**
 * @extends TableController<Storage>
 */
class StoragesController extends TableController
{
    protected ?string $model = Storage::class;

    protected array $default_sort = ['device_hostname' => 'asc', 'storage_descr' => 'asc'];

    protected function rules(): array
    {
        return [
            'status' => 'nullable|string',
        ];
    }

    protected function sortFields(Request $request): array
    {
        return [
            'device_hostname',
            'storage_descr',
            'storage_used',
            'storage_perc',
        ];
    }

    protected function searchFields(Request $request): array
    {
        return [
            'hostname',
            'display',
            'storage_descr',
        ];
    }

    protected function baseQuery(Request $request): Builder|\Illuminate\Database\Query\Builder
    {
        $this->authorize('viewAny', Storage::class);

        return Storage::query()
            ->hasAccess($request->user())
            ->when($request->input('searchPhrase'), fn ($q) => $q->leftJoin('devices', 'devices.device_id', '=', 'storage.device_id'))
            ->withAggregate('device', 'hostname')
            ->when($request->input('status') == 'warning', function ($q): void {
                // show only entries in warning state
                $q->where('storage_perc', '>', 0)
                    ->whereColumn('storage_perc', '>=', 'storage_perc_warn');
            });
    }

    /**
     * @param  Storage  $model
     * @return array<string, scalar>
     */
    public function formatItem(Model $model): array
    {
        $hostname = Blade::render('<x-device-link :device="$device" />', ['device' => $model->device]);
        $descr = htmlentities((string) $model->storage_descr);
        $graph_array = [
            'type' => 'storage_usage',
            'popup_title' => htmlentities(strip_tags($model->device?->displayName() . ': ' . $model->storage_descr)),
            'id' => $model->storage_id,
            'from' => '-1d',
            'height' => 20,
            'width' => 80,
        ];
        $mini_graph = Url::graphPopup($graph_array);
        $used = $this->usageBar($model, $graph_array);

        if (\Request::input('view') == 'graphs') {
            $row = Html::graphRow(array_replace($graph_array, ['height' => 100, 'width' => 216]));
            $hostname = '<div class="tw:border-b tw:border-gray-200">' . $hostname . '</div><div style="width:216px;margin-left:auto;border-top:">' . $row[0] . '</div>';
            $descr = '<div class="tw:border-b tw:border-gray-200">' . $descr . '</div><div style="width:216px">' . $row[1] . '</div>';
            $mini_graph = '<div class="tw:border-b tw:border-gray-200" style="min-height:20px">' . $mini_graph . '</div><div style="width:216px">' . $row[2] . '</div>';
            $used = '<div class="tw:border-b tw:border-gray-200">' . $used . '</div><div style="width:216px">' . $row[3] . '</div>';
        }

        return [
            'device_hostname' => $hostname,
            'storage_descr' => $descr,
            'graph' => $mini_graph,
            'storage_used' => $used,
            'storage_perc' => round($model->storage_perc) . '%',
        ];
    }

    private function usageBar(Storage $storage, array $graph_array): string
    {
        $storage_size = Number::formatBi($storage->storage_size);
        $left_text = Number::formatBi($storage->storage_used) . ' / ' . $storage_size;
        $storage_free = Number::formatBi($storage->storage_free);
        $right_text = $storage_free !== $storage_size ? $storage_free : null;
        $bar = Html::percentageBar(400, 10, $storage->storage_perc, $left_text, $right_text, $storage->storage_perc_warn);

        return Url::graphPopup($graph_array, $bar);
    }

    /**
     * Get headers for CSV export
     */
    protected function getExportHeaders(): array
    {
        return [
            'Device Hostname',
            'Storage',
            'Used',
            'Free',
        ];
    }

    /**
     * Format a row for CSV export
     *
     * @param  Storage  $storage
     * @return array<scalar>
     */
    protected function formatExportRow(Model $storage): array
    {
        return [
            $storage->device ? $storage->device->displayName() : '',
            $storage->storage_descr,
            Number::formatBi($storage->storage_used),
            Number::formatBi($storage->storage_free),
        ];
    }
}
