// ============================================
// MariusVPN — api helper, mock data, icons
// Exposes on window: api, MOCK, ICON, FMT
// ============================================

const API_BASE = "/api/cabinet";
// Real backend (served by FastAPI). Flip to true only for standalone
// design preview without a backend.
const MOCK = false;

// CSRF
function getCsrf() { return document.cookie.match(/csrf=([^;]+)/)?.[1] || ''; }

// ============================================
// MOCK DATA (mutable so writes feel realistic)
// ============================================
const M = {
  me: {
    user: { id: 'u_47102', name: 'Алексей Кузнецов', telegram: '@alexei_k', initials: 'АК' },
    subscription: {
      status: 'active',          // 'active' | 'expired' | 'trial'
      plan_id: 'pro_12m',
      plan_name: 'PRO',
      period_label: '12 месяцев',
      price_per_month: 249,
      currency: '₽',
      started_at: '2026-01-17',
      expires_at: '2027-01-17',
      days_left: 247,
      total_days: 365,
      auto_renew: true,
    },
    limits: {
      devices_used: 3,
      devices_max: 5,
      extra_device_price: 99,
      extra_device_currency: '₽',
    },
    balance: { amount: 320, currency: '₽' },
  },
  traffic: {
    total: { up_gb: 28.4, down_gb: 142.7 },
    bypass: { used_gb: 87.3, quota_gb: 150, base_cap_gb: 100, extra_gb: 50, price_per_gb: 19, currency: '₽' },
    devices: [
      { id: 'd1', name: 'iPhone 15 Pro',     up_gb: 12.1, down_gb: 88.4 },
      { id: 'd2', name: 'MacBook Pro 14"',   up_gb: 14.2, down_gb: 48.6 },
      { id: 'd3', name: 'iPad Air',          up_gb: 2.1,  down_gb: 5.7  },
    ],
  },
  plans: [
    { id: 'pro_1m',  name: '1 месяц',    period_months: 1,  price: 390,  per_month: 390, currency: '₽', popular: false, discount_pct: 0 },
    { id: 'pro_6m',  name: '6 месяцев',  period_months: 6,  price: 1890, per_month: 315, currency: '₽', popular: false, discount_pct: 19 },
    { id: 'pro_12m', name: '12 месяцев', period_months: 12, price: 2990, per_month: 249, currency: '₽', popular: true,  discount_pct: 36 },
    { id: 'pro_24m', name: '24 месяца',  period_months: 24, price: 4790, per_month: 199, currency: '₽', popular: false, discount_pct: 49 },
  ],
  payment_methods: [
    { id: 'card',   name: 'Банковская карта', description: 'Visa, Mastercard, МИР', enabled: true,  icon: 'card' },
    { id: 'sbp',    name: 'СБП',              description: 'Через любой банк РФ',   enabled: true,  icon: 'sbp' },
    { id: 'crypto', name: 'Криптовалюта',     description: 'USDT, BTC, ETH',        enabled: true,  icon: 'crypto' },
    { id: 'apple',  name: 'Apple Pay',        description: 'Временно недоступно',   enabled: false, icon: 'apple' },
  ],
  payments_history: [
    { id: 'p_2026_01', date: '2026-01-17', amount: 2990, currency: '₽', method: 'Карта •• 4421', status: 'paid',      description: 'Подписка PRO · 12 месяцев' },
    { id: 'p_2025_12', date: '2025-12-17', amount: 390,  currency: '₽', method: 'СБП',           status: 'paid',      description: 'Подписка PRO · 1 месяц'   },
    { id: 'p_2025_11', date: '2025-11-22', amount: 950,  currency: '₽', method: 'Карта •• 4421', status: 'pending',   description: 'Докупка трафика · 50 ГБ'  },
    { id: 'p_2025_10', date: '2025-10-17', amount: 390,  currency: '₽', method: 'Карта •• 4421', status: 'paid',      description: 'Подписка PRO · 1 месяц'   },
    { id: 'p_2025_09', date: '2025-09-30', amount: 390,  currency: '₽', method: 'Карта •• 4421', status: 'cancelled', description: 'Подписка PRO · 1 месяц'   },
  ],
  devices: [
    { id: 'd1', name: 'iPhone 15 Pro',     platform: 'ios',     hwid: 'A7B3-4D2F-9E1C', online: true,  last_activity: 'сейчас' },
    { id: 'd2', name: 'MacBook Pro 14"',   platform: 'macos',   hwid: '8C4E-1F7A-3B2D', online: true,  last_activity: '12 минут назад' },
    { id: 'd3', name: 'iPad Air',          platform: 'ios',     hwid: '2D9F-6E1B-4A8C', online: false, last_activity: 'вчера, 21:14' },
  ],
  referral: {
    code: 'ALEXEIK7M',
    link: 'https://mariusvpn.com/r/ALEXEIK7M',
    invited_count: 3,
    paid_count: 2,
    balance: 90,
    balance_unit: 'дней',
    rule_text: 'Пригласите друга по своей ссылке. Когда он оплатит первый месяц, вы получите +30 дней к подписке, а друг — первый месяц бесплатно. Бонус начисляется автоматически, ограничений по количеству приглашений нет.',
  },
  help: {
    platforms: [
      { id: 'ios',     name: 'iPhone / iPad', steps: [
        { n: 1, text: 'Скачайте Happ или v2RayTun в App Store — это бесплатно.' },
        { n: 2, text: 'Откройте раздел «Устройства» в личном кабинете и нажмите «Добавить устройство».' },
        { n: 3, text: 'Скопируйте ссылку-подписку или отсканируйте QR-код в приложении.' },
        { n: 4, text: 'Выберите любой сервер из списка и нажмите «Подключить».' },
      ]},
      { id: 'android', name: 'Android', steps: [
        { n: 1, text: 'Установите v2RayTun, Hiddify или Happ из Google Play.' },
        { n: 2, text: 'Откройте раздел «Устройства» и нажмите «Добавить устройство».' },
        { n: 3, text: 'Вставьте ссылку-подписку в приложение или импортируйте через QR.' },
        { n: 4, text: 'Выберите сервер и нажмите «Подключить».' },
      ]},
      { id: 'windows', name: 'Windows', steps: [
        { n: 1, text: 'Скачайте Hiddify-Next или Nekobox с официального сайта.' },
        { n: 2, text: 'В личном кабинете создайте устройство и скопируйте ссылку-подписку.' },
        { n: 3, text: 'Вставьте ссылку в Hiddify и нажмите «Добавить».' },
        { n: 4, text: 'Выберите сервер и подключитесь.' },
      ]},
      { id: 'macos', name: 'macOS', steps: [
        { n: 1, text: 'Установите Streisand или Hiddify-Next через App Store или официальный сайт.' },
        { n: 2, text: 'Добавьте устройство в кабинете и получите ссылку-подписку.' },
        { n: 3, text: 'Импортируйте подписку в клиент (Subscription → Add).' },
        { n: 4, text: 'Выберите сервер и нажмите «Подключить».' },
      ]},
    ],
    faq: [
      { q: 'Что делать, если VPN не подключается?', a: 'Проверьте, что устройство активно в кабинете и подписка не истекла. Попробуйте сменить сервер в клиенте, переустановить конфиг. Если не помогло — напишите в поддержку.' },
      { q: 'Сколько устройств можно подключить?', a: 'На тарифе PRO — до 5 устройств. Каждое дополнительное устройство стоит 99 ₽/месяц.' },
      { q: 'Как отвязать устройство?', a: 'В разделе «Устройства» нажмите на нужное устройство и выберите «Удалить». Конфиг будет аннулирован сразу.' },
      { q: 'Можно ли вернуть деньги?', a: 'Возврат возможен в течение 7 дней после первой оплаты при условии, что использовано менее 5 ГБ трафика. Напишите в поддержку для оформления.' },
      { q: 'Что такое «сервер обхода»?', a: 'Это специальная категория серверов для регионов с блокировками. У них отдельный лимит трафика; превышение можно докупить пакетами.' },
    ],
    support_url: 'https://t.me/marius_support',
  },
};

// fake VLESS config + QR
function fakeConfigFor(device) {
  const vless = `vless://${device.id}-uuid-mock@de-fra-01.example.com:443?encryption=none&security=reality&type=tcp&sni=cloudflare.com&pbk=fake_pub_key&fp=chrome#${encodeURIComponent('VPN — ' + device.name)}`;
  const sub_url = `https://mariusvpn.com/sub/${device.id}-${device.hwid.replace(/-/g, '').toLowerCase()}`;
  return { vless, sub_url, qr_data: sub_url };
}

// ============================================
// MOCK RESOLVER
// ============================================
function mockResolve(path, opts = {}) {
  const method = opts.method || 'GET';
  const body = opts.body || {};

  // GET endpoints
  if (method === 'GET') {
    if (path === '/me')                return clone(M.me);
    if (path === '/traffic')           return clone(M.traffic);
    if (path === '/plans')             return clone(M.plans);
    if (path === '/payments/methods')  return clone(M.payment_methods);
    if (path === '/payments/history')  return clone(M.payments_history);
    if (path === '/devices')           return clone(M.devices);
    if (path === '/referral')          return clone(M.referral);
    if (path === '/help')              return clone(M.help);
    // GET /devices/{id}/config
    const cfg = path.match(/^\/devices\/([^/]+)\/config$/);
    if (cfg) {
      const dev = M.devices.find(d => d.id === cfg[1]);
      if (!dev) throw new Error('device not found');
      return fakeConfigFor(dev);
    }
  }

  // POST /login
  if (method === 'POST' && path === '/login') {
    return { ok: true, user: clone(M.me.user) };
  }
  // POST /subscription/auto-renew
  if (method === 'POST' && path === '/subscription/auto-renew') {
    M.me.subscription.auto_renew = !!body.enabled;
    return { ok: true, auto_renew: M.me.subscription.auto_renew };
  }
  // POST /subscription/renew
  if (method === 'POST' && path === '/subscription/renew') {
    return { ok: true, payment_url: 'https://pay.mariusvpn.com/mock?order=ord_' + Date.now() };
  }
  // POST /payments/topup
  if (method === 'POST' && path === '/payments/topup') {
    return { ok: true, payment_url: 'https://pay.mariusvpn.com/mock?order=top_' + Date.now() };
  }
  // POST /traffic/buy-gb
  if (method === 'POST' && path === '/traffic/buy-gb') {
    M.traffic.bypass.extra_gb += body.gb || 0;
    M.traffic.bypass.quota_gb = M.traffic.bypass.base_cap_gb + M.traffic.bypass.extra_gb;
    return { ok: true, quota_gb: M.traffic.bypass.quota_gb };
  }
  // POST /devices
  if (method === 'POST' && path === '/devices') {
    const id = 'd' + (M.devices.length + 1 + Math.floor(Math.random() * 1000));
    const hwid = Array.from({ length: 3 }, () => Math.random().toString(16).slice(2, 6).toUpperCase()).join('-');
    const dev = { id, name: body.name || 'Новое устройство', platform: body.platform || 'ios', hwid, online: false, last_activity: 'только что' };
    M.devices.push(dev);
    M.me.limits.devices_used = M.devices.length;
    return { ok: true, device: clone(dev), config: fakeConfigFor(dev) };
  }
  // PATCH /devices/{id}
  const patchDev = path.match(/^\/devices\/([^/]+)$/);
  if (method === 'PATCH' && patchDev) {
    const dev = M.devices.find(d => d.id === patchDev[1]);
    if (!dev) throw new Error('device not found');
    Object.assign(dev, body);
    return { ok: true, device: clone(dev) };
  }
  // DELETE /devices/{id}
  if (method === 'DELETE' && patchDev) {
    M.devices = M.devices.filter(d => d.id !== patchDev[1]);
    M.me.limits.devices_used = M.devices.length;
    return { ok: true };
  }

  console.warn('MOCK: no handler for', method, path);
  return { ok: false, error: 'unhandled' };
}

function clone(x) { return JSON.parse(JSON.stringify(x)); }

// ============================================
// API
// ============================================
async function api(path, opts = {}) {
  if (MOCK) {
    await new Promise(r => setTimeout(r, 180 + Math.random() * 220));
    return mockResolve(path, opts);
  }
  const headers = { 'Content-Type': 'application/json', 'X-CSRF': getCsrf(), ...(opts.headers || {}) };
  const init = { method: opts.method || 'GET', credentials: 'include', headers };
  if (opts.body) init.body = JSON.stringify(opts.body);
  const res = await fetch(API_BASE + path, init);
  if (!res.ok) throw new Error(`API ${path} → ${res.status}`);
  return res.json();
}

// ============================================
// FORMATTERS
// ============================================
const FMT = {
  money: (amount, currency = '₽') => `${new Intl.NumberFormat('ru-RU').format(amount)} ${currency}`,
  gb:    (n) => `${(+n).toFixed(1).replace(/\.0$/, '')} ГБ`,
  date:  (iso) => {
    const d = new Date(iso);
    return d.toLocaleDateString('ru-RU', { day: 'numeric', month: 'long', year: 'numeric' });
  },
  dateShort: (iso) => {
    const d = new Date(iso);
    return d.toLocaleDateString('ru-RU', { day: 'numeric', month: 'short', year: '2-digit' });
  },
  declOf: (n, forms) => {
    const a = Math.abs(n) % 100, b = a % 10;
    if (a > 10 && a < 20) return forms[2];
    if (b > 1 && b < 5) return forms[1];
    if (b === 1) return forms[0];
    return forms[2];
  },
  daysWord: (n) => FMT.declOf(n, ['день', 'дня', 'дней']),
};

// ============================================
// ICONS (lucide-style, 24×24, stroke 1.7)
// ============================================
const Icon = ({ name, size = 20, className = '', strokeWidth = 1.7 }) => {
  const paths = ICON_PATHS[name];
  if (!paths) return null;
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor"
      strokeWidth={strokeWidth} strokeLinecap="round" strokeLinejoin="round"
      className={className} aria-hidden="true">
      {paths}
    </svg>
  );
};

const ICON_PATHS = {
  home:        <><path d="M3 11l9-8 9 8" /><path d="M5 10v10h14V10" /><path d="M10 20v-6h4v6" /></>,
  shield:      <><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" /></>,
  shieldCheck: <><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" /><path d="M9 12l2 2 4-4" /></>,
  crown:       <><path d="M3 7l5 5 4-7 4 7 5-5v11H3z" /></>,
  device:      <><rect x="2" y="4" width="14" height="11" rx="2" /><path d="M2 19h14" /><rect x="17" y="9" width="5" height="11" rx="1.5" /></>,
  chart:       <><path d="M3 3v18h18" /><path d="M7 14l4-4 4 3 5-7" /></>,
  card:        <><rect x="2" y="5" width="20" height="14" rx="3" /><path d="M2 10h20" /><path d="M7 15h4" /></>,
  users:       <><circle cx="9" cy="8" r="3.5" /><path d="M2 21c0-4 3.5-6 7-6s7 2 7 6" /><circle cx="17" cy="9" r="2.5" /><path d="M22 19c0-2.5-2-4-5-4" /></>,
  help:        <><circle cx="12" cy="12" r="9" /><path d="M9.5 9a2.5 2.5 0 0 1 5 0c0 1.5-2.5 2-2.5 4" /><circle cx="12" cy="17" r="0.7" fill="currentColor" /></>,
  menu:        <><path d="M4 6h16" /><path d="M4 12h16" /><path d="M4 18h16" /></>,
  more:        <><circle cx="6" cy="12" r="1.5" fill="currentColor" /><circle cx="12" cy="12" r="1.5" fill="currentColor" /><circle cx="18" cy="12" r="1.5" fill="currentColor" /></>,
  close:       <><path d="M6 6l12 12" /><path d="M18 6l-12 12" /></>,
  chevR:       <><path d="M9 6l6 6-6 6" /></>,
  chevD:       <><path d="M6 9l6 6 6-6" /></>,
  chevU:       <><path d="M6 15l6-6 6 6" /></>,
  copy:        <><rect x="9" y="9" width="11" height="11" rx="2" /><path d="M5 15V5a2 2 0 0 1 2-2h10" /></>,
  qr:          <><rect x="3" y="3" width="7" height="7" rx="1" /><rect x="14" y="3" width="7" height="7" rx="1" /><rect x="3" y="14" width="7" height="7" rx="1" /><path d="M14 14h3v3h-3z" /><path d="M20 14v3" /><path d="M14 20h3" /></>,
  check:       <><path d="M5 12l5 5 9-11" /></>,
  plus:        <><path d="M12 5v14" /><path d="M5 12h14" /></>,
  download:    <><path d="M12 4v12" /><path d="M7 11l5 5 5-5" /><path d="M5 20h14" /></>,
  trash:       <><path d="M3 6h18" /><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" /><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" /></>,
  edit:        <><path d="M12 20h9" /><path d="M16.5 3.5a2.12 2.12 0 1 1 3 3L7 19l-4 1 1-4z" /></>,
  bell:        <><path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9" /><path d="M10 21a2 2 0 0 0 4 0" /></>,
  link:        <><path d="M10 13a5 5 0 0 0 7.5.5l3-3a5 5 0 0 0-7-7l-1.5 1.5" /><path d="M14 11a5 5 0 0 0-7.5-.5l-3 3a5 5 0 0 0 7 7l1.5-1.5" /></>,
  telegram:    <><path d="M22 2L2 11l5 2 2 7 4-4 6 5 3-19z" /></>,
  arrowUp:     <><path d="M12 19V5" /><path d="M5 12l7-7 7 7" /></>,
  arrowDown:   <><path d="M12 5v14" /><path d="M5 12l7 7 7-7" /></>,
  arrowRight:  <><path d="M5 12h14" /><path d="M13 5l7 7-7 7" /></>,
  zap:         <><path d="M13 2L4 14h7l-1 8 9-12h-7z" /></>,
  gift:        <><path d="M20 12v9H4v-9" /><path d="M2 7h20v5H2z" /><path d="M12 21V7" /><path d="M12 7a3 3 0 0 1-3-3 2 2 0 0 1 2-2c2 0 1 5 1 5z" /><path d="M12 7a3 3 0 0 0 3-3 2 2 0 0 0-2-2c-2 0-1 5-1 5z" /></>,
  globe:       <><circle cx="12" cy="12" r="9" /><path d="M3 12h18" /><path d="M12 3a14 14 0 0 1 0 18" /><path d="M12 3a14 14 0 0 0 0 18" /></>,
  settings:    <><circle cx="12" cy="12" r="3" /><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.6a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" /></>,
  logout:      <><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" /><path d="M16 17l5-5-5-5" /><path d="M21 12H9" /></>,
  refresh:     <><path d="M3 12a9 9 0 0 1 15-6.7L21 8" /><path d="M21 3v5h-5" /><path d="M21 12a9 9 0 0 1-15 6.7L3 16" /><path d="M3 21v-5h5" /></>,
  // platforms
  apple:       <><path d="M16 1c-1.5 0-3 1-3.5 2.3.6.3 1.5 1 2 2 1.4 0 3-1.3 3-2.7 0-.5-.5-1.2-1.5-1.6z" /><path d="M19 16c-.5 1.5-1.5 3-2.5 4-1 .5-2 .5-3 0-1-.5-2-.5-3 0-1.5.5-2.5 0-3.5-1-2-2.5-3-7.5-1-10 1-1.5 3-2 4.5-2 1 0 2 .5 2.5.5s2-.5 3.5-.5c.5 0 2.5 0 4 2-3 1.5-2.5 5 .5 7z" /></>,
  android:     <><path d="M5 17V9" /><path d="M19 17V9" /><path d="M5 17h14v-7a7 7 0 0 0-14 0v7z" /><path d="M8 6l-1-2" /><path d="M16 6l1-2" /><circle cx="9" cy="13" r="0.5" fill="currentColor" /><circle cx="15" cy="13" r="0.5" fill="currentColor" /></>,
  windows:     <><path d="M3 5l8-1v7H3z" /><path d="M12 4l9-1v9h-9z" /><path d="M3 12h8v7l-8-1z" /><path d="M12 12h9v9l-9-1z" /></>,
  linux:       <><circle cx="12" cy="12" r="9" /><circle cx="9" cy="10" r="1" fill="currentColor" /><circle cx="15" cy="10" r="1" fill="currentColor" /><path d="M9 16c1 1 5 1 6 0" /></>,
};

// platform → human + icon name
const PLATFORM_LABEL = { ios: 'iOS', android: 'Android', windows: 'Windows', macos: 'macOS', linux: 'Linux' };
const PLATFORM_ICON  = { ios: 'apple', android: 'android', windows: 'windows', macos: 'apple', linux: 'linux' };

Object.assign(window, { api, MOCK, Icon, ICON_PATHS, FMT, PLATFORM_LABEL, PLATFORM_ICON, getCsrf });
