<?php

namespace App\Http\Controllers\Admin;

/*
 * BlockAdminController — управление блоками контента.
 *
 * Каждый блок привязан к макету (BlockLayoutRegistry), пользователь заполняет
 * структурированные поля — никакой вёрстки в руках редактора.
 * Данные хранятся в JSON-поле data, рендеринг — через Blade-шаблон blocks/{layout}.
 *
 * Изображения: загружаются через ImageUploadService, хранятся в storage/public/blocks/,
 * ресайзятся по размерам из определения поля макета, конвертируются в WebP.
 */

use App\Http\Controllers\Controller;
use App\Models\Block;
use App\Services\ImageUploadService;
use App\Support\BlockLayoutRegistry;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\View\View;

class BlockAdminController extends Controller
{
    public function __construct(private ImageUploadService $images) {}

    public function index(): View
    {
        $blocks = Block::orderBy('title')->get();

        return view('admin.blocks.index', compact('blocks'));
    }

    public function create(): View
    {
        return view('admin.blocks.form', [
            'block' => new Block,
            'layouts' => BlockLayoutRegistry::all(),
            'layoutDef' => null,
        ]);
    }

    public function store(Request $request): RedirectResponse
    {
        $validated = $request->validate([
            'name' => 'required|string|max:100|regex:/^[a-z0-9_]+$/|unique:blocks,name',
            'title' => 'required|string|max:255',
            'layout' => 'required|string|in:'.implode(',', BlockLayoutRegistry::keys()),
            'is_active' => 'nullable|boolean',
        ]);

        $validated['is_active'] = $request->boolean('is_active');
        $validated['data'] = $this->buildData($request, $validated['layout'], null);

        Block::create($validated);

        return redirect()->route('admin.blocks.index')
            ->with('success', 'Блок «'.$validated['title'].'» создан.');
    }

    public function edit(Block $block): View
    {
        return view('admin.blocks.form', [
            'block' => $block,
            'layouts' => BlockLayoutRegistry::all(),
            'layoutDef' => BlockLayoutRegistry::get($block->layout ?? ''),
        ]);
    }

    public function update(Request $request, Block $block): RedirectResponse
    {
        $validated = $request->validate([
            'title' => 'required|string|max:255',
            'is_active' => 'nullable|boolean',
        ]);

        $validated['is_active'] = $request->boolean('is_active');
        $validated['data'] = $this->buildData($request, $block->layout, $block->data ?? []);

        $block->update($validated);

        Cache::forget('block.'.$block->name);
        // Cache::tags() не поддерживается database-драйвером — сбрасываем секции всех страниц явно
        foreach (['home', 'services', 'contacts', 'privacy', 'offer'] as $slug) {
            Cache::forget('page_sections.'.$slug);
            Cache::forget('page.'.$slug);
        }

        return redirect()->route('admin.blocks.index')
            ->with('success', 'Блок «'.$block->title.'» обновлён.');
    }

    public function destroy(Block $block): RedirectResponse
    {
        Cache::forget('block.'.$block->name);
        $title = $block->title;
        $block->delete();

        return redirect()->route('admin.blocks.index')
            ->with('success', 'Блок «'.$title.'» удалён.');
    }

    // ── Сборка data: текстовые поля + загруженные изображения ────────────

    private function buildData(Request $request, ?string $layoutKey, ?array $oldData): array
    {
        $layoutDef = $layoutKey ? BlockLayoutRegistry::get($layoutKey) : null;

        if (! $layoutDef) {
            return [];
        }

        $raw = $request->input('data', []);
        $uploads = $request->file('uploads', []);
        $result = [];

        foreach ($layoutDef['fields'] as $field) {
            $name = $field['name'];

            if ($field['type'] === 'repeater') {
                $rows = array_values($raw[$name] ?? []);
                $oldRows = $oldData[$name] ?? [];

                $result[$name] = array_map(function (array $row, int $i) use ($field, $uploads, $name, $oldRows, $layoutKey) {
                    $clean = [];
                    foreach ($field['sub_fields'] as $sub) {
                        $subName = $sub['name'];
                        $oldVal = $oldRows[$i][$subName] ?? '';
                        $uploadFile = data_get($uploads, "{$name}.{$i}.{$subName}");

                        if ($sub['type'] === 'image' && $uploadFile?->isValid()) {
                            $this->images->delete($oldVal);
                            $clean[$subName] = $this->images->store($uploadFile, $layoutKey, $sub);
                        } else {
                            $clean[$subName] = $sub['type'] === 'image'
                                ? ($row[$subName] ?? $oldVal)     // hidden input сохраняет старый путь
                                : trim($row[$subName] ?? '');
                        }
                    }

                    return $clean;
                }, $rows, array_keys($rows));

            } elseif ($field['type'] === 'checkbox') {
                // Булев флаг: hidden-поле даёт "0", чекбокс при отмеченном даёт "1"
                $result[$name] = (bool) ($raw[$name] ?? false);

            } elseif (in_array($field['type'], ['cars_picker', 'makes_picker'])) {
                // Мультиселект — хранится как plain array значений
                $result[$name] = array_values(array_filter((array) ($raw[$name] ?? [])));

            } elseif ($field['type'] === 'reviews_picker') {
                // Мультиселект отзывов — хранится как plain array целочисленных ID
                $result[$name] = array_values(array_map('intval', array_filter((array) ($raw[$name] ?? []))));

            } elseif ($field['type'] === 'services_picker') {
                // Мультиселект услуг — plain array целочисленных ID
                $result[$name] = array_values(array_map('intval', array_filter((array) ($raw[$name] ?? []))));

            } elseif ($field['type'] === 'image') {
                $oldVal = $oldData[$name] ?? '';
                $uploadFile = data_get($uploads, $name);

                if ($uploadFile?->isValid()) {
                    $this->images->delete($oldVal);
                    $result[$name] = $this->images->store($uploadFile, $layoutKey, $field);
                } else {
                    // Сохраняем путь из hidden-input (не трогаем старый файл)
                    $result[$name] = $raw[$name] ?? $oldVal;
                }

            } else {
                $result[$name] = trim($raw[$name] ?? '');
            }
        }

        return $result;
    }
}
