<?php

namespace App\Http\Controllers\Api\V1;

use App\Http\Controllers\Controller;
use App\Models\UserKeyword;
use App\Services\Auth\ApiKeyService;
use App\Services\Keywords\KeywordQuotaService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class UserKeywordController extends Controller
{
    public function __construct(
        private readonly ApiKeyService $keys,
        private readonly KeywordQuotaService $keywordQuota
    ) {}

    private function ensureUser(Request $request): ?array
    {
        $user = $this->keys->resolveUser($request);
        if (! $user) {
            return ['error' => 'unauthorized', 'status' => 401];
        }

        return ['user' => $user];
    }

    public function index(Request $request): JsonResponse
    {
        $check = $this->ensureUser($request);
        if (! isset($check['user'])) {
            return response()->json(['ok' => false, 'error' => $check['error']], $check['status']);
        }

        $user = $check['user'];
        $items = UserKeyword::where('user_id', $user->id)
            ->orderByDesc('id')
            ->get(['id', 'emoji_slug', 'keyword', 'lang', 'is_active', 'created_at', 'updated_at']);

        return response()->json(['ok' => true, 'items' => $items]);
    }

    public function store(Request $request): JsonResponse
    {
        $check = $this->ensureUser($request);
        if (! isset($check['user'])) {
            return response()->json(['ok' => false, 'error' => $check['error']], $check['status']);
        }

        $data = $request->validate([
            'emoji_slug' => 'required|string|max:120',
            'keyword' => 'required|string|max:200',
            'lang' => 'nullable|string|max:10',
        ]);

        $lang = $data['lang'] ?? 'und';
        $user = $check['user'];
        $existing = UserKeyword::where('user_id', $user->id)
            ->where('emoji_slug', $data['emoji_slug'])
            ->where('keyword', $data['keyword'])
            ->first();
        $targetActive = $existing ? (bool) $existing->is_active : true;
        $limit = $this->keywordLimitFor($user);
        if ($limit !== null) {
            if (! $existing && $targetActive) {
                $activeCount = $this->keywordQuota->activeCount((int) $user->id);
                if ($activeCount >= $limit) {
                    return response()->json(['ok' => false, 'error' => 'free_active_limit_reached', 'limit' => $limit], 403);
                }
            }
        }

        if ($existing) {
            $existing->update([
                'lang' => $lang,
            ]);
            $item = $existing;
        } else {
            $item = UserKeyword::create([
                'user_id' => $user->id,
                'emoji_slug' => $data['emoji_slug'],
                'keyword' => $data['keyword'],
                'lang' => $lang,
                'is_active' => true,
            ]);
        }

        return response()->json(['ok' => true, 'item' => $item]);
    }

    public function destroy(Request $request, int $id): JsonResponse
    {
        $check = $this->ensureUser($request);
        if (! isset($check['user'])) {
            return response()->json(['ok' => false, 'error' => $check['error']], $check['status']);
        }

        $deleted = UserKeyword::where('user_id', $check['user']->id)
            ->where('id', $id)
            ->delete();

        return response()->json(['ok' => true, 'deleted' => $deleted > 0]);
    }

    public function update(Request $request, int $id): JsonResponse
    {
        $check = $this->ensureUser($request);
        if (! isset($check['user'])) {
            return response()->json(['ok' => false, 'error' => $check['error']], $check['status']);
        }

        $data = $request->validate([
            'emoji_slug' => 'required|string|max:120',
            'keyword' => 'required|string|max:200',
            'lang' => 'nullable|string|max:10',
        ]);

        $item = UserKeyword::where('user_id', $check['user']->id)
            ->where('id', $id)
            ->first();

        if (! $item) {
            return response()->json(['ok' => false, 'error' => 'not_found'], 404);
        }

        $duplicate = UserKeyword::where('user_id', $check['user']->id)
            ->where('emoji_slug', $data['emoji_slug'])
            ->where('keyword', $data['keyword'])
            ->first();

        if ($duplicate && $duplicate->id !== $item->id) {
            $item->delete();
            $item = $duplicate;
        } else {
            $item->update([
                'emoji_slug' => $data['emoji_slug'],
                'keyword' => $data['keyword'],
                'lang' => $data['lang'] ?? 'und',
            ]);
        }

        return response()->json(['ok' => true, 'item' => $item]);
    }

    public function export(Request $request): JsonResponse
    {
        $check = $this->ensureUser($request);
        if (! isset($check['user'])) {
            return response()->json(['ok' => false, 'error' => $check['error']], $check['status']);
        }

        $items = UserKeyword::where('user_id', $check['user']->id)
            ->orderByDesc('id')
            ->get(['emoji_slug', 'keyword', 'lang', 'is_active']);

        return response()->json(['ok' => true, 'items' => $items]);
    }

    public function import(Request $request): JsonResponse
    {
        $check = $this->ensureUser($request);
        if (! isset($check['user'])) {
            return response()->json(['ok' => false, 'error' => $check['error']], $check['status']);
        }

        $data = $request->validate([
            'items' => 'required|array',
            'items.*.emoji_slug' => 'required|string|max:120',
            'items.*.keyword' => 'required|string|max:200',
            'items.*.lang' => 'nullable|string|max:10',
        ]);

        $count = 0;
        $skipped = 0;
        $user = $check['user'];
        $limit = $this->keywordLimitFor($user);
        $activeCount = $this->keywordQuota->activeCount((int) $user->id);
        foreach ($data['items'] as $row) {
            $existing = UserKeyword::where('user_id', $user->id)
                ->where('emoji_slug', $row['emoji_slug'])
                ->where('keyword', $row['keyword'])
                ->first();
            $targetActive = filter_var($row['is_active'] ?? true, FILTER_VALIDATE_BOOL);

            if (! $existing && $targetActive && $limit !== null && $activeCount >= $limit) {
                $skipped += 1;

                continue;
            }

            if ($existing) {
                $existing->update([
                    'lang' => $row['lang'] ?? 'und',
                ]);
            } else {
                UserKeyword::create([
                    'user_id' => $user->id,
                    'emoji_slug' => $row['emoji_slug'],
                    'keyword' => $row['keyword'],
                    'lang' => $row['lang'] ?? 'und',
                    'is_active' => $targetActive,
                ]);
                if ($targetActive) {
                    $activeCount += 1;
                }
            }
            $count += 1;
        }

        return response()->json(['ok' => true, 'imported' => $count, 'skipped' => $skipped]);
    }

    public function toggleActive(Request $request, int $id): JsonResponse
    {
        $check = $this->ensureUser($request);
        if (! isset($check['user'])) {
            return response()->json(['ok' => false, 'error' => $check['error']], $check['status']);
        }

        $data = $request->validate([
            'is_active' => 'required|boolean',
        ]);

        $user = $check['user'];
        $item = UserKeyword::where('user_id', $user->id)->where('id', $id)->first();
        if (! $item) {
            return response()->json(['ok' => false, 'error' => 'not_found'], 404);
        }

        if ((bool) $data['is_active'] && ($limit = $this->keywordLimitFor($user))) {
            $activeCount = $this->keywordQuota->activeCount((int) $user->id);
            if (! $item->is_active && $activeCount >= $limit) {
                return response()->json(['ok' => false, 'error' => 'free_active_limit_reached', 'limit' => $limit], 403);
            }
        }

        $item->update(['is_active' => (bool) $data['is_active']]);

        return response()->json(['ok' => true, 'item' => $item]);
    }

    private function keywordLimitFor($user): ?int
    {
        if ((string) ($user->tier ?? 'free') === 'personal') {
            return null;
        }

        return (int) config('dewemoji.pagination.free_max_limit', 20);
    }
}
