<?php

declare(strict_types=1);

namespace Tricks\NovaTools\Nova;

use Illuminate\Database\Eloquent\Model;
use Laravel\Nova\Fields\Field;
use Laravel\Nova\Fields\Heading;
use Laravel\Nova\Fields\Repeater;
use Laravel\Nova\Http\Requests\NovaRequest;
use Laravel\Nova\Panel;

final class DynamicContentPanel extends Panel
{
    /**
     * @param  array<int,class-string>  $fields
     */
    public function __construct(
        NovaRequest $request,
        ?Model $resource,
        array $fields,
        string $name = 'Inhalt',
        string $attribute = 'content',
    ) {
        $callback = [];

        if ($request->isFormRequest()) {
            $callback = fn (): array => $this->prepareFormRequest($fields, $attribute);
        } elseif ($request->isResourceDetailRequest()) {
            $callback = fn (): array => $this->prepareDetailRequest($resource, $fields, $attribute);
        }

        parent::__construct($name, $callback);
    }

    /**
     * @param  array<int,class-string>  $fields
     * @return array<int, Repeater>
     */
    public function prepareFormRequest(array $fields, string $attribute): array
    {
        $repeatables = [];
        foreach ($fields as $field) {
            $repeatable = $field::make();
            if ($repeatable instanceof Repeater\Repeatable === false) {
                continue;
            }
            $repeatables[] = $repeatable;
        }

        return [
            Repeater::make('Inhalt', $attribute)
                ->repeatables($repeatables)
                ->rules([
                    'required',
                ]),
        ];

    }

    /**
     * @param  array<int,class-string>  $fields
     * @return array<int, Field>
     */
    public function prepareDetailRequest(?Model $resource, array $fields, string $attribute): array
    {
        $blocks = [];

        if (is_null($resource)) {
            return $blocks;
        }
        $rawAttribute = $resource->{$attribute};
        if (is_array($rawAttribute) === false) {
            return $blocks;
        }

        /** @var array<string,class-string> $classes */
        $classes = [];
        foreach ($fields as $field) {
            $classes[$field::key()] = $field;
        }

        foreach ($rawAttribute as $data) {
            if (is_array($data) === false) {
                continue;
            }
            $type = $data['type'];
            if (is_string($type) === false) {
                continue;
            }
            $fields = $data['fields'] ?? [];
            $class = $classes[$type];

            $heading = $class::label() ?? $type;
            if (is_string($heading) === false) {
                continue;
            }
            $blocks[] = Heading::make($heading);
            $displayFields = $class::displayFields($resource, $fields);
            if (is_array($displayFields) === false) {
                continue;
            }
            foreach ($displayFields as $block) {
                if ($block instanceof Field === false) {
                    continue;
                }
                $blocks[] = $block;
            }
        }

        return $blocks;
    }
}
