<?php

/**
 * 文件功能：禁用用户名管理控制器（站长专用）
 *
 * 管理 username_blacklist 表中 type=permanent 的永久禁用词列表。
 * 包含：国家领导人名称、攻击性词汇、违禁词等不允许注册或改名的词语。
 *
 * 用户在注册（AuthController）和改名（ShopService::useRenameCard）时均会经过该表检测。
 *
 * @author  ChatRoom Laravel
 *
 * @version 1.0.0
 */

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\UsernameBlacklist;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;

class ForbiddenUsernameController extends Controller
{
    /**
     * 分页列出所有永久禁用词。
     * 支持关键词模糊搜索（GET ?q=xxx）。
     */
    public function index(Request $request): \Illuminate\View\View
    {
        $q = $request->query('q', '');

        $items = UsernameBlacklist::permanent()
            ->when($q, fn ($query) => $query->where('username', 'like', "%{$q}%"))
            ->orderByDesc('created_at')
            ->paginate(20)
            ->withQueryString();

        return view('admin.forbidden-usernames.index', [
            'items' => $items,
            'q' => $q,
        ]);
    }

    /**
     * 新增一条永久禁用词。
     *
     * @param  Request  $request  请求体：username（必填），reason（选填）
     */
    public function store(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'username' => ['required', 'string', 'max:50'],
            'reason' => ['nullable', 'string', 'max:100'],
        ], [
            'username.required' => '禁用词不能为空。',
            'username.max' => '禁用词最长50字符。',
        ]);

        $username = trim($validated['username']);

        // 已存在同名的永久记录则不重复插入
        $exists = UsernameBlacklist::permanent()
            ->where('username', $username)
            ->exists();

        if ($exists) {
            return response()->json(['status' => 'error', 'message' => '该词语已在永久禁用列表中。'], 422);
        }

        UsernameBlacklist::create([
            'username' => $username,
            'type' => 'permanent',
            'reserved_until' => null,
            'reason' => $validated['reason'] ?? null,
            'created_at' => Carbon::now(),
        ]);

        return response()->json(['status' => 'success', 'message' => "「{$username}」已加入永久禁用列表。"]);
    }

    /**
     * 批量添加永久禁用词。
     *
     * 接受多行文本或逗号分隔的词语列表，自动去重并过滤已存在者。
     * 返回成功添加数量和跳过数量。
     *
     * @param  Request  $request  请求体：words（换行/逗号分隔），reason（选填，共用）
     */
    public function batchStore(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'words' => ['required', 'string'],
            'reason' => ['nullable', 'string', 'max:100'],
        ], [
            'words.required' => '请输入至少一个词语。',
        ]);

        // 净化输入：去除非法 UTF-8 字节（零宽字符、BOM、控制字符等），防止 json_encode 失败
        $rawInput = $this->sanitizeUtf8($validated['words']);
        $reason = $this->sanitizeUtf8(trim($validated['reason'] ?? ''));

        // 支持换行、逗号、中文逗号、空格分隔
        $rawWords = preg_split('/[\r\n,，\s]+/u', $rawInput);

        // 过滤空串、超长词、去重
        $words = collect($rawWords)
            ->map(fn ($w) => trim($w))
            ->filter(fn ($w) => $w !== '' && mb_strlen($w) <= 50)
            ->unique()
            ->values();

        if ($words->isEmpty()) {
            return response()->json(['status' => 'error', 'message' => '没有有效的词语，请检查输入。'], 422);
        }

        // 批量查询已存在的词（一次查询）
        $existing = UsernameBlacklist::permanent()
            ->whereIn('username', $words->all())
            ->pluck('username')
            ->flip();

        $now = Carbon::now();
        $added = 0;
        $rows = [];

        foreach ($words as $word) {
            if ($existing->has($word)) {
                continue;
            }
            $rows[] = [
                'username' => $word,
                'type' => 'permanent',
                'reserved_until' => null,
                'reason' => $reason ?: null,
                'created_at' => $now,
            ];
            $added++;
        }

        if (! empty($rows)) {
            UsernameBlacklist::insert($rows);
        }

        $skipped = $words->count() - $added;
        $msg = "成功添加 {$added} 个词语".($skipped > 0 ? "，跳过 {$skipped} 个（已存在）" : '').'。';

        return response()->json(['status' => 'success', 'message' => $msg, 'added' => $added], 200, [], JSON_UNESCAPED_UNICODE);
    }

    /**
     * 净化字符串，移除非法 UTF-8 字节及常见控制/零宽字符。
     *
     * @param  string  $str  待净化字符串
     * @return string 合法的 UTF-8 字符串
     */
    private function sanitizeUtf8(string $str): string
    {
        // 去除 BOM
        $str = str_replace("\xEF\xBB\xBF", '', $str);
        // 去除零宽字符（零宽空格、零宽不连字等）
        $str = preg_replace('/[\x{200B}-\x{200D}\x{FEFF}\x{00AD}]/u', '', $str);
        // 转换为合法 UTF-8，忽略非法字节
        $str = mb_convert_encoding($str, 'UTF-8', 'UTF-8');
        // 保底：去除控制字符（保留换行 \r\n）
        $str = preg_replace('/[^\P{C}\r\n]+/u', '', $str);

        return $str;
    }

    /**
     * 更新指定禁用词的原因备注。
     *
     * @param  int  $id  记录 ID
     * @param  Request  $request  请求体：reason
     */
    public function update(Request $request, int $id): JsonResponse
    {
        $item = UsernameBlacklist::permanent()->findOrFail($id);

        $validated = $request->validate([
            'reason' => ['nullable', 'string', 'max:100'],
        ]);

        $item->update(['reason' => $validated['reason']]);

        return response()->json(['status' => 'success', 'message' => '备注已更新。']);
    }

    /**
     * 删除指定永久禁用词。
     *
     * @param  int  $id  记录 ID
     */
    public function destroy(int $id): JsonResponse
    {
        $item = UsernameBlacklist::permanent()->findOrFail($id);
        $name = $item->username;
        $item->delete();

        return response()->json(['status' => 'success', 'message' => "「{$name}」已从永久禁用列表移除。"]);
    }
}
