<?php
/**
 * Дашборд Я.Директ — статистика клиентов (gubtor.ru/direct/)
 * Роли: admin (все клиенты) / client (только свой кабинет)
 * Данные: CRM egokad -> SQLite (сборщик collect.py по крону)
 */
declare(strict_types=1);
/* сессия живёт 90 дней (и для админа, и для клиентов) */
ini_set('session.gc_maxlifetime', '7776000');
ini_set('session.cookie_lifetime', '7776000');
ini_set('session.use_strict_mode', '0');
session_set_cookie_params([
    'lifetime' => 7776000,
    'path' => '/',
    'secure' => true,
    'httponly' => true,
    'samesite' => 'Lax',
]);
session_start();

$SECRETS = require '/etc/quiz-secrets/direct.php';
$DB_MAIN = __DIR__ . '/data.db';
$DB_USERS = __DIR__ . '/users.db';

/* ── инициализация БД пользователей ── */
function db_users(): PDO {
    global $DB_USERS;
    $pdo = new PDO('sqlite:' . $DB_USERS, null, null, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_TIMEOUT => 30]);
    $pdo->exec('CREATE TABLE IF NOT EXISTS users (
        email TEXT PRIMARY KEY,
        password_hash TEXT NOT NULL,
        role TEXT NOT NULL DEFAULT "client",
        created_at TEXT DEFAULT (datetime("now"))
    )');
    $pdo->exec('CREATE TABLE IF NOT EXISTS user_clients (
        email TEXT NOT NULL,
        client_id INTEGER NOT NULL,
        PRIMARY KEY(email, client_id)
    )');
    return $pdo;
}

function db_main(): PDO {
    global $DB_MAIN;
    $pdo = new PDO('sqlite:' . $DB_MAIN, null, null, [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_TIMEOUT => 30,  // ждать снятия блокировки до 30 с (WAL)
    ]);
    $pdo->exec('PRAGMA busy_timeout=30000');
    return $pdo;
}

/* ── утилиты рендера ── */
function money($v): string {
    if ($v === null || $v === '') return '—';
    return number_format((float)$v, 0, '.', ' ') . ' ₽';
}
function num($v): string {
    if ($v === null || $v === '') return '—';
    return number_format((float)$v, 0, '.', ' ');
}
function cpl($cost, $conv): string {
    $cost = (float)$cost; $conv = (float)$conv;
    if ($conv <= 0) return '—';
    return number_format($cost / $conv, 0, '.', ' ') . ' ₽';
}
function forecast_days($forecast): ?int {
    if ($forecast === null || $forecast === '') return null;
    if (preg_match('/(\d+)\s*(?:дн|день|дня)/u', (string)$forecast, $m)) return (int)$m[1];
    if (preg_match('/(\d+)/', (string)$forecast, $m)) return (int)$m[1];
    return null;
}
function forecast_color($forecast): string {
    $d = forecast_days($forecast);
    if ($d === null) return '';
    if ($d < 4)  return 'fc-red';     // менее 4 дней — красный
    if ($d <= 7) return 'fc-orange';  // ≤ 7 дней — оранжевый
    if ($d < 10) return 'fc-yellow';  // < 10 дней — жёлтый
    return '';
}
/* ── генерация логина/пароля для нового клиента ── */
function translit_ru(string $s): string {
    $map = ['а'=>'a','б'=>'b','в'=>'v','г'=>'g','д'=>'d','е'=>'e','ё'=>'e','ж'=>'zh','з'=>'z','и'=>'i','й'=>'y',
            'к'=>'k','л'=>'l','м'=>'m','н'=>'n','о'=>'o','п'=>'p','р'=>'r','с'=>'s','т'=>'t','у'=>'u','ф'=>'f',
            'х'=>'h','ц'=>'ts','ч'=>'ch','ш'=>'sh','щ'=>'sch','ъ'=>'','ы'=>'y','ь'=>'','э'=>'e','ю'=>'yu','я'=>'ya'];
    $out = '';
    foreach (preg_split('//u', mb_strtolower($s), -1, PREG_SPLIT_NO_EMPTY) as $ch) {
        $out .= $map[$ch] ?? (preg_match('/[a-z0-9]/', $ch) ? $ch : '-');
    }
    return trim(preg_replace('/-+/', '-', $out), '-');
}
function gen_login_php(string $name, PDO $users): string {
    $base = '';
    if (preg_match('/ИП\s+([А-ЯЁ][а-яё]+)/u', $name, $m)) $base = translit_ru($m[1]);
    if ($base === '' && preg_match('/([А-ЯЁ][а-яё]+)/u', $name, $m)) $base = translit_ru($m[1]);
    if ($base === '') $base = 'client';
    $login = $base;
    $i = 1;
    while (true) {
        $st = $users->prepare('SELECT 1 FROM users WHERE login = ?');
        $st->execute([$login]);
        if (!$st->fetch()) break;
        $i++;
        $login = $base . $i;
    }
    return $login;
}
function gen_password_php(string $name): string {
    $base = 'Client';
    if (preg_match('/ИП\s+([А-ЯЁ][а-яё]+)/u', $name, $m)) $base = ucfirst(translit_ru($m[1]));
    return $base . '-' . random_int(1000, 9999);
}
function plural_days_php(int $d): string {
    $d10 = $d % 10; $d100 = $d % 100;
    if ($d100 >= 11 && $d100 <= 14) return $d . ' дней';
    if ($d10 == 1) return $d . ' день';
    if ($d10 >= 2 && $d10 <= 4) return $d . ' дня';
    return $d . ' дней';
}
/**
 * Остаток для клиента из Директа: баланс / дневной расход.
 * Дневной расход: недельный бюджет (если указан) / 7, иначе — фактический средний за 7 дней.
 */
function yandex_exchange_code(string $code): ?string {
    $data = http_build_query([
        'grant_type' => 'authorization_code',
        'code' => $code,
        'client_id' => '18476717535549aba73d77da1bcd4f57',
        'client_secret' => '864d07eac585446d9d105f6740eab9a7',
    ]);
    $ctx = stream_context_create(['http' => [
        'method' => 'POST',
        'header' => "Content-Type: application/x-www-form-urlencoded\r\n"
                  . "Content-Length: " . strlen($data) . "\r\n",
        'content' => $data,
        'timeout' => 30,
        'ignore_errors' => true,
    ]]);
    $resp = @file_get_contents('https://oauth.yandex.ru/token', false, $ctx);
    if ($resp === false) return null;
    $j = json_decode($resp, true);
    if (!is_array($j) || empty($j['access_token'])) return null;
    return $j['access_token'];
}

function direct_forecast(array $c, array $direct7): string {
    if (($c['source'] ?? 'crm') !== 'direct') return $c['forecast'] ?? '—';
    $bal = (float)($c['balance'] ?? 0);
    if ($bal <= 0) return '—';
    $daily = 0.0;
    if ((float)($c['weekly_budget'] ?? 0) > 0) {
        $daily = (float)$c['weekly_budget'] / 7;
    } elseif (!empty($direct7[(int)$c['client_id']])) {
        $daily = $direct7[(int)$c['client_id']] / 7;
    }
    if ($daily <= 0) return '—';
    return plural_days_php((int)floor($bal / $daily));
}
/* ── рендер Markdown базы знаний (с блоками ```copy) ── */
function kb_inline(string $t): string {
    $t = htmlspecialchars($t, ENT_QUOTES, 'UTF-8');
    $t = preg_replace('/`([^`]+)`/', '<code>$1</code>', $t);
    $t = preg_replace('/\*\*([^*]+)\*\*/', '<b>$1</b>', $t);
    $t = preg_replace('/(?<!\*)\*([^*\n]+)\*(?!\*)/', '<i>$1</i>', $t);
    $t = preg_replace('/~~([^~]+)~~/', '<s>$1</s>', $t);
    $t = preg_replace('/\[([^\]]+)\]\(([^)]+)\)/', '<a href="$2" target="_blank" rel="noopener">$1</a>', $t);
    return $t;
}
function kb_render_md(string $md): string {
    $copy = [];
    $md = preg_replace_callback('/```copy\s*\n(.*?)```/s', function ($m) use (&$copy) {
        $i = count($copy);
        $t = htmlspecialchars(trim($m[1]), ENT_QUOTES, 'UTF-8');
        $copy[$i] = '<div class="kb-copy"><pre>' . $t . '</pre>'
                  . '<button type="button" class="kb-copy-btn" data-copy="' . $t . '">Копировать</button></div>';
        return "\n@@KBCOPY$i@@\n";
    }, $md);
    $md = preg_replace_callback('/```\s*\n(.*?)```/s', function ($m) {
        return '<pre class="kb-code">' . htmlspecialchars($m[1], ENT_QUOTES, 'UTF-8') . '</pre>';
    }, $md);
    $out = '';
    $in_ul = false; $in_ol = false;
    $close_lists = function () use (&$out, &$in_ul, &$in_ol) {
        if ($in_ul) { $out .= '</ul>'; $in_ul = false; }
        if ($in_ol) { $out .= '</ol>'; $in_ol = false; }
    };
    foreach (preg_split('/\r?\n/', $md) as $line) {
        $trim = trim($line);
        if (preg_match('/^@@KBCOPY(\d+)@@$/', $trim, $m)) { $out .= $copy[(int)$m[1]] . "\n"; continue; }
        if ($trim === '') { $close_lists(); continue; }
        if (preg_match('/^##\s+(.+)$/', $trim, $m)) { $close_lists(); $out .= '<h2>' . kb_inline($m[1]) . '</h2>'; continue; }
        if (preg_match('/^#\s+(.+)$/', $trim, $m))  { $close_lists(); $out .= '<h1>' . kb_inline($m[1]) . '</h1>'; continue; }
        if (preg_match('/^&gt;\s?(.*)$/', $trim, $m)) { $close_lists(); $out .= '<blockquote>' . kb_inline($m[1]) . '</blockquote>'; continue; }
        if (preg_match('/^-{3,}\s*$/', $trim)) { $close_lists(); $out .= '<hr>'; continue; }
        if (preg_match('/^\s{2,}[-*]\s+(.+)$/', $line, $m)) {
            if (!$in_ul) { $out .= '<ul class="kb-sub">'; $in_ul = true; }
            $out .= '<li>' . kb_inline($m[1]) . '</li>'; continue;
        }
        if (preg_match('/^[-*]\s+(.+)$/', $trim, $m)) {
            if ($in_ol) { $out .= '</ol>'; $in_ol = false; }
            if (!$in_ul) { $out .= '<ul>'; $in_ul = true; }
            $out .= '<li>' . kb_inline($m[1]) . '</li>'; continue;
        }
        if (preg_match('/^\d+[.)]\s+(.+)$/', $trim, $m)) {
            if ($in_ul) { $out .= '</ul>'; $in_ul = false; }
            if (!$in_ol) { $out .= '<ol>'; $in_ol = true; }
            $out .= '<li>' . kb_inline($m[1]) . '</li>'; continue;
        }
        $close_lists();
        $out .= '<p>' . kb_inline($trim) . '</p>';
    }
    $close_lists();
    return $out;
}

function daily_table_html(array $rows, string $from_d, string $to_d): string {
    if (!$rows) return '';
    $tcost = 0; $tleads = 0;
    foreach ($rows as $r) { $tcost += (float)$r['cost']; $tleads += (int)$r['leads']; }
    $h = '<div class="table-wrap daily-tbl-wrap"><table class="tbl daily-tbl"><thead><tr>'
       . '<th>Дата</th><th class="num">Расход</th><th class="num">Заявки</th><th class="num">CPL</th></tr></thead><tbody>';
    $h .= '<tr class="total-row"><td>ИТОГО · ' . htmlspecialchars($from_d . ' — ' . $to_d) . '</td>'
        . '<td class="num">' . money($tcost) . '</td><td class="num">' . num($tleads) . '</td>'
        . '<td class="num">' . cpl($tcost, $tleads) . '</td></tr>';
    foreach (array_reverse($rows) as $r) {
        $h .= '<tr><td class="mono">' . date('d.m.Y', strtotime($r['date'])) . '</td>'
            . '<td class="num">' . money($r['cost']) . '</td><td class="num">' . num($r['leads']) . '</td>'
            . '<td class="num">' . cpl($r['cost'], $r['leads']) . '</td></tr>';
    }
    return $h . '</tbody></table></div>';
}
function balance_history(PDO $db, ?array $client_ids): array {
    $sql = "SELECT date, client_id, balance FROM snapshots";
    if ($client_ids) { $sql .= " WHERE client_id IN (" . implode(',', array_map('intval', $client_ids)) . ")"; }
    $sql .= " ORDER BY date";
    $rows = $db->query($sql)->fetchAll(PDO::FETCH_ASSOC);
    $out = [];
    foreach ($rows as $r) { $out[$r['date']][(int)$r['client_id']] = (float)$r['balance']; }
    return $out;
}
function period_menu(array $PRESETS, string $period, string $url_prefix, string $from, string $to): string {
    $rows = '';
    foreach ($PRESETS as $k => $label) {
        $cls = $k === $period ? ' class="pm-item pm-active"' : ' class="pm-item"';
        $rows .= '<a' . $cls . ' href="' . htmlspecialchars($url_prefix . 'p=' . $k) . '">' . htmlspecialchars($label) . '</a>';
    }
    $custom = $period === 'custom' ? ' pm-active' : '';
    // параметры страницы (a=client, id, tab…) — скрытыми полями формы:
    // браузер при GET-submit выбрасывает query из action, поэтому их нельзя держать в action
    $hidden = '';
    $q = ltrim($url_prefix, '?&');
    if ($q !== '') {
        foreach (explode('&', $q) as $pair) {
            if ($pair === '') continue;
            $kv = explode('=', $pair, 2);
            $k = trim($kv[0]);
            if ($k === '' || $k === 'p' || $k === 'from' || $k === 'to') continue;
            $v = isset($kv[1]) ? urldecode($kv[1]) : '';
            $hidden .= '<input type="hidden" name="' . htmlspecialchars($k) . '" value="' . htmlspecialchars($v) . '">';
        }
    }
    return '<div class="period-menu">
      <button type="button" class="period-btn" id="period-btn">' . htmlspecialchars($GLOBALS['P_LABEL']) . ' <span class="pm-caret">▾</span></button>
      <div class="period-pop" id="period-pop" hidden>
        <div class="pm-list">' . $rows . '</div>
        <div class="pm-custom">
          <div class="pm-label">Свои даты</div>
          <form method="get" class="pm-form">' . $hidden . '
            <input type="hidden" name="p" value="custom">
            <input type="date" name="from" value="' . htmlspecialchars($from) . '" class="pm-date"> —
            <input type="date" name="to" value="' . htmlspecialchars($to) . '" class="pm-date">
            <button type="submit" class="btn btn-sm">Применить</button>
          </form>
        </div>
      </div>
    </div>';
}

/* ── авторизация ── */
$me = null;
if (!empty($_SESSION['user'])) {
    $me = $_SESSION['user'];
}

$action = $_GET['a'] ?? 'dashboard';

/* ── периоды отчёта (формат партнёра: пресеты + свои даты) ── */
$PRESETS = [
    'today'      => 'Сегодня',
    'yesterday'  => 'Вчера',
    'day_before' => 'Позавчера',
    '7d'         => '7 дней',
    '14d'        => '14 дней',
    '30d'        => '30 дней',
    'cur_week'   => 'Текущая неделя',
    'week'       => 'Прошлая неделя',
    'prev_week'  => 'Позапрошлая неделя',
    'month'      => 'Месяц',
    'prev_month' => 'Прошлый месяц',
];
function period_range(string $p): array {
    $today = new DateTime('today');
    switch ($p) {
        case 'today':      return [$today->format('Y-m-d'), $today->format('Y-m-d')];
        case 'yesterday':  $d = (clone $today)->modify('-1 day');  return [$d->format('Y-m-d'), $d->format('Y-m-d')];
        case 'day_before': $d = (clone $today)->modify('-2 days'); return [$d->format('Y-m-d'), $d->format('Y-m-d')];
        case '7d':  $d = (clone $today)->modify('-6 days');  return [$d->format('Y-m-d'), $today->format('Y-m-d')];
        case '14d': $d = (clone $today)->modify('-13 days'); return [$d->format('Y-m-d'), $today->format('Y-m-d')];
        case '30d': $d = (clone $today)->modify('-29 days'); return [$d->format('Y-m-d'), $today->format('Y-m-d')];
        case 'cur_week':
            $m = (clone $today)->modify('monday this week');
            return [$m->format('Y-m-d'), $today->format('Y-m-d')];
        case 'week':
            $end = (clone $today)->modify('monday this week')->modify('-1 day');
            $start = (clone $end)->modify('-6 days');
            return [$start->format('Y-m-d'), $end->format('Y-m-d')];
        case 'prev_week':
            $end = (clone $today)->modify('monday this week')->modify('-8 days');
            $start = (clone $end)->modify('-6 days');
            return [$start->format('Y-m-d'), $end->format('Y-m-d')];
        case 'month':
            $m = (clone $today)->modify('first day of this month');
            return [$m->format('Y-m-d'), $today->format('Y-m-d')];
        case 'prev_month':
            $s = (clone $today)->modify('first day of last month');
            $e = (clone $today)->modify('last day of last month');
            return [$s->format('Y-m-d'), $e->format('Y-m-d')];
        default: // custom
            $f = $_GET['from'] ?? ''; $t = $_GET['to'] ?? '';
            if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $f) && preg_match('/^\d{4}-\d{2}-\d{2}$/', $t) && $f <= $t) {
                return [$f, $t];
            }
            // fallback на прошлую неделю
            $end = (clone $today)->modify('monday this week')->modify('-1 day');
            $start = (clone $end)->modify('-6 days');
            return [$start->format('Y-m-d'), $end->format('Y-m-d')];
    }
}
$period = $_GET['p'] ?? ($_SESSION['period'] ?? 'week');
if (!isset($PRESETS[$period]) && $period !== 'custom') $period = 'week';
if ($period === 'custom' && !isset($_GET['from'])) $period = 'week';
if (isset($_GET['p'])) $_SESSION['period'] = $period;
[$FROM, $TO] = period_range($period);
$FROM_D = date('d.m.Y', strtotime($FROM));
$TO_D = date('d.m.Y', strtotime($TO));
$P_LABEL = $period === 'custom' ? "Свои даты" : $PRESETS[$period];

if ($action === 'login' && $_SERVER['REQUEST_METHOD'] === 'POST') {
    $email = strtolower(trim($_POST['login'] ?? ''));
    $pass  = (string)($_POST['password'] ?? '');
    $ok = false;

    // админ
    if ($email === $SECRETS['admin_email'] && password_verify($pass, $SECRETS['admin_password_hash'])) {
        $ok = true;
        $_SESSION['user'] = ['email' => $email, 'role' => 'admin', 'client_ids' => []];
    } else {
        // клиент
        $u = db_users()->prepare('SELECT * FROM users WHERE login = ?');
        $u->execute([$email]);
        $row = $u->fetch(PDO::FETCH_ASSOC);
        if ($row && password_verify($pass, $row['password_hash'])) {
            $ok = true;
            $uc = db_users()->prepare('SELECT client_id FROM user_clients WHERE login = ?');
            $uc->execute([$email]);
            $client_ids = array_map(fn($r) => (int)$r['client_id'], $uc->fetchAll(PDO::FETCH_ASSOC));
            $_SESSION['user'] = ['email' => $email, 'role' => $row['role'], 'client_ids' => $client_ids];
        }
    }
    if ($ok) {
        header('Location: /direct/');
        exit;
    }
    $login_error = 'Неверный логин или пароль';
}

if ($action === 'logout') {
    session_destroy();
    header('Location: /direct/');
    exit;
}

$is_admin = $me['role'] === 'admin';

/* ── вкладка админки: stats | access | add | archive | kb ── */
$tab = $_GET['tab'] ?? 'stats';
if (!in_array($tab, ['stats', 'access', 'add', 'archive', 'kb'], true)) $tab = 'stats';

/* ── добавление нового клиента (Я.Директ) ── */
if ($is_admin && $action === 'add_direct' && $_SERVER['REQUEST_METHOD'] === 'POST') {
    $name = trim($_POST['name'] ?? '');
    $note = trim($_POST['note'] ?? '');
    $dlogin = trim($_POST['dlogin'] ?? '');
    $goal_id = trim($_POST['goal_id'] ?? '');
    $wb_raw = trim($_POST['weekly_budget'] ?? '');
    $wb_val = is_numeric($wb_raw) ? (float)$wb_raw : null;
    $oauth_code = trim($_POST['oauth_code'] ?? '');
    if ($name === '') {
        $_SESSION['flash_err'] = 'Укажите название клиента';
    } else {
        $db = db_main();
        $min = (int)$db->query("SELECT MIN(client_id) FROM clients WHERE client_id < 0")->fetchColumn();
        $cid = ($min < 0) ? $min - 1 : -1;
        $db->prepare("INSERT INTO clients (client_id, name, note, login, section, source, direct_login, goal_id, weekly_budget, updated_at)
                      VALUES (?,?,?,?, 'Директ', 'direct', ?, ?, ?, ?)")
           ->execute([$cid, $name, $note, $dlogin, $dlogin, $goal_id, $wb_val, date('Y-m-d H:i:s')]);
        // токен для аккаунта клиента (если кабинет в другом аккаунте Яндекса)
        if ($oauth_code !== '') {
            $tok = yandex_exchange_code($oauth_code);
            if (!$tok) {
                $db->prepare("DELETE FROM clients WHERE client_id = ?")->execute([$cid]);
                $_SESSION['flash_err'] = 'Не удалось обменять код подтверждения на токен. Проверьте код и попробуйте ещё раз.';
                header('Location: /direct/?tab=add');
                exit;
            }
            $db->prepare("UPDATE clients SET direct_token = ? WHERE client_id = ?")->execute([$tok, $cid]);
        }
        // запуск сбора данных — подхватит крон-помощник в течение минуты, прогресс виден в кабинете
        $db->prepare("UPDATE clients SET setup_status = 'running', setup_progress = 5, setup_msg = 'Клиент создан, запуск сбора…' WHERE client_id = ?")
           ->execute([$cid]);
        $users = db_users();
        $login = gen_login_php($name, $users);
        $password = gen_password_php($name);
        $cmd = sprintf("/usr/bin/php %s add %s %s %d", escapeshellarg('/opt/direct-dashboard/add_user.php'),
                       escapeshellarg($login), escapeshellarg($password), $cid);
        exec($cmd . ' 2>&1', $out, $rc);
        $_SESSION['flash_add'] = ['name' => $name, 'login' => $login, 'password' => $password];
    }
    header('Location: /direct/');
    exit;
}

/* ── редактирование клиента (Директ) ── */
if ($is_admin && $action === 'edit_client' && $_SERVER['REQUEST_METHOD'] === 'POST') {
    $cid = (int)($_POST['id'] ?? 0);
    $name = trim($_POST['name'] ?? '');
    $note = trim($_POST['note'] ?? '');
    $dlogin = trim($_POST['dlogin'] ?? '');
    $goal_id = trim($_POST['goal_id'] ?? '');
    $wb_raw = trim($_POST['weekly_budget'] ?? '');
    $wb = is_numeric($wb_raw) ? (float)$wb_raw : null;
    $oauth_code = trim($_POST['oauth_code'] ?? '');
    $db = db_main();
    if ($name === '') {
        $_SESSION['flash_err'] = 'Название клиента не может быть пустым';
    } else {
        $old = $db->prepare("SELECT goal_id, weekly_budget, direct_token FROM clients WHERE client_id = ?");
        $old->execute([$cid]);
        $old = $old->fetch(PDO::FETCH_ASSOC) ?: [];
        $db->prepare("UPDATE clients SET name = ?, note = ?, login = ?, goal_id = ?, weekly_budget = ?, updated_at = ?
                      WHERE client_id = ?")
           ->execute([$name, $note, $dlogin, $goal_id, $wb, date('Y-m-d H:i:s'), $cid]);
        // изменилась цель заявок или бюджет — пересчитываем статистику (крон-помощник подхватит)
        $need_recalc = ((string)($old['goal_id'] ?? '') !== $goal_id)
                    || ((string)($old['weekly_budget'] ?? '') !== (string)($wb ?? ''));
        // смена токена аккаунта (если введён новый код подтверждения)
        if ($oauth_code !== '') {
            $tok = yandex_exchange_code($oauth_code);
            if (!$tok) {
                $_SESSION['flash_err'] = 'Не удалось обменять код подтверждения на токен. Остальные изменения сохранены.';
            } else {
                $db->prepare("UPDATE clients SET direct_token = ? WHERE client_id = ?")->execute([$tok, $cid]);
                // пересбор с новым токеном — подхватит крон-помощник, прогресс в кабинете
                $db->prepare("UPDATE clients SET setup_status = 'running', setup_progress = 5, setup_msg = 'Токен обновлён, пересбор…' WHERE client_id = ?")
                   ->execute([$cid]);
                $_SESSION['flash_ok'] = 'Клиент обновлён. Токен аккаунта заменён.';
            }
        } else {
            $_SESSION['flash_ok'] = 'Клиент обновлён.';
        }
        // цель/бюджет изменились — запускаем пересбор статистики
        if (!empty($need_recalc) && $oauth_code === '') {
            $db->prepare("UPDATE clients SET setup_status = 'running', setup_progress = 5, setup_msg = 'Настройки изменены, пересбор статистики…' WHERE client_id = ?")
               ->execute([$cid]);
            $_SESSION['flash_ok'] = 'Клиент обновлён. Пересчёт статистики займёт до минуты.';
        }
    }
    header('Location: /direct/?a=client&id=' . $cid);
    exit;
}

/* ── архив клиента: act=1 в архив, act=0 вернуть ── */
if ($is_admin && $action === 'archive' && $_SERVER['REQUEST_METHOD'] === 'POST') {
    $cid = (int)($_POST['id'] ?? 0);
    $act = (int)($_POST['act'] ?? 1);
    $db = db_main();
    if ($act === 1) {
        $db->prepare("UPDATE clients SET archived = 1, archived_at = datetime('now') WHERE client_id = ?")->execute([$cid]);
        $_SESSION['flash_ok'] = 'Клиент перенесён в архив';
        header('Location: /direct/');
    } else {
        $db->prepare("UPDATE clients SET archived = 0, archived_at = NULL WHERE client_id = ?")->execute([$cid]);
        $_SESSION['flash_ok'] = 'Клиент возвращён из архива';
        header('Location: /direct/?tab=archive');
    }
    exit;
}

/* ── статус настройки кабинета (JSON для прогресс-бара) ── */
if ($action === 'setup_status' && isset($_GET['id'])) {
    $cid = (int)$_GET['id'];
    $allowed = $is_admin || in_array($cid, $me['client_ids'] ?? [], true);
    header('Content-Type: application/json');
    if (!$allowed) { echo json_encode(['error' => 1]); exit; }
    $db = db_main();
    $r = $db->prepare("SELECT setup_status, setup_progress, setup_msg FROM clients WHERE client_id = ?");
    $r->execute([$cid]);
    $row = $r->fetch(PDO::FETCH_ASSOC);
    echo json_encode($row ?: ['setup_status' => 'done', 'setup_progress' => 100, 'setup_msg' => '']);
    exit;
}
if ($is_admin && $action === 'set_budget' && $_SERVER['REQUEST_METHOD'] === 'POST') {
    $cid = (int)($_POST['id'] ?? 0);
    $wb_raw = trim($_POST['weekly_budget'] ?? '');
    $wb = is_numeric($wb_raw) ? (float)$wb_raw : null;
    $db = db_main();
    $db->prepare("UPDATE clients SET weekly_budget = ? WHERE client_id = ?")->execute([$wb, $cid]);
    $_SESSION['flash_ok'] = 'Недельный бюджет сохранён: ' . ($wb !== null ? number_format($wb, 0, '.', ' ') . ' ₽' : 'не указан');
    header('Location: /direct/?a=client&id=' . $cid);
    exit;
}

/* ── права: какие клиенты видит пользователь ── */
function visible_client_ids(?array $me): ?array {
    if (!$me) return null;
    if ($me['role'] === 'admin') return null; // все
    return $me['client_ids'] ?? [];
}

if (!$me) {
    /* ── страница входа ── */
    ?><!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Вход — Я.Директ дашборд</title>
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<link rel="stylesheet" href="assets/style.css">
</head>
<body class="login-body">
<div class="login-card">
  <div class="login-logo">📊</div>
  <h1>Я.Директ дашборд</h1>
  <p class="login-sub">Статистика рекламных кабинетов</p>
  <?php if (!empty($login_error)): ?><div class="alert alert-red"><?= htmlspecialchars($login_error) ?></div><?php endif; ?>
  <form method="post" action="?a=login">
    <div class="form-group">
      <label>Логин</label>
      <input type="text" name="login" required autofocus placeholder="ваш логин">
    </div>
    <div class="form-group">
      <label>Пароль</label>
      <input type="password" name="password" required placeholder="••••••••">
    </div>
    <button type="submit" class="btn btn-primary btn-block">Войти</button>
  </form>
</div>
</body>
</html><?php
    exit;
}

/* ── данные для дашборда ── */
$db = db_main();
$ids = visible_client_ids($me);

// фактический расход за 7 дней (для остатка директ-клиентов)
$direct7 = [];
foreach ($db->query("SELECT k.client_id, SUM(d.cost) AS cost7 FROM campaigns k
    JOIN daily_stats d ON d.campaign_id = k.campaign_id
    WHERE d.date >= date('now','-6 days') GROUP BY k.client_id") as $r7) {
    $direct7[(int)$r7['client_id']] = (float)$r7['cost7'];
}

// списки материалов базы знаний (для меню админки)
$kb_akk = []; $kb_faq = [];
if ($me && $me['role'] === 'admin') {
    foreach ($db->query("SELECT slug, title, sort_order, section_slug FROM kb_articles ORDER BY sort_order") as $kr) {
        if (($kr['section_slug'] ?? '') === 'faq') $kb_faq[] = $kr; else $kb_akk[] = $kr;
    }
}

// страница кабинета одного клиента (для админа)
if ($is_admin && $action === 'client' && isset($_GET['id'])) {
    $cid = (int)$_GET['id'];
    $c = $db->prepare("SELECT c.*,
        COALESCE(SUM(d.cost),0) AS cost_p, COALESCE(SUM(d.conv),0) AS conv_p, COALESCE(SUM(d.leads),0) AS leads_p
        FROM clients c
        LEFT JOIN campaigns k ON k.client_id = c.client_id
        LEFT JOIN daily_stats d ON d.campaign_id = k.campaign_id AND d.date BETWEEN ? AND ?
        WHERE c.client_id = ? GROUP BY c.client_id");
    $c->execute([$FROM, $TO, $cid]);
    $c = $c->fetch(PDO::FETCH_ASSOC);
    if (!$c) { header('Location: /direct/'); exit; }
    $camps = $db->prepare("SELECT k.*, COALESCE(d.cost,0) AS cost_p, COALESCE(d.conv,0) AS conv_p, COALESCE(d.leads,0) AS leads_p
        FROM campaigns k
        LEFT JOIN (SELECT campaign_id, SUM(cost) cost, SUM(conv) conv, SUM(leads) leads
                   FROM daily_stats WHERE date BETWEEN ? AND ? GROUP BY campaign_id) d ON d.campaign_id = k.campaign_id
        WHERE k.client_id = ? ORDER BY k.campaigntip, k.campaign_id");
    $camps->execute([$FROM, $TO, $cid]);
    $camps = $camps->fetchAll(PDO::FETCH_ASSOC);
    $bal_hist = balance_history($db, [$cid]);
    // дневной ряд для графика
    $daily_rows = $db->prepare("SELECT date, SUM(cost) AS cost, SUM(leads) AS leads FROM daily_stats
        WHERE campaign_id IN (SELECT campaign_id FROM campaigns WHERE client_id = ?) AND date BETWEEN ? AND ?
        GROUP BY date ORDER BY date");
    $daily_rows->execute([$cid, $FROM, $TO]);
    $daily_rows = $daily_rows->fetchAll(PDO::FETCH_ASSOC);
    ?><!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?= htmlspecialchars($c['name']) ?> — Я.Директ дашборд</title>
<link rel="stylesheet" href="assets/style.css">
</head>
<body>
<header class="topbar"><div class="topbar-inner">
  <div class="brand">📊 <b>Я.Директ</b> <span class="brand-sub">дашборд кабинетов</span></div>
  <div class="topbar-right">
    <?= period_menu($PRESETS, $period, '?a=client&id=' . $cid . '&', $FROM, $TO) ?>
    <a class="btn btn-sm" href="/direct/">← Все клиенты</a>
    <?php if ((int)($c['archived'] ?? 0) === 1): ?>
      <span class="btn btn-sm st-stop" style="pointer-events:none">В архиве</span>
      <form method="post" action="?a=archive" style="display:inline">
        <input type="hidden" name="id" value="<?= (int)$cid ?>">
        <input type="hidden" name="act" value="0">
        <button type="submit" class="btn btn-sm">Вернуть из архива</button>
      </form>
    <?php else: ?>
      <form method="post" action="?a=archive" style="display:inline" onsubmit="return confirm('Перенести клиента в архив? Он исчезнет из статистики.')">
        <input type="hidden" name="id" value="<?= (int)$cid ?>">
        <input type="hidden" name="act" value="1">
        <button type="submit" class="btn btn-sm btn-danger">В архив</button>
      </form>
    <?php endif; ?>
    <span class="who"><?= htmlspecialchars($me['email']) ?></span>
    <a class="btn btn-sm" href="?a=logout">Выйти</a>
  </div>
</div></header>
<main class="wrap">
  <section class="cards">
    <div class="card"><div class="card-label">Расход · <?= $P_LABEL ?></div><div class="card-value"><?= money($c['cost_p']) ?></div><div class="card-sub"><?= $FROM_D ?> — <?= $TO_D ?></div></div>
    <div class="card"><div class="card-label">Заявки · <?= $P_LABEL ?></div><div class="card-value"><?= num($c['leads_p']) ?></div><div class="card-sub">CPL <?= cpl($c['cost_p'], $c['leads_p']) ?></div></div>
    <div class="card"><div class="card-label">CPL · <?= $P_LABEL ?></div><div class="card-value"><?= cpl($c['cost_p'], $c['leads_p']) ?></div><div class="card-sub">цена лида</div></div>
    <div class="card"><div class="card-label">Баланс кабинета</div><div class="card-value <?= (float)$c['balance'] < 3000 ? 'txt-red' : '' ?>"><?= money($c['balance']) ?></div><div class="card-sub">остаток: <b class="<?= forecast_color(direct_forecast($c, $direct7)) ?>"><?= htmlspecialchars(direct_forecast($c, $direct7)) ?></b> · лимит <?= money($c['limit_'] ?? $c['alt_limit']) ?></div></div>
  </section>

  <?php if (($c['source'] ?? 'crm') === 'direct' && ($c['setup_status'] ?? 'done') !== 'done'): ?>
  <section class="panel" id="setup-panel">
    <div class="panel-h"><h2>Настройка кабинета</h2><span class="hint">подключение к Яндексу</span></div>
    <div class="setup-bar"><div class="setup-fill" id="setup-fill" style="width:<?= (int)($c['setup_progress'] ?? 0) ?>%"></div></div>
    <div class="setup-meta"><b id="setup-pct"><?= (int)($c['setup_progress'] ?? 0) ?>%</b> · <span id="setup-msg"><?= htmlspecialchars($c['setup_msg'] ?? '') ?></span></div>
  </section>
  <?php endif; ?>

  <?php if (!empty($_SESSION['flash_ok'])): ?>
    <div class="alert alert-green"><?= htmlspecialchars($_SESSION['flash_ok']) ?></div>
    <?php unset($_SESSION['flash_ok']); ?>
  <?php endif; ?>

  <?php if ($is_admin && ($c['source'] ?? 'crm') === 'direct'): ?>
  <section class="panel">
    <div class="panel-h"><h2>Настройки кабинета</h2><span class="hint">редактирование клиента</span></div>
    <form method="post" action="?a=edit_client" class="add-form">
      <input type="hidden" name="id" value="<?= (int)$cid ?>">
      <input type="text" name="name" value="<?= htmlspecialchars($c['name'] ?? '') ?>" placeholder="Название клиента" required>
      <input type="text" name="note" value="<?= htmlspecialchars($c['note'] ?? '') ?>" placeholder="Город">
      <input type="text" name="dlogin" value="<?= htmlspecialchars($c['login'] ?? '') ?>" placeholder="Логин кабинета Я.Директ (пусто = основной)">
      <input type="text" name="goal_id" value="<?= htmlspecialchars($c['goal_id'] ?? '') ?>" placeholder="ID цели заявок (order_done)">
      <input type="text" name="weekly_budget" value="<?= htmlspecialchars((string)($c['weekly_budget'] ?? '')) ?>" placeholder="Недельный бюджет, ₽">
      <input type="text" name="oauth_code" placeholder="Новый код доступа (сменить аккаунт)" style="min-width:260px">
      <button type="submit" class="btn btn-primary">Сохранить</button>
    </form>
    <div class="hint" style="margin-top:10px;line-height:1.55">
      Остаток дней = баланс ÷ (бюджет ÷ 7). Если бюджет пустой — по фактическому среднему расходу за 7 дней.<br>
      <b>Сменить аккаунт клиента:</b> нажми <a href="https://oauth.yandex.ru/authorize?response_type=code&client_id=18476717535549aba73d77da1bcd4f57&redirect_uri=https%3A%2F%2Foauth.yandex.ru%2Fverification_code&force_confirm=1" target="_blank" rel="noopener"><b>Получить код доступа</b></a>, войди под нужным аккаунтом и вставь код в поле «Новый код доступа».
    </div>
  </section>
  <?php endif; ?>

  <section class="panel">
    <div class="panel-h"><h2>Отчёт для клиента</h2><span class="hint">скопируйте и отправьте клиенту</span>
      <button type="button" class="copy-report-btn" title="Скопировать текст">
        <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
        <span class="crp-txt">Копировать</span>
      </button>
    </div>
    <?php
      $report_text = "За период с " . $FROM_D . " по " . $TO_D . "\n"
        . "Получили " . num($c['leads_p']) . " заявок по цене " . cpl($c['cost_p'], $c['leads_p']) . "\n"
        . "Остаток баланса " . money($c['balance']) . " (" . direct_forecast($c, $direct7) . ")";
    ?>
    <pre class="report-text" id="report-text"><?= htmlspecialchars($report_text) ?></pre>
  </section>

  <section class="panel">
    <div class="panel-h"><h2><?= htmlspecialchars($c['name']) ?></h2>
      <span class="hint"><?= htmlspecialchars($c['note'] ?? '') ?> · логин <?= htmlspecialchars($c['login'] ?? '') ?> · <?= htmlspecialchars($c['section'] ?? '') ?>
        · маркетолог <?= htmlspecialchars($c['marketolog'] ?? '') ?> · директолог <?= htmlspecialchars($c['directolog'] ?? '') ?></span></div>
    <?php if ($daily_rows): ?>
      <div class="daily-view">
        <div class="view-toggle">
          <span class="vt-label">По дням:</span>
          <button type="button" class="vt-btn vt-active" data-view="chart">График</button>
          <button type="button" class="vt-btn" data-view="table">Таблица</button>
          <a class="btn btn-sm xls-btn" href="export.php?cab=<?= (int)($cab ?? $cid) ?>&from=<?= $FROM ?>&to=<?= $TO ?>">Скачать в Excel</a>
        </div>
        <div class="vt-pane vt-chart"><canvas id="daily-chart" height="90"></canvas></div>
        <div class="vt-pane vt-table" hidden><?= daily_table_html($daily_rows, $FROM_D, $TO_D) ?></div>
      </div>
    <?php else: ?>
      <div class="hint">Нет дневных данных за выбранный период (история накапливается ежедневно)</div>
    <?php endif; ?>
    <?php if ($bal_hist): ?><canvas id="bal-chart" height="80"></canvas><?php endif; ?>
  </section>

  <section class="panel">
    <div class="panel-h"><h2>Кампании</h2><span class="hint"><?= count($camps) ?> · <?= $FROM_D ?> — <?= $TO_D ?></span></div>
    <div class="table-wrap">
    <table class="tbl">
      <thead><tr>
        <th>Кампания</th><th class="num">Статус</th>
        <th class="num">Расход</th><th class="num">Заявки</th><th class="num">CPL</th>
      </tr></thead>
      <tbody>
      <?php foreach ($camps as $k): ?>
        <tr>
          <td class="mono"><?= htmlspecialchars($k['campaign_id']) ?></td>
          <td class="num"><span class="st <?= $k['campaigntip'] === 'Стоп' ? 'st-stop' : 'st-run' ?>"><?= htmlspecialchars($k['campaigntip']) ?></span></td>
          <td class="num"><?= money($k['cost_p']) ?></td>
          <td class="num"><?= num($k['leads_p']) ?></td>
          <td class="num"><?= cpl($k['cost_p'], $k['leads_p']) ?></td>
        </tr>
      <?php endforeach; ?>
      </tbody>
    </table>
    </div>
  </section>
</main>
<script>
const BAL_HISTORY = <?= json_encode($bal_hist, JSON_UNESCAPED_UNICODE) ?>;
const DAILY = <?= json_encode($daily_rows, JSON_UNESCAPED_UNICODE) ?>;
</script>
<script src="assets/chart.umd.min.js"></script>
<script src="assets/app.js"></script>
</body>
</html><?php
    exit;
}

// общая дата последнего обновления
$upd = $db->query("SELECT MAX(updated_at) FROM clients")->fetchColumn();

// сводка по клиентам: расход/заявки за выбранный период из daily_stats
$sql = "SELECT c.client_id, c.name, c.login, c.note, c.section, c.marketolog, c.directolog,
               c.balance, c.limit_ AS lim, c.alt_limit, c.forecast, c.source, c.weekly_budget,
               COALESCE(SUM(d.cost),0)  AS cost_p,
               COALESCE(SUM(d.conv),0)  AS conv_p,
               COALESCE(SUM(d.leads),0) AS leads_p
        FROM clients c
        LEFT JOIN campaigns k ON k.client_id = c.client_id
        LEFT JOIN daily_stats d ON d.campaign_id = k.campaign_id AND d.date BETWEEN ? AND ?
        WHERE c.archived = 0
        GROUP BY c.client_id
        ORDER BY c.name";
$stmt = $db->prepare($sql);
if ($ids !== null) {
    $in = implode(',', array_map('intval', $ids));
    // клиент видит только свои кабинеты (архивный фильтр уже в запросе)
    $sql = str_replace('WHERE c.archived = 0', "WHERE c.archived = 0 AND c.client_id IN ($in)", $sql);
    $stmt = $db->prepare($sql);
}
$stmt->execute([$FROM, $TO]);
$clients = $stmt->fetchAll(PDO::FETCH_ASSOC);

?><!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Я.Директ дашборд<?= $is_admin ? '' : ' — ' . htmlspecialchars($clients[0]['name'] ?? '') ?></title>
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<link rel="stylesheet" href="assets/style.css">
</head>
<body>
<header class="topbar">
  <div class="topbar-inner">
    <div class="brand">📊 <b>Я.Директ</b> <span class="brand-sub">дашборд кабинетов</span></div>
    <div class="topbar-right">
      <?= period_menu($PRESETS, $period, '?', $FROM, $TO) ?>
      <span class="upd">обновлено: <?= htmlspecialchars((string)$upd) ?></span>
      <span class="who"><?= htmlspecialchars($me['email']) ?></span>
      <a class="btn btn-sm" href="?a=logout">Выйти</a>
    </div>
  </div>
</header>

<main class="wrap">
<?php if ($is_admin): ?>
<div class="admin-layout">
  <aside class="sidebar">
    <div class="side-title">Меню</div>
    <nav class="side-nav">
      <a class="side-link<?= $tab === 'stats' ? ' active' : '' ?>" href="?tab=stats">Статистика клиентов</a>
      <a class="side-link<?= $tab === 'access' ? ' active' : '' ?>" href="?tab=access">Доступы клиентов</a>
      <a class="side-link<?= $tab === 'add' ? ' active' : '' ?>" href="?tab=add">Добавить клиента</a>
      <a class="side-link<?= $tab === 'archive' ? ' active' : '' ?>" href="?tab=archive">Архив клиентов</a>
      <div class="side-group<?= $tab === 'kb' && !isset($_GET['qa']) && !in_array($_GET['slug'] ?? '', array_column($kb_faq, 'slug'), true) ? ' open' : '' ?>">
        <a class="side-link side-toggle<?= $tab === 'kb' && !isset($_GET['qa']) ? ' active' : '' ?>" href="?tab=kb">
          <span>Аккаунтинг</span><span class="chev">▾</span>
        </a>
        <div class="side-sub">
          <?php $kb_cur = $_GET['slug'] ?? ($kb_akk[0]['slug'] ?? ''); ?>
          <?php foreach ($kb_akk as $kr): ?>
            <a class="side-link side-sub-link<?= ($tab === 'kb' && !isset($_GET['qa']) && $kb_cur === $kr['slug']) ? ' active' : '' ?>"
               href="?tab=kb&slug=<?= urlencode($kr['slug']) ?>"><?= htmlspecialchars($kr['title']) ?></a>
          <?php endforeach; ?>
        </div>
      </div>
      <div class="side-group<?= $tab === 'kb' && (isset($_GET['qa']) || in_array($_GET['slug'] ?? '', array_column($kb_faq, 'slug'), true)) ? ' open' : '' ?>">
        <a class="side-link side-toggle<?= $tab === 'kb' && isset($_GET['qa']) ? ' active' : '' ?>" href="?tab=kb&qa=1">
          <span>FAQ и возражения</span><span class="chev">▾</span>
        </a>
        <div class="side-sub">
          <?php foreach ($kb_faq as $kr): ?>
            <a class="side-link side-sub-link<?= ($tab === 'kb' && !isset($_GET['qa']) && ($_GET['slug'] ?? '') === $kr['slug']) ? ' active' : '' ?>"
               href="?tab=kb&slug=<?= urlencode($kr['slug']) ?>"><?= htmlspecialchars($kr['title']) ?></a>
          <?php endforeach; ?>
          <a class="side-link side-sub-link<?= ($tab === 'kb' && isset($_GET['qa'])) ? ' active' : '' ?>" href="?tab=kb&qa=1">Вопросы и ответы</a>
        </div>
      </div>
    </nav>
  </aside>
  <div class="admin-main">

  <?php if ($tab === 'stats'): ?>
  <?php
    $tc = array_sum(array_column($clients, 'cost_p'));
    $lc = array_sum(array_column($clients, 'leads_p'));
    $bal = array_sum(array_column($clients, 'balance'));
    $low = count(array_filter($clients, fn($c) => $c['balance'] < 3000));
  ?>
  <section class="cards">
    <div class="card"><div class="card-label">Расход · <?= $P_LABEL ?></div><div class="card-value"><?= money($tc) ?></div><div class="card-sub"><?= $FROM_D ?> — <?= $TO_D ?> · все кабинеты</div></div>
    <div class="card"><div class="card-label">Заявки · <?= $P_LABEL ?></div><div class="card-value"><?= num($lc) ?></div><div class="card-sub">CPL <?= cpl($tc, $lc) ?></div></div>
    <div class="card"><div class="card-label">CPL · <?= $P_LABEL ?></div><div class="card-value"><?= cpl($tc, $lc) ?></div><div class="card-sub">цена лида</div></div>
    <div class="card"><div class="card-label">Балансы клиентов</div><div class="card-value"><?= money($bal) ?></div><div class="card-sub <?= $low ? 'txt-red' : '' ?>"><?= count($clients) ?> кабинетов · <?= $low ?> с балансом &lt; 3 000 ₽</div></div>
  </section>

  <section class="panel">
    <div class="panel-h"><h2>Клиенты</h2><span class="hint"><?= count($clients) ?> кабинетов · <?= $FROM_D ?> — <?= $TO_D ?></span></div>
    <div class="table-wrap">
    <table class="tbl" id="clients-tbl">
      <thead>
        <tr>
          <th data-k="name">Клиент</th>
          <th data-k="cost" class="num">Расход</th>
          <th data-k="leads" class="num">Заявки</th>
          <th data-k="cpl" class="num">CPL</th>
          <th data-k="balance" class="num">Баланс</th>
          <th data-k="forecast" class="num">Остаток</th>
          <th class="num"></th>
        </tr>
      </thead>
      <tbody>
        <?php foreach ($clients as $c):
          $cost_v = (float)$c['cost_p'];
          $leads_v = (float)$c['leads_p'];
          $fc = direct_forecast($c, $direct7);
        ?>
        <tr class="cl-row" data-id="<?= (int)$c['client_id'] ?>" data-cost="<?= $cost_v ?>" data-leads="<?= $leads_v ?>" data-cpl="<?= $leads_v > 0 ? round($cost_v / $leads_v, 2) : 0 ?>" data-balance="<?= (float)$c['balance'] ?>" data-forecast="<?= forecast_days($fc) ?? 0 ?>">
          <td>
            <div class="cl-name"><?= htmlspecialchars($c['name']) ?></div>
            <div class="cl-sub"><?= htmlspecialchars($c['note']) ?> · <?= htmlspecialchars($c['login']) ?></div>
          </td>
          <td class="num"><?= money($cost_v) ?></td>
          <td class="num"><?= num($leads_v) ?></td>
          <td class="num"><?= cpl($cost_v, $leads_v) ?></td>
          <td class="num <?= (float)$c['balance'] < 3000 ? 'txt-red' : '' ?>"><?= money($c['balance']) ?></td>
          <td class="num <?= forecast_color($fc) ?>"><b><?= htmlspecialchars($fc) ?></b></td>
          <td class="num">
            <form method="post" action="?a=archive" style="display:inline" onsubmit="return confirm('Перенести клиента в архив?')">
              <input type="hidden" name="id" value="<?= (int)$c['client_id'] ?>">
              <input type="hidden" name="act" value="1">
              <button type="submit" class="btn btn-sm btn-arch" title="В архив">В архив</button>
            </form>
          </td>
        </tr>
        <?php endforeach; ?>
      </tbody>
    </table>
    </div>
  </section>
  <?php elseif ($tab === 'access'): ?>
  <section class="panel">
    <div class="panel-h"><h2>Доступы клиентов</h2><span class="hint">логин и пароль для выдачи клиентам</span></div>
    <div class="table-wrap">
    <table class="tbl" id="access-tbl">
      <thead><tr>
        <th>Клиент</th><th>Логин</th><th>Пароль</th><th class="num"></th>
      </tr></thead>
      <tbody>
      <?php
        $up = db_users();
        $acc_rows = $up->query("SELECT u.login, p.plain_password
              FROM users u LEFT JOIN user_passwords p ON p.login = u.login
              WHERE u.role = 'client' ORDER BY u.login")->fetchAll(PDO::FETCH_ASSOC);
        $name_by_id = [];
        foreach ($db->query("SELECT client_id, name, note FROM clients") as $n) {
            $name_by_id[$n['client_id']] = $n['name'] . ' (' . $n['note'] . ')';
        }
        $accs = [];
        $st = $up->prepare('SELECT client_id FROM user_clients WHERE login = ?');
        foreach ($acc_rows as $r) {
            $st->execute([$r['login']]);
            $strs = [];
            foreach (array_column($st->fetchAll(PDO::FETCH_ASSOC), 'client_id') as $cid) {
                $strs[] = $name_by_id[$cid] ?? ('кабинет #' . $cid);
            }
            $r['clients_str'] = implode('; ', $strs);
            $accs[] = $r;
        }
        foreach ($accs as $a): ?>
        <tr data-login="<?= htmlspecialchars($a['login']) ?>" data-pass="<?= htmlspecialchars($a['plain_password']) ?>">
          <td><?= htmlspecialchars($a['clients_str'] ?? '—') ?></td>
          <td class="mono"><?= htmlspecialchars($a['login']) ?></td>
          <td class="mono"><?= htmlspecialchars($a['plain_password'] ?? '—') ?></td>
          <td class="num"><button type="button" class="btn btn-sm copy-btn">Копировать</button></td>
        </tr>
        <?php endforeach; ?>
      </tbody>
    </table>
    </div>
  </section>
  <?php elseif ($tab === 'add'): ?>
  <section class="panel">
    <div class="panel-h"><h2>Добавить клиента (Я.Директ)</h2><span class="hint">кабинет с доступом через API Директа — данные подтянутся автоматически</span></div>
    <?php if (!empty($_SESSION['flash_add'])): $fa = $_SESSION['flash_add']; unset($_SESSION['flash_add']); ?>
      <div class="alert alert-green">
        <b>Клиент «<?= htmlspecialchars($fa['name']) ?>» добавлен.</b><br>
        Ссылка для клиента: <b>https://gubtor.ru/direct/</b><br>
        Логин: <b><?= htmlspecialchars($fa['login']) ?></b> · Пароль: <b><?= htmlspecialchars($fa['password']) ?></b><br>
        <span class="hint">Данные начнут собираться после ближайшего обновления (раз в 10 минут)</span>
      </div>
    <?php endif; ?>
    <?php if (!empty($_SESSION['flash_err'])): ?>
      <div class="alert alert-red"><?= htmlspecialchars($_SESSION['flash_err']) ?></div>
      <?php unset($_SESSION['flash_err']); ?>
    <?php endif; ?>
    <form method="post" action="?a=add_direct" class="add-form">
      <input type="text" name="name" placeholder="Название клиента (например: ИП Молодцов)" required>
      <input type="text" name="note" placeholder="Город (необязательно)">
      <input type="text" name="dlogin" placeholder="Логин кабинета Я.Директ (пусто = основной кабинет)">
      <input type="text" name="goal_id" placeholder="ID цели заявок (order_done) — необязательно">
      <input type="text" name="weekly_budget" placeholder="Недельный бюджет, ₽ (необязательно)">
      <input type="text" name="oauth_code" placeholder="Код подтверждения (если кабинет в другом аккаунте)">
      <button type="submit" class="btn btn-primary">Добавить клиента</button>
    </form>
    <div class="hint" style="margin-top:10px;line-height:1.55">
      Остаток дней = баланс ÷ (недельный бюджет / 7). Если бюджет не указан — по фактическому среднему расходу за 7 дней. ID цели нужен, чтобы заявки считались только по order_done.<br>
      <b>Клиент в другом аккаунте Яндекса?</b> Нажми <a href="https://oauth.yandex.ru/authorize?response_type=code&client_id=18476717535549aba73d77da1bcd4f57&redirect_uri=https%3A%2F%2Foauth.yandex.ru%2Fverification_code&force_confirm=1" target="_blank" rel="noopener"><b>Получить код доступа</b></a> — войди под аккаунтом этого клиента, разреши доступ и вставь код подтверждения в поле выше. Кабинет будет подключён со своим токеном.
    </div>
  </section>
  <?php elseif ($tab === 'archive'): ?>
  <?php
    $arch = $db->query("SELECT client_id, name, note, login, source, balance, archived_at, weekly_budget
                        FROM clients WHERE archived = 1 ORDER BY archived_at DESC")->fetchAll(PDO::FETCH_ASSOC);
  ?>
  <section class="panel">
    <div class="panel-h"><h2>Архив клиентов</h2><span class="hint"><?= count($arch) ?> · не показываются в статистике</span></div>
    <?php if (!empty($_SESSION['flash_ok'])): ?>
      <div class="alert alert-green"><?= htmlspecialchars($_SESSION['flash_ok']) ?></div>
      <?php unset($_SESSION['flash_ok']); ?>
    <?php endif; ?>
    <?php if (!$arch): ?>
      <div class="hint">Архив пуст. Клиенты попадают сюда вручную (кнопка «В архив») или автоматически — через 3 дня нулевого баланса.</div>
    <?php else: ?>
    <div class="table-wrap">
    <table class="tbl">
      <thead><tr>
        <th>Клиент</th><th>Источник</th><th>Баланс</th><th>В архиве с</th><th class="num"></th>
      </tr></thead>
      <tbody>
        <?php foreach ($arch as $a): ?>
        <tr>
          <td>
            <a class="cl-name" href="?a=client&id=<?= (int)$a['client_id'] ?>" style="text-decoration:none"><?= htmlspecialchars($a['name']) ?></a>
            <div class="cl-sub"><?= htmlspecialchars($a['note']) ?></div>
          </td>
          <td><?= ($a['source'] ?? 'crm') === 'direct' ? 'Директ' : 'CRM' ?></td>
          <td class="num"><?= money($a['balance']) ?></td>
          <td class="num"><?= htmlspecialchars(substr((string)$a['archived_at'], 0, 10)) ?></td>
          <td class="num">
            <form method="post" action="?a=archive" style="display:inline">
              <input type="hidden" name="id" value="<?= (int)$a['client_id'] ?>">
              <input type="hidden" name="act" value="0">
              <button type="submit" class="btn btn-sm">Вернуть из архива</button>
            </form>
          </td>
        </tr>
        <?php endforeach; ?>
      </tbody>
    </table>
    </div>
    <?php endif; ?>
  </section>
  <?php elseif ($tab === 'kb'): ?>
  <?php if (isset($_GET['qa'])): ?>
    <?php
      $qs = $db->query("SELECT question, answer FROM kb_questions ORDER BY sort_order, id")->fetchAll(PDO::FETCH_ASSOC);
    ?>
    <section class="panel kb-panel">
      <h1 class="kb-title">Вопросы и ответы</h1>
      <div class="hint" style="margin-bottom:12px">Возражения и частые вопросы — <?= count($qs) ?> шт. Клик по вопросу раскрывает ответ.</div>
      <?php foreach ($qs as $qq): ?>
        <details class="kb-qa">
          <summary><?= htmlspecialchars($qq['question']) ?></summary>
          <div class="kb-qa-body"><?= kb_render_md((string)$qq['answer']) ?></div>
        </details>
      <?php endforeach; ?>
    </section>
  <?php else: ?>
    <?php
      $arts = $db->query("SELECT slug, title, sort_order, section_slug FROM kb_articles ORDER BY sort_order")->fetchAll(PDO::FETCH_ASSOC);
      $slug = $_GET['slug'] ?? ($arts[0]['slug'] ?? '');
      $cur = null;
      foreach ($arts as $a) { if ($a['slug'] === $slug) { $cur = $a; break; } }
      if (!$cur && $arts) $cur = $arts[0];
      $body = '';
      if ($cur) {
          $st = $db->prepare("SELECT body_md FROM kb_articles WHERE slug = ?");
          $st->execute([$cur['slug']]);
          $body = kb_render_md((string)$st->fetchColumn());
      }
    ?>
    <section class="panel kb-panel">
      <div class="kb-body">
        <?php if ($cur): ?>
          <h1 class="kb-title"><?= htmlspecialchars($cur['title']) ?></h1>
          <?= $body ?>
        <?php else: ?>
          <div class="hint">Раздел пуст — запустите синхронизацию (kb_sync.py)</div>
        <?php endif; ?>
      </div>
    </section>
  <?php endif; ?>
  <?php endif; ?>

  </div>
</div>
<?php else: ?>
  <?php
    $my_ids = $me['client_ids'] ?? [];
    // активный кабинет (вкладка): ?cab=N, по умолчанию первый
    $cab = (int)($_GET['cab'] ?? ($my_ids[0] ?? 0));
    if (!in_array($cab, $my_ids)) $cab = (int)($my_ids[0] ?? 0);
    $c = null;
    foreach ($clients as $row) { if ((int)$row['client_id'] === $cab) { $c = $row; break; } }
    if ($c):
    $cost_v = (float)$c['cost_p'];
    $leads_v = (float)$c['leads_p'];
    $my_daily = [];
    $st = $db->prepare("SELECT date, SUM(cost) AS cost, SUM(leads) AS leads FROM daily_stats
        WHERE campaign_id IN (SELECT campaign_id FROM campaigns WHERE client_id = ?) AND date BETWEEN ? AND ?
        GROUP BY date ORDER BY date");
    $st->execute([$cab, $FROM, $TO]);
    $my_daily = $st->fetchAll(PDO::FETCH_ASSOC);
    $bal_hist = balance_history($db, [$cab]);
    // вкладки: несколько кабинетов у клиента
    $tabs = '';
    if (count($my_ids) > 1) {
        $by_id = [];
        foreach ($clients as $row) $by_id[(int)$row['client_id']] = $row;
        foreach ($my_ids as $mid) {
            $rr = $by_id[$mid] ?? null;
            $label = $rr ? trim($rr['note']) : ('Кабинет ' . $mid);
            if ($label === '') $label = $rr ? $rr['name'] : ('Кабинет ' . $mid);
            $active = $mid === $cab ? ' tab-active' : '';
            $tabs .= '<a class="tab' . $active . '" href="?cab=' . $mid . '&p=' . htmlspecialchars($period) . '">' . htmlspecialchars($label) . '</a>';
        }
        $tabs = '<div class="tabs">' . $tabs . '</div>';
    }
  ?>
  <?php if ($tabs): ?><div class="panel"><?= $tabs ?></div><?php endif; ?>
  <section class="cards">
    <div class="card"><div class="card-label">Расход · <?= $P_LABEL ?></div><div class="card-value"><?= money($cost_v) ?></div><div class="card-sub"><?= $FROM_D ?> — <?= $TO_D ?></div></div>
    <div class="card"><div class="card-label">Заявки · <?= $P_LABEL ?></div><div class="card-value"><?= num($leads_v) ?></div><div class="card-sub">CPL <?= cpl($cost_v, $leads_v) ?></div></div>
    <div class="card"><div class="card-label">CPL · <?= $P_LABEL ?></div><div class="card-value"><?= cpl($cost_v, $leads_v) ?></div><div class="card-sub">цена лида</div></div>
    <div class="card"><div class="card-label">Баланс кабинета</div><div class="card-value <?= (float)$c['balance'] < 3000 ? 'txt-red' : '' ?>"><?= money($c['balance']) ?></div><div class="card-sub">остаток: <b class="<?= forecast_color(direct_forecast($c, $direct7)) ?>"><?= htmlspecialchars(direct_forecast($c, $direct7)) ?></b></div></div>
  </section>

  <section class="panel">
    <div class="panel-h"><h2><?= htmlspecialchars($c['name']) ?></h2><span class="hint"><?= htmlspecialchars($c['note']) ?> · <?= $FROM_D ?> — <?= $TO_D ?></span></div>
    <?php if ($my_daily): ?>
      <div class="daily-view">
        <div class="view-toggle">
          <span class="vt-label">По дням:</span>
          <button type="button" class="vt-btn vt-active" data-view="chart">График</button>
          <button type="button" class="vt-btn" data-view="table">Таблица</button>
          <a class="btn btn-sm xls-btn" href="export.php?cab=<?= (int)($cab ?? $cid) ?>&from=<?= $FROM ?>&to=<?= $TO ?>">Скачать в Excel</a>
        </div>
        <div class="vt-pane vt-chart"><canvas id="daily-chart" height="90"></canvas></div>
        <div class="vt-pane vt-table" hidden><?= daily_table_html($my_daily, $FROM_D, $TO_D) ?></div>
      </div>
    <?php else: ?>
      <div class="hint">Нет дневных данных за выбранный период (история накапливается ежедневно)</div>
    <?php endif; ?>
    <?php if ($bal_hist): ?><canvas id="bal-chart" height="80"></canvas><?php endif; ?>
  </section>
  <?php endif; ?>
<?php endif; ?>

<?php if (!$is_admin): ?>
  <?php
    $camps = $db->prepare("SELECT k.*, COALESCE(d.cost,0) AS cost_p, COALESCE(d.conv,0) AS conv_p, COALESCE(d.leads,0) AS leads_p
        FROM campaigns k
        LEFT JOIN (SELECT campaign_id, SUM(cost) cost, SUM(conv) conv, SUM(leads) leads
                   FROM daily_stats WHERE date BETWEEN ? AND ? GROUP BY campaign_id) d ON d.campaign_id = k.campaign_id
        WHERE k.client_id = ? ORDER BY k.campaigntip, k.campaign_id");
    $camps->execute([$FROM, $TO, $cab]);
    $camps = $camps->fetchAll(PDO::FETCH_ASSOC);
  ?>
  <section class="panel">
    <div class="panel-h"><h2>Кампании</h2><span class="hint"><?= count($camps) ?> · <?= $FROM_D ?> — <?= $TO_D ?></span></div>
    <div class="table-wrap">
    <table class="tbl">
      <thead><tr>
        <th>Кампания</th><th class="num">Статус</th>
        <th class="num">Расход</th><th class="num">Заявки</th><th class="num">CPL</th>
      </tr></thead>
      <tbody>
      <?php foreach ($camps as $k): ?>
        <tr>
          <td class="mono"><?= htmlspecialchars($k['campaign_id']) ?></td>
          <td class="num"><span class="st <?= $k['campaigntip'] === 'Стоп' ? 'st-stop' : 'st-run' ?>"><?= htmlspecialchars($k['campaigntip']) ?></span></td>
          <td class="num"><?= money($k['cost_p']) ?></td>
          <td class="num"><?= num($k['leads_p']) ?></td>
          <td class="num"><?= cpl($k['cost_p'], $k['leads_p']) ?></td>
        </tr>
      <?php endforeach; ?>
      </tbody>
    </table>
    </div>
  </section>
<?php endif; ?>
</main>

<?php if ($is_admin): ?>
<script>
const BAL_HISTORY = <?= json_encode(balance_history($db, null), JSON_UNESCAPED_UNICODE) ?>;
const CLIENTS = <?= json_encode($clients, JSON_UNESCAPED_UNICODE) ?>;
</script>
<?php else: ?>
<script>
const BAL_HISTORY = <?= json_encode($bal_hist, JSON_UNESCAPED_UNICODE) ?>;
const DAILY = <?= json_encode($my_daily ?? [], JSON_UNESCAPED_UNICODE) ?>;
</script>
<?php endif; ?>
<script src="assets/chart.umd.min.js"></script>
<script src="assets/app.js"></script>
</body>
</html>
