<?php

namespace App\Http\Controllers\Admin;

/*
 * BlockLayoutWizardController — мастер генерации макетов блоков.
 *
 * Шаг 1: пользователь вставляет HTML-фрагмент секции.
 * Шаг 2: парсер определяет поля, показывает черновик Blade и таблицу полей для правки.
 * Шаг 3: сохраняем два файла и редиректим на создание блока.
 *
 * Генерируемые файлы:
 *   app/Support/layouts/{name}.php              — определение полей для реестра
 *   resources/views/blocks/{name}.blade.php     — Blade-шаблон для рендера
 */

use App\Http\Controllers\Controller;
use App\Support\BlockLayoutParser;
use App\Support\BlockLayoutRegistry;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class BlockLayoutWizardController extends Controller
{
    // Шаг 1: форма ввода HTML
    public function index(): View
    {
        return view('admin.blocks.wizard', ['parsed' => null]);
    }

    // Шаг 2: парсим HTML, показываем обнаруженные поля и черновик Blade
    public function analyze(Request $request): View
    {
        $request->validate([
            'layout_name'  => 'required|string|max:100|regex:/^[a-z0-9_]+$/',
            'layout_title' => 'required|string|max:255',
            'html'         => 'required|string',
        ]);

        $parsed = (new BlockLayoutParser)->parse($request->input('html'));

        return view('admin.blocks.wizard', [
            'parsed'        => $parsed,
            'layout_name'   => $request->input('layout_name'),
            'layout_title'  => $request->input('layout_title'),
            'original_html' => $request->input('html'),
        ]);
    }

    // Шаг 3: сохраняем файлы макета и Blade-шаблона
    public function generate(Request $request): RedirectResponse
    {
        $request->validate([
            'layout_name'  => 'required|string|max:100|regex:/^[a-z0-9_]+$/',
            'layout_title' => 'required|string|max:255',
            'blade'        => 'required|string',
        ]);

        $name  = $request->input('layout_name');
        $title = $request->input('layout_title');

        // Защита: не перезаписываем встроенные макеты
        if (isset(BlockLayoutRegistry::all()[$name]) && !file_exists(app_path("Support/layouts/{$name}.php"))) {
            return back()->withInput()->withErrors(['layout_name' => 'Такое имя уже занято встроенным макетом.']);
        }

        // Собираем определение полей из submitted-данных формы
        $fields = $this->buildFieldsFromRequest($request);

        // Сохраняем app/Support/layouts/{name}.php
        $layoutPhp = $this->renderLayoutPhp($title, $fields);
        file_put_contents(app_path("Support/layouts/{$name}.php"), $layoutPhp);

        // Сохраняем resources/views/blocks/{name}.blade.php
        $bladeContent = "{{-- Blade-шаблон блока «{$title}». Сгенерирован мастером макетов. --}}\n"
            . trim($request->input('blade')) . "\n";
        file_put_contents(resource_path("views/blocks/{$name}.blade.php"), $bladeContent);

        // Сбрасываем кеш скомпилированных вьюх
        array_map('unlink', glob(storage_path('framework/views/*.php')));

        return redirect()->route('admin.blocks.create')
            ->with('success', "Макет «{$title}» создан. Теперь создайте блок на его основе.");
    }

    // Собирает поля из multipart-данных формы шага 2
    private function buildFieldsFromRequest(Request $request): array
    {
        $isRepeater    = (bool) $request->input('is_repeater', false);
        $rawFlatFields = $request->input('flat_fields', []);

        $flatFields = array_values(array_filter(
            array_map(fn($f) => [
                'name'  => trim($f['name']  ?? ''),
                'label' => trim($f['label'] ?? ''),
                'type'  => $f['type'] ?? 'text',
            ], $rawFlatFields),
            fn($f) => $f['name'] !== ''
        ));

        if (!$isRepeater) {
            return $flatFields;
        }

        // Repeater: плоские поля перед/после + repeater-поле
        $subRaw = $request->input('sub_fields', []);
        $subFields = array_values(array_filter(
            array_map(fn($f) => [
                'name'  => trim($f['name']  ?? ''),
                'label' => trim($f['label'] ?? ''),
                'type'  => $f['type'] ?? 'text',
            ], $subRaw),
            fn($f) => $f['name'] !== ''
        ));

        $repeaterField = [
            'name'       => trim($request->input('repeater_name', 'items')),
            'label'      => trim($request->input('repeater_label', 'Элементы')),
            'type'       => 'repeater',
            'sub_fields' => $subFields,
        ];

        // Плоские поля (если есть) идут перед repeater
        return array_merge($flatFields, [$repeaterField]);
    }

    // Рендерит PHP-файл определения макета
    private function renderLayoutPhp(string $title, array $fields): string
    {
        $fieldsExport = $this->varExportPretty($fields, 1);

        return <<<PHP
<?php

// Сгенерирован мастером макетов tocha_app
return [
    'title'  => {$this->exportStr($title)},
    'fields' => {$fieldsExport},
];
PHP;
    }

    // Аккуратный var_export с отступами вместо стандартного
    private function varExportPretty(mixed $value, int $depth = 0): string
    {
        $pad = str_repeat('    ', $depth);
        $pad1 = str_repeat('    ', $depth + 1);

        if (is_string($value)) {
            return $this->exportStr($value);
        }

        if (!is_array($value)) {
            return var_export($value, true);
        }

        if (empty($value)) {
            return '[]';
        }

        $isList = array_keys($value) === range(0, count($value) - 1);
        $lines  = [];

        foreach ($value as $k => $v) {
            $key     = $isList ? '' : $this->exportStr((string) $k) . ' => ';
            $lines[] = $pad1 . $key . $this->varExportPretty($v, $depth + 1);
        }

        return "[\n" . implode(",\n", $lines) . ",\n{$pad}]";
    }

    private function exportStr(string $s): string
    {
        return "'" . addcslashes($s, "'\\") . "'";
    }
}
