<?php

/**
 * 文件功能：后台开发日志管理控制器（仅 id=1 超级管理员可访问）
 * 提供开发日志的 CRUD 功能，发布时可选择向 Room 1 大厅广播通知
 *
 * @author   ChatRoom Laravel
 *
 * @version  1.0.0
 */

namespace App\Http\Controllers\Admin;

use App\Events\ChangelogPublished;
use App\Http\Controllers\Controller;
use App\Jobs\SaveMessageJob;
use App\Models\DevChangelog;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\View\View;

class ChangelogController extends Controller
{
    /**
     * 后台日志列表（含草稿）
     */
    public function index(): View
    {
        $logs = DevChangelog::orderByDesc('created_at')->paginate(20);

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

    /**
     * 新增日志表单页（预填今日日期）
     */
    public function create(): View
    {
        // 预填今日日期为版本号
        $todayVersion = now()->format('Y-m-d');

        return view('admin.changelog.form', [
            'log' => null,
            'todayVersion' => $todayVersion,
            'typeOptions' => DevChangelog::TYPE_CONFIG,
            'isCreate' => true,
        ]);
    }

    /**
     * 保存新日志
     * 若勾选"立即发布"，则记录 published_at 并可选向大厅广播通知
     */
    public function store(Request $request): RedirectResponse
    {
        $data = $request->validate([
            'version' => 'required|string|max:30',
            'title' => 'required|string|max:200',
            'type' => 'required|in:feature,fix,improve,other',
            'content' => 'required|string',
            'is_published' => 'nullable|boolean',
            'notify_chat' => 'nullable|boolean',
        ]);

        $isPublished = (bool) ($data['is_published'] ?? false);
        $notifyChat = (bool) ($data['notify_chat'] ?? false);

        /** @var DevChangelog $log */
        $log = DevChangelog::create([
            'version' => $data['version'],
            'title' => $data['title'],
            'type' => $data['type'],
            'content' => $data['content'],
            'is_published' => $isPublished,
            // 只有同时勾选"通知"才记录 notify_chat，否则置 false
            'notify_chat' => $isPublished && $notifyChat,
            // 首次发布时记录发布时间
            'published_at' => $isPublished ? Carbon::now() : null,
        ]);

        // 如果发布且勾选了"通知大厅用户"，则触发 WebSocket 广播 + 持久化到消息库
        if ($isPublished && $notifyChat) {
            event(new ChangelogPublished($log));
            $this->saveChangelogNotification($log);
        }

        return redirect()->route('admin.changelogs.index')
            ->with('success', '开发日志创建成功！'.($isPublished ? '（已发布）' : '（草稿已保存）'));
    }

    /**
     * 编辑日志表单页
     *
     * @param  DevChangelog  $changelog  路由模型自动注入
     */
    public function edit(DevChangelog $changelog): View
    {
        return view('admin.changelog.form', [
            'log' => $changelog,
            'todayVersion' => $changelog->version,
            'typeOptions' => DevChangelog::TYPE_CONFIG,
            'isCreate' => false,
        ]);
    }

    /**
     * 更新日志内容（编辑操作不更新 published_at，不触发通知）
     *
     * @param  DevChangelog  $changelog  路由模型自动注入
     */
    public function update(Request $request, DevChangelog $changelog): RedirectResponse
    {
        $log = $changelog;

        $data = $request->validate([
            'version' => 'required|string|max:30',
            'title' => 'required|string|max:200',
            'type' => 'required|in:feature,fix,improve,other',
            'content' => 'required|string',
            'is_published' => 'nullable|boolean',
            'notify_chat' => 'nullable|boolean',
        ]);

        $isPublished = (bool) ($data['is_published'] ?? false);

        // 如果从草稿切换为发布，记录首次发布时间
        $publishedAt = $log->published_at;
        if ($isPublished && ! $log->is_published) {
            $publishedAt = Carbon::now();
        } elseif (! $isPublished) {
            // 从发布退回草稿，清除发布时间
            $publishedAt = null;
        }

        $log->update([
            'version' => $data['version'],
            'title' => $data['title'],
            'type' => $data['type'],
            'content' => $data['content'],
            'is_published' => $isPublished,
            'published_at' => $publishedAt,
        ]);

        // 若勾选了「通知大厅用户」且当前已发布，则广播通知 + 持久化到消息库
        $notifyChat = (bool) ($data['notify_chat'] ?? false);
        if ($notifyChat && $isPublished) {
            event(new ChangelogPublished($log));
            $this->saveChangelogNotification($log);
        }

        return redirect()->route('admin.changelogs.index')
            ->with('success', '开发日志已更新！');
    }

    /**
     * 删除日志
     *
     * @param  DevChangelog  $changelog  路由模型自动注入
     */
    public function destroy(DevChangelog $changelog): RedirectResponse
    {
        $changelog->delete();

        return redirect()->route('admin.changelogs.index')
            ->with('success', '日志已删除。');
    }

    /**
     * 将版本更新通知持久化为 Room 1 系统消息
     * 确保用户重进聊天室时仍能在历史消息中看到该通知
     *
     * @param  DevChangelog  $log  已发布的日志
     */
    private function saveChangelogNotification(DevChangelog $log): void
    {
        // 广播文案允许保留安全链接，但标题与版本号必须先做 HTML 转义，避免系统消息被拼成恶意标签。
        $safeTypeLabel = e(DevChangelog::TYPE_CONFIG[$log->type]['label'] ?? '更新');
        $safeVersion = e((string) $log->version);
        $safeTitle = e((string) $log->title);
        $detailUrl = e($this->buildChangelogDetailUrl($log));

        SaveMessageJob::dispatch([
            'room_id' => 1,
            'from_user' => '系统公告',
            'to_user' => '大家',
            'content' => "📢 【版本更新 {$safeTypeLabel}】v{$safeVersion}《{$safeTitle}》— <a href=\"{$detailUrl}\" target=\"_blank\" rel=\"noopener\" class=\"underline\">点击查看详情</a>",
            'is_secret' => false,
            'font_color' => '#7c3aed',
            'action' => '',
            'sent_at' => now()->toIso8601String(),
        ]);
    }

    /**
     * 生成开发日志详情链接，并对版本片段做 URL 编码，避免广播 href 被注入额外属性。
     */
    private function buildChangelogDetailUrl(DevChangelog $log): string
    {
        return route('changelog.index').'#v'.rawurlencode((string) $log->version);
    }
}
