<?php
if (!defined('APP_ROOT')) exit;

const TOPIC_READ_GROUPS_TABLE = 'plugin_topic_read_groups_rules';
const TOPIC_READ_GROUPS_META  = 'plugin_topic_read_groups_meta';

/* ===== 权限判断（请求级缓存 + 主组/附属组）===== */

function topic_read_groups_user_can_view(int $topic_id, ?array $topic = null): bool
{
    static $cache = [];
    $uid = uid();
    $key = $topic_id . '_' . $uid;
    if (isset($cache[$key])) return $cache[$key];

    if (is_super_user() || can_manage()) return $cache[$key] = true;

    $author_id = (int)($topic['user_id'] ?? 0);
    if ($uid > 0 && $author_id > 0 && $uid === $author_id) return $cache[$key] = true;

    $rule_count = (int)val('SELECT COUNT(*) FROM ' . TOPIC_READ_GROUPS_TABLE . ' WHERE topic_id=?', [$topic_id]);
    if ($rule_count === 0) return $cache[$key] = true;

    $me = me();
    if (!$me) return $cache[$key] = false;

    $gids = [];
    $main_gid = (int)($me['group_id'] ?? 0);
    if ($main_gid > 0) $gids[] = $main_gid;
    $extra_raw = trim((string)($me['group_ids'] ?? ''));
    if ($extra_raw !== '') {
        foreach (explode(',', $extra_raw) as $eg) {
            $eg = (int)$eg;
            if ($eg > 0) $gids[] = $eg;
        }
    }
    $gids = array_values(array_unique($gids));
    if (!$gids) return $cache[$key] = false;

    $marks = sql_marks(count($gids));
    $hit = (int)val(
        'SELECT 1 FROM ' . TOPIC_READ_GROUPS_TABLE . ' WHERE topic_id=? AND group_id IN(' . $marks . ')',
        array_merge([$topic_id], $gids)
    );
    return $cache[$key] = $hit > 0;
}

function topic_read_groups_is_hidden(int $topic_id): bool
{
    return (int)val('SELECT 1 FROM ' . TOPIC_READ_GROUPS_META . ' WHERE topic_id=? AND hidden=1', [$topic_id]) > 0;
}

function topic_read_groups_allowed_ids(int $topic_id): array
{
    $rows = q('SELECT group_id FROM ' . TOPIC_READ_GROUPS_TABLE . ' WHERE topic_id=? ORDER BY group_id', [$topic_id])->fetchAll();
    $ids = [];
    foreach ($rows as $r) $ids[] = (int)$r['group_id'];
    return $ids;
}

/* ===== 安装 / 卸载（可重复执行）===== */

function topic_read_groups_install(array $plugin): void
{
    $t = app_db_types();
    app_db_create_table(TOPIC_READ_GROUPS_TABLE,
        'id ' . $t['id'] . ','
        . 'topic_id ' . $t['uint'] . ' NOT NULL,'
        . 'group_id ' . $t['uint'] . ' NOT NULL,'
        . 'created_at ' . $t['uint'] . ' NOT NULL DEFAULT 0'
    );
    app_db_ensure_columns(TOPIC_READ_GROUPS_TABLE, ['created_at' => $t['uint'] . ' NOT NULL DEFAULT 0']);

    $drv = db_driver();
    db()->exec('CREATE UNIQUE INDEX IF NOT EXISTS '
        . app_db_identifier($drv, TOPIC_READ_GROUPS_TABLE . '_uniq')
        . ' ON ' . app_db_identifier($drv, TOPIC_READ_GROUPS_TABLE)
        . '(topic_id,group_id)');
    app_db_create_index(TOPIC_READ_GROUPS_TABLE . '_idx_topic', TOPIC_READ_GROUPS_TABLE . '(topic_id)');

    app_db_create_table(TOPIC_READ_GROUPS_META,
        'topic_id ' . $t['uint'] . ' NOT NULL PRIMARY KEY,'
        . 'hidden ' . $t['uint'] . ' NOT NULL DEFAULT 0'
    );
    app_db_ensure_columns(TOPIC_READ_GROUPS_META, ['hidden' => $t['uint'] . ' NOT NULL DEFAULT 0']);
}

function topic_read_groups_uninstall(array $plugin): void
{
    app_db_drop_table(TOPIC_READ_GROUPS_TABLE);
    app_db_drop_table(TOPIC_READ_GROUPS_META);
}

/* ===== CSS（系统变量配色，插件前缀类名）===== */

function topic_read_groups_css(): string
{
    return <<<'CSS'
.trg-field{display:flex;flex-direction:column;gap:var(--spacing-xs,6px);padding:var(--spacing-sm,10px) 0;border-top:1px solid var(--line-soft,#eee);margin-top:var(--spacing-xs,6px)}
.trg-form-label{font-weight:600;color:var(--text,#222);font-size:var(--font-size-sm,13px)}
.trg-form-help{color:var(--text-muted,#888);font-size:var(--font-size-xs,12px);margin-top:2px}
.trg-group-checkbox{display:flex;flex-wrap:wrap;gap:6px 12px;padding:6px 0}
.trg-gcheck{display:inline-flex;align-items:center;gap:4px;font-size:var(--font-size-sm,13px);color:var(--text,#222);cursor:pointer;padding:3px 8px;border-radius:6px;background:var(--bg,#f7f8fa);border:1px solid var(--line-soft,#e5e7eb);transition:background .15s,border-color .15s;user-select:none;white-space:nowrap}
.trg-gcheck:hover{background:var(--brand-soft,#e8f0fe);border-color:var(--brand,#2563eb)}
.trg-gcheck input[type="checkbox"]{accent-color:var(--brand,#2563eb);margin:0}
.trg-hidden-field{margin-top:4px}
.trg-hidden-check{display:flex;align-items:center;gap:6px;font-size:var(--font-size-sm,13px);color:var(--text,#222);cursor:pointer;user-select:none}
.trg-hidden-check input[type="checkbox"]{accent-color:var(--danger,#dc3545);margin:0}
.trg-badge{display:inline-block;margin-left:4px;padding:2px 7px;border-radius:4px;font-size:var(--font-size-xs,12px);font-weight:600;line-height:1;background:var(--danger-soft,#fce4e4);color:var(--danger,#dc3545);vertical-align:middle;white-space:nowrap}
.trg-denied-panel{text-align:center;padding:48px 20px}
.trg-denied-panel h2{color:var(--danger,#dc3545);margin-bottom:12px;font-size:var(--font-size-lg,18px)}
.trg-denied-panel p{color:var(--text-muted,#666);margin-bottom:20px;font-size:var(--font-size-sm,14px)}
.trg-denied-links{display:flex;justify-content:center;gap:12px;flex-wrap:wrap}
.trg-denied-links a{display:inline-flex;align-items:center;gap:4px;padding:8px 18px;border-radius:6px;font-size:var(--font-size-sm,13px);text-decoration:none;transition:all .15s}
.trg-denied-links .trg-btn-back{background:var(--bg,#f7f8fa);color:var(--text,#222);border:1px solid var(--line-soft,#e5e7eb)}
.trg-denied-links .trg-btn-back:hover{background:var(--line-soft,#e5e7eb)}
.trg-denied-links .trg-btn-home{background:var(--brand,#2563eb);color:#fff;border:1px solid var(--brand,#2563eb)}
.trg-denied-links .trg-btn-home:hover{opacity:.9}
CSS;
}

/* ===== Hook: 表单扩展（发帖/编辑注入用户组多选 + 隐藏选项）===== */

function topic_read_groups_form_extra(string $html, array $ctx): string
{
    $t = (array)($ctx['topic'] ?? []);
    $topic_id = (int)($t['id'] ?? 0);
    $editing = !empty($ctx['editing']);
    $groups = groups_cache();
    if (!$groups) return $html;

    $checked_ids = ($editing && $topic_id > 0) ? topic_read_groups_allowed_ids($topic_id) : [];
    $is_hidden = ($editing && $topic_id > 0) ? topic_read_groups_is_hidden($topic_id) : false;

    $out = '<div class="trg-field">'
        . '<span class="trg-form-label">阅读权限（按用户组）</span>'
        . '<div class="trg-group-checkbox">';
    foreach ($groups as $g) {
        $gid = (int)$g['id'];
        if ($gid <= 0) continue;
        $chk = in_array($gid, $checked_ids, true) ? ' checked' : '';
        $out .= '<label class="trg-gcheck"><input type="checkbox" name="trg_group_ids[]" value="' . $gid . '"' . $chk . '>'
            . h((string)($g['name'] ?? ('组#' . $gid))) . '</label>';
    }
    $out .= '</div><div class="trg-form-help">勾选允许阅读的用户组；不勾选任何组表示公开（所有人可看）。</div>';

    $hidden_chk = $is_hidden ? ' checked' : '';
    $out .= '<div class="trg-hidden-field"><label class="trg-hidden-check">'
        . '<input type="checkbox" name="trg_hidden" value="1"' . $hidden_chk . '>'
        . '<span>对无权限用户完全隐藏此主题（含标题）</span></label>'
        . '<div class="trg-form-help">开启后，无阅读权限的用户在列表中也将看不到此主题。</div></div>';

    $out .= '</div>';
    return $html . $out;
}

/* ===== Hook: 保存后同步规则 + 隐藏标志（事务原子写入）===== */

function topic_read_groups_after_save(?array $payload, array $ctx): void
{
    $topic_id = (int)($ctx['id'] ?? 0);
    if ($topic_id <= 0) return;

    $raw = $_POST['trg_group_ids'] ?? [];
    $group_ids = [];
    if (is_array($raw)) {
        foreach ($raw as $v) {
            $gid = (int)$v;
            if ($gid > 0 && !in_array($gid, $group_ids, true)) $group_ids[] = $gid;
        }
    }
    $hide = !empty($_POST['trg_hidden']);

    tx(function () use ($topic_id, $group_ids, $hide) {
        q('DELETE FROM ' . TOPIC_READ_GROUPS_TABLE . ' WHERE topic_id=?', [$topic_id]);
        $ts = now();
        foreach ($group_ids as $gid) {
            q('INSERT INTO ' . TOPIC_READ_GROUPS_TABLE . '(topic_id,group_id,created_at) VALUES(?,?,?)', [$topic_id, $gid, $ts]);
        }
        q('DELETE FROM ' . TOPIC_READ_GROUPS_META . ' WHERE topic_id=?', [$topic_id]);
        if ($hide) {
            q('INSERT INTO ' . TOPIC_READ_GROUPS_META . '(topic_id,hidden) VALUES(?,1)', [$topic_id]);
        }
    });
}

/* ===== Hook: 删除主题时清理插件数据 ===== */

function topic_read_groups_before_delete(?array $payload, array $ctx): void
{
    $topic_id = (int)($ctx['id'] ?? 0);
    if ($topic_id <= 0) return;
    q('DELETE FROM ' . TOPIC_READ_GROUPS_TABLE . ' WHERE topic_id=?', [$topic_id]);
    q('DELETE FROM ' . TOPIC_READ_GROUPS_META . ' WHERE topic_id=?', [$topic_id]);
}

/* ===== Hook: 详情页阅读拦截 =====
 * 列表页的标题徽标/隐藏由 before_render + after_render + title_suffix 处理；
 * 详情页（非 list）此处统一拦截无权限访问。
 */
function topic_read_groups_after_view(?array $payload, array $ctx): void
{
    $topic = (array)($ctx['topic'] ?? []);
    $topic_id = (int)($topic['id'] ?? 0);
    if ($topic_id <= 0) return;
    if (topic_read_groups_user_can_view($topic_id, $topic)) return;

    $back_url = $_SERVER['HTTP_REFERER'] ?? route_url('home');
    $home_url = route_url('home');

    $body = '<div class="form-panel trg-denied-panel">'
        . '<h2>无权查看</h2>'
        . '<p>您没有查看此主题的权限</p>'
        . '<div class="trg-denied-links">'
        . '<a class="trg-btn-back" href="' . h($back_url) . '">← 返回上一页</a>'
        . '<a class="trg-btn-home" href="' . h($home_url) . '">返回首页</a>'
        . '</div></div>';

    page('无权查看', shell_html($body, sidebar_stack_html([sidebar_user_card_html()])));
    exit;
}

/* ===== Hook: 列表行前置处理（list=true）=====
 * topic.before_render 的返回值被核心采用（见 index.php:2006），
 * 通过写入 __trg_denied / __trg_hidden 标记传递给后续 title_suffix 与 after_render。
 */
function topic_read_groups_before_render(?array $payload, array $ctx): ?array
{
    if (empty($ctx['list'])) return $payload;
    $row = (array)($ctx['row'] ?? ($payload['row'] ?? []));
    if (empty($row)) return $payload;
    $tid = (int)($row['id'] ?? 0);
    if ($tid <= 0) return $payload;

    if (topic_read_groups_user_can_view($tid, $row)) return $payload;

    if (topic_read_groups_is_hidden($tid)) {
        $row['__trg_hidden'] = true;
    } else {
        $row['__trg_denied'] = true;
    }
    return ['row' => $row];
}

/* ===== Hook: 列表行后置处理（隐藏整行）===== */
function topic_read_groups_after_render(string $html, array $ctx): string
{
    if (empty($ctx['list'])) return $html;
    $row = (array)($ctx['row'] ?? []);
    if (!empty($row['__trg_hidden'])) return '';
    return $html;
}

/* ===== Hook: 列表标题后缀徽标（仅对可见但无权的主题）===== */
function topic_read_groups_title_suffix(string $suffix, array $ctx): string
{
    if (empty($ctx['list'])) return $suffix;
    $row = (array)($ctx['row'] ?? []);
    if (!empty($row['__trg_denied'])) {
        $suffix .= '<span class="trg-badge">权限贴</span>';
    }
    return $suffix;
}

/* ===== Manifest ===== */

return [
    'id'          => 'topic_read_groups',
    'name'        => '主题阅读权限',
    'version'     => '1.30',
    'description' => '发帖时可按用户组设置阅读权限；可选隐藏使无权限用户（含游客）完全不可见。支持附属用户组。',
    'author'      => 'one',
    'assets'      => ['css' => 'topic_read_groups_css'],
    'hooks'       => [
        'topic.form_extra'          => 'topic_read_groups_form_extra',
        'topic.after_save'          => 'topic_read_groups_after_save',
        'topic.before_delete'       => 'topic_read_groups_before_delete',
        'topic.after_view'          => 'topic_read_groups_after_view',
        'topic.before_render'       => 'topic_read_groups_before_render',
        'topic.after_render'        => 'topic_read_groups_after_render',
        'topic.title_suffix'        => 'topic_read_groups_title_suffix',
    ],
    'install'     => 'topic_read_groups_install',
    'uninstall'   => 'topic_read_groups_uninstall',
];
