<?php

declare(strict_types=1);

namespace App\Http\Controllers\Api\V1;

use App\Http\Controllers\Controller;
use App\Models\Manual;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;

class ManualController extends Controller
{
    public function index(Request $request): JsonResponse
    {
        $version = $request->query('version');
        $q = Manual::query()->where('is_published', true);
        if ($version) {
            $q->where('version', $version);
        }
        $items = $q->orderBy('order_sort')->orderBy('title')->get();

        // Build tree
        $byId = [];
        foreach ($items as $it) {
            $byId[$it->id] = [
                'id' => $it->id,
                'version' => $it->version,
                'slug' => $it->slug,
                'title' => $it->title,
                'parent_id' => $it->parent_id,
                'order_sort' => $it->order_sort,
                'children' => [],
            ];
        }
        $tree = [];
        foreach ($byId as $id => &$node) {
            if ($node['parent_id'] && isset($byId[$node['parent_id']])) {
                $byId[$node['parent_id']]['children'][] = &$node;
            } else {
                $tree[] = &$node;
            }
        }
        unset($node);

        return response()->json([
            'data' => array_values($tree),
            'flat' => array_values(array_map(fn ($v) => [
                'id' => $v['id'], 'version' => $v['version'], 'slug' => $v['slug'],
                'title' => $v['title'], 'parent_id' => $v['parent_id'],
                'order_sort' => $v['order_sort'],
            ], $byId)),
        ]);
    }

    public function show(string $version, string $slug): JsonResponse
    {
        $manual = Manual::where('version', $version)
            ->where('slug', $slug)
            ->where('is_published', true)
            ->firstOrFail();

        // Previous/next by order_sort within version
        $siblings = Manual::where('version', $version)
            ->where('is_published', true)
            ->orderBy('order_sort')
            ->get(['id', 'slug', 'title', 'order_sort']);
        $idx = $siblings->search(fn ($s) => $s->id === $manual->id);
        $prev = $idx > 0 ? $siblings[$idx - 1] : null;
        $next = $idx !== false && $idx < $siblings->count() - 1 ? $siblings[$idx + 1] : null;

        return response()->json([
            'data' => $manual,
            'prev' => $prev,
            'next' => $next,
        ]);
    }

    public function store(Request $request): JsonResponse
    {
        $this->authorizePerm($request, 'manuals.create');

        $tenantId = app('currentTenant')->getKey();
        $data = $request->validate([
            'version' => ['required', 'string', 'max:20'],
            'slug' => ['required', 'string', 'max:191'],
            'title' => ['required', 'string', 'max:255'],
            'parent_id' => ['nullable', 'string'],
            'content' => ['nullable', 'string'],
            'order_sort' => ['nullable', 'integer'],
            'is_published' => ['nullable', 'boolean'],
        ]);
        $data['tenant_id'] = $tenantId;
        $data['order_sort'] = $data['order_sort'] ?? 0;
        $data['is_published'] = $data['is_published'] ?? true;

        $manual = Manual::create($data);

        return response()->json(['data' => $manual], 201);
    }

    public function update(Request $request, string $id): JsonResponse
    {
        $this->authorizePerm($request, 'manuals.update');
        $manual = Manual::findOrFail($id);

        $data = $request->validate([
            'version' => ['sometimes', 'string', 'max:20'],
            'slug' => ['sometimes', 'string', 'max:191'],
            'title' => ['sometimes', 'string', 'max:255'],
            'parent_id' => ['nullable', 'string'],
            'content' => ['nullable', 'string'],
            'order_sort' => ['nullable', 'integer'],
            'is_published' => ['nullable', 'boolean'],
        ]);

        $manual->update($data);

        return response()->json(['data' => $manual]);
    }

    public function destroy(Request $request, string $id): JsonResponse
    {
        $this->authorizePerm($request, 'manuals.delete');
        $manual = Manual::findOrFail($id);
        $manual->delete();

        return response()->json(['data' => ['deleted' => true]]);
    }

    private function authorizePerm(Request $request, string $perm): void
    {
        $user = $request->user();
        if (! $user) {
            throw new AccessDeniedHttpException('UNAUTH');
        }
        if ($user->hasRole('super_admin') || $user->hasRole('tenant_admin')) {
            return;
        }
        if (! $user->can($perm)) {
            throw new AccessDeniedHttpException("PERM_DENIED:{$perm}");
        }
    }
}
