<?php

namespace App\Http\Controllers\Api\V1;

use App\Http\Controllers\Controller;
use App\Services\Extension\ExtensionVerificationService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use RuntimeException;

class ExtensionController extends Controller
{
    /** @var array<string,mixed>|null */
    private static ?array $dataset = null;

    public function __construct(private readonly ExtensionVerificationService $verifier)
    {
    }

    public function verify(Request $request): JsonResponse
    {
        $token = trim((string) $request->header('X-Extension-Token', ''));
        $expected = config('dewemoji.public_access.extension_ids', []);
        $ok = $this->verifier->verifyToken($token, is_array($expected) ? $expected : []);

        return response()->json([
            'ok' => $ok,
            'verified' => $ok,
        ], $ok ? 200 : 403);
    }

    public function search(Request $request): JsonResponse
    {
        $token = trim((string) $request->header('X-Extension-Token', ''));
        $expected = config('dewemoji.public_access.extension_ids', []);
        $ok = $this->verifier->verifyToken($token, is_array($expected) ? $expected : []);
        if (!$ok) {
            return response()->json(['ok' => false, 'error' => 'extension_unverified'], 403);
        }

        try {
            $data = $this->loadData();
        } catch (RuntimeException $e) {
            return response()->json([
                'ok' => false,
                'error' => 'data_load_failed',
                'message' => $e->getMessage(),
            ], 500);
        }

        $items = $data['emojis'] ?? [];
        $q = trim((string) ($request->query('q', $request->query('query', ''))));
        $category = $this->normalizeCategoryFilter((string) $request->query('category', ''));
        $subSlug = $this->slugify((string) $request->query('subcategory', ''));
        $page = max((int) $request->query('page', 1), 1);

        $defaultLimit = max((int) config('dewemoji.pagination.default_limit', 20), 1);
        $maxLimit = max((int) config('dewemoji.pagination.free_max_limit', 20), 1);
        $limit = min(max((int) $request->query('limit', $defaultLimit), 1), $maxLimit);

        $filtered = $this->filterItems($items, $q, $category, $subSlug);
        $total = count($filtered);
        $offset = ($page - 1) * $limit;
        $pageItems = array_slice($filtered, $offset, $limit);

        return response()->json([
            'ok' => true,
            'items' => array_map(fn (array $item): array => $this->transformItem($item), $pageItems),
            'total' => $total,
            'page' => $page,
            'limit' => $limit,
            'plan' => 'free',
        ]);
    }

    /**
     * @return array<string,mixed>
     */
    private function loadData(): array
    {
        if (self::$dataset !== null) {
            return self::$dataset;
        }

        $path = (string) config('dewemoji.data_path');
        if (!is_file($path)) {
            throw new RuntimeException('Emoji dataset file was not found at: '.$path);
        }

        $raw = file_get_contents($path);
        if ($raw === false) {
            throw new RuntimeException('Emoji dataset file could not be read.');
        }

        $decoded = json_decode($raw, true);
        if (!is_array($decoded)) {
            throw new RuntimeException('Emoji dataset JSON is invalid.');
        }

        self::$dataset = $decoded;
        return self::$dataset;
    }

    private function normalizeCategoryFilter(string $category): string
    {
        $value = strtolower(trim($category));
        if ($value === '' || $value === 'all') {
            return '';
        }

        $map = [
            'all' => 'all',
            'smileys' => 'Smileys & Emotion',
            'people' => 'People & Body',
            'animals' => 'Animals & Nature',
            'food' => 'Food & Drink',
            'travel' => 'Travel & Places',
            'activities' => 'Activities',
            'objects' => 'Objects',
            'symbols' => 'Symbols',
            'flags' => 'Flags',
        ];
        return $map[$value] ?? $category;
    }

    private function slugify(string $text): string
    {
        $value = strtolower(trim($text));
        $value = str_replace('&', 'and', $value);
        $value = preg_replace('/[^a-z0-9]+/', '-', $value) ?? '';
        return trim($value, '-');
    }

    /**
     * @param array<int,array<string,mixed>> $items
     * @return array<int,array<string,mixed>>
     */
    private function filterItems(array $items, string $q, string $category, string $subSlug): array
    {
        return array_values(array_filter($items, function (array $item) use ($q, $category, $subSlug): bool {
            $itemCategory = trim((string) ($item['category'] ?? ''));
            $itemSubcategory = trim((string) ($item['subcategory'] ?? ''));

            if ($category !== '' && strcasecmp($itemCategory, $category) !== 0) {
                return false;
            }
            if ($subSlug !== '' && $this->slugify($itemSubcategory) !== $subSlug) {
                return false;
            }
            if ($q === '') {
                return true;
            }

            $haystack = strtolower(implode(' ', [
                (string) ($item['emoji'] ?? ''),
                (string) ($item['name'] ?? ''),
                (string) ($item['slug'] ?? ''),
                $itemCategory,
                $itemSubcategory,
                implode(' ', $item['keywords_en'] ?? []),
                implode(' ', $item['keywords_id'] ?? []),
                implode(' ', $item['aliases'] ?? []),
                implode(' ', $item['shortcodes'] ?? []),
                implode(' ', $item['alt_shortcodes'] ?? []),
                implode(' ', $item['intent_tags'] ?? []),
            ]));

            $tokens = preg_split('/\s+/', strtolower($q)) ?: [];
            foreach ($tokens as $token) {
                if ($token === '') {
                    continue;
                }
                if (!str_contains($haystack, $token)) {
                    return false;
                }
            }
            return true;
        }));
    }

    /**
     * @param array<string,mixed> $item
     * @return array<string,mixed>
     */
    private function transformItem(array $item): array
    {
        return [
            'emoji' => (string) ($item['emoji'] ?? ''),
            'name' => (string) ($item['name'] ?? ''),
            'slug' => (string) ($item['slug'] ?? ''),
            'category' => (string) ($item['category'] ?? ''),
            'subcategory' => (string) ($item['subcategory'] ?? ''),
            'supports_skin_tone' => (bool) ($item['supports_skin_tone'] ?? false),
            'summary' => $this->summary((string) ($item['description'] ?? ''), 150),
        ];
    }

    private function summary(string $text, int $max): string
    {
        $text = trim(preg_replace('/\s+/', ' ', strip_tags($text)) ?? '');
        if (mb_strlen($text) <= $max) {
            return $text;
        }

        return rtrim(mb_substr($text, 0, $max - 1), " ,.;:-").'…';
    }
}
