// =======================================================================
// MariusVPN Franchise — Login + screens (Dashboard, Users, Broadcast,
// Settings, Payouts). Uses primitives from marius-admin-ui.jsx and
// API helpers from marius-fr-data.jsx.
// =======================================================================

const { frApi, RUBfr, NUMfr, DATEfr, DATETIMEfr, frUserStatus } = window.FR_API;

// =======================================================================
// LOGIN
// =======================================================================

function FrLogin({ onLogin }) {
  const [username, setU] = React.useState('');
  const [password, setP] = React.useState('');
  const [loading, setLoading] = React.useState(false);
  const [err, setErr] = React.useState('');
  const t = useToast();

  const submit = async (e) => {
    e.preventDefault();
    setErr(''); setLoading(true);
    try {
      await frApi('/login', { method: 'POST', body: { username, password } });
      const me = await frApi('/whoami');
      onLogin(me);
    } catch (e) {
      setErr(e.message || 'Не удалось войти');
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="min-h-screen grid-bg flex items-center justify-center p-6">
      <div className="w-full max-w-[420px] fade-in">
        <div className="flex items-center gap-3 mb-7">
          <div className="h-11 w-11 rounded-xl bg-m-accent/15 border border-m-accent/30 flex items-center justify-center text-m-accent">
            <Icon d={ICONS.shield} size={22}/>
          </div>
          <div>
            <div className="text-[18px] font-bold leading-none">Панель управления</div>
            <div className="text-xs text-m-mute mt-1">Вход для франчайзи</div>
          </div>
        </div>

        <Card padding="p-7">
          <h1 className="text-[22px] font-bold tracking-tight mb-1">Вход для франчайзи</h1>
          <p className="text-sm text-m-mute mb-6">Логин и пароль выдаёт владелец сети.</p>

          <form onSubmit={submit} className="flex flex-col gap-4">
            <Field label="Логин">
              <Input value={username} onChange={e => setU(e.target.value)} placeholder="speedvpn" autoFocus icon={ICONS.users}/>
            </Field>
            <Field label="Пароль">
              <Input type="password" value={password} onChange={e => setP(e.target.value)} placeholder="••••••••" icon={ICONS.shield}/>
            </Field>
            {err && (
              <div className="flex items-start gap-2 text-sm text-m-err bg-m-err/10 border border-m-err/25 rounded-lg px-3 py-2">
                <Icon d={ICONS.warn} size={14} className="mt-0.5 shrink-0"/>{err}
              </div>
            )}
            <Button type="submit" loading={loading} size="lg" className="mt-1">Войти</Button>
          </form>

          <div className="mt-5 pt-5 border-t border-m-line text-xs text-m-dim leading-relaxed">
            Демо-доступ: <span className="font-mono text-m-mute">speedvpn / demo</span>
          </div>
        </Card>

        <div className="mt-5 text-center text-xs text-m-dim">
          © 2026 · Панель управления франшизой
        </div>
      </div>
    </div>
  );
}

// =======================================================================
// DASHBOARD
// =======================================================================

function FrDashboard({ goto, openWithdraw }) {
  const [data, setData] = React.useState(null);
  React.useEffect(() => { frApi('/dashboard').then(setData); }, []);

  if (!data) return <Loading/>;
  return (
    <div className="fade-in">
      <SectionHeader
        title="Дашборд"
        subtitle="Сводка по вашей франшизе"
        right={<Button icon={<Icon d={ICONS.wallet} size={16}/>} variant="primary" onClick={openWithdraw}>Запросить выплату</Button>}
      />

      <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
        <Kpi
          label="Мои пользователи"
          value={NUMfr(data.users)}
          hint={`${data.users_active} активных`}
          icon={ICONS.users}
        />
        <Kpi
          label="Моя выручка"
          value={RUBfr(data.revenue)}
          hint={`${RUBfr(data.revenue_month)} за месяц`}
          icon={ICONS.trending}
          accent="ok"
          hintTone="up"
        />
        <Kpi
          label="Баланс"
          value={RUBfr(data.balance)}
          hint={`Выведено всего: ${RUBfr(data.payouts_total)}`}
          icon={ICONS.wallet}
          accent="gold"
        />
        <Kpi
          label="Доля владельца / моя"
          value={`${100 - data.share_percent}% / ${data.share_percent}%`}
          hint="Делится с каждой оплаты"
          icon={ICONS.finance}
        />
      </div>

      <div className="grid grid-cols-1 lg:grid-cols-3 gap-4">
        <Card className="lg:col-span-2">
          <div className="flex items-center justify-between mb-4">
            <div>
              <div className="text-base font-semibold">Как считается выручка</div>
              <div className="text-xs text-m-mute mt-1">С каждой оплаты вашего пользователя</div>
            </div>
            <Badge tone="info" dot>50 / 50</Badge>
          </div>

          <div className="grid grid-cols-3 gap-3 text-center">
            <div className="rounded-xl bg-m-bg2 border border-m-line p-4">
              <div className="text-[11px] uppercase tracking-wider text-m-mute mb-1.5">Оплата клиента</div>
              <div className="text-xl font-bold font-mono">249 ₽</div>
            </div>
            <div className="flex items-center justify-center text-m-dim">
              <Icon d="M5 12h14M13 6l6 6-6 6" size={20}/>
            </div>
            <div className="rounded-xl bg-m-accent/10 border border-m-accent/25 p-4">
              <div className="text-[11px] uppercase tracking-wider text-m-accent mb-1.5">Вам</div>
              <div className="text-xl font-bold text-m-accent font-mono">{Math.round(249 * data.share_percent / 100)} ₽</div>
            </div>
          </div>

          <div className="mt-4 text-xs text-m-mute leading-relaxed">
            Выручка зачисляется на баланс сразу после оплаты. Запросить вывод можно в любой момент во вкладке «Выплаты».
          </div>
        </Card>

        <Card>
          <div className="text-base font-semibold mb-1">Быстрые действия</div>
          <div className="text-xs text-m-mute mb-4">Самые частые операции</div>
          <div className="flex flex-col gap-2">
            <button onClick={() => goto('users')} className="group flex items-center gap-3 px-3 py-2.5 rounded-xl bg-white/[0.03] hover:bg-white/[0.07] border border-m-line transition">
              <span className="h-8 w-8 rounded-lg bg-m-accent/12 text-m-accent flex items-center justify-center"><Icon d={ICONS.users} size={15}/></span>
              <span className="text-sm flex-1 text-left">Посмотреть пользователей</span>
              <Icon d={ICONS.chevR} size={14} className="text-m-dim group-hover:text-m-text"/>
            </button>
            <button onClick={() => goto('broadcast')} className="group flex items-center gap-3 px-3 py-2.5 rounded-xl bg-white/[0.03] hover:bg-white/[0.07] border border-m-line transition">
              <span className="h-8 w-8 rounded-lg bg-m-ok/12 text-m-ok flex items-center justify-center"><Icon d={ICONS.broadcast} size={15}/></span>
              <span className="text-sm flex-1 text-left">Запустить рассылку</span>
              <Icon d={ICONS.chevR} size={14} className="text-m-dim group-hover:text-m-text"/>
            </button>
            <button onClick={() => goto('settings')} className="group flex items-center gap-3 px-3 py-2.5 rounded-xl bg-white/[0.03] hover:bg-white/[0.07] border border-m-line transition">
              <span className="h-8 w-8 rounded-lg bg-m-gold/12 text-m-gold flex items-center justify-center"><Icon d={ICONS.settings} size={15}/></span>
              <span className="text-sm flex-1 text-left">Настроить бота</span>
              <Icon d={ICONS.chevR} size={14} className="text-m-dim group-hover:text-m-text"/>
            </button>
          </div>
        </Card>
      </div>
    </div>
  );
}

// =======================================================================
// USERS
// =======================================================================

function FrUsers() {
  const [query, setQuery] = React.useState('');
  const [status, setStatus] = React.useState('');
  const [page, setPage] = React.useState(1);
  const [data, setData] = React.useState(null);
  const [openId, setOpenId] = React.useState(null);
  const t = useToast();

  const load = React.useCallback(async () => {
    const q = new URLSearchParams();
    if (query) q.set('query', query);
    if (status) q.set('status', status);
    q.set('page', String(page));
    const res = await frApi('/users?' + q.toString());
    setData(res);
  }, [query, status, page]);

  React.useEffect(() => { load(); }, [load]);
  React.useEffect(() => { setPage(1); }, [query, status]);

  const totalPages = data ? Math.max(1, Math.ceil(data.total / data.page_size)) : 1;

  return (
    <div className="fade-in">
      <SectionHeader
        title="Пользователи"
        subtitle={data ? `${NUMfr(data.total)} пользователей вашей франшизы` : ''}
      />

      <Card padding="p-0" className="overflow-hidden">
        <div className="p-4 flex flex-wrap items-center gap-3 border-b border-m-line">
          <div className="flex-1 min-w-[240px]">
            <Input
              icon={ICONS.search}
              placeholder="Поиск по имени, @username, ID, TG-ID"
              value={query}
              onChange={e => setQuery(e.target.value)}
            />
          </div>
          <div className="w-[180px]">
            <Select value={status} onChange={e => setStatus(e.target.value)}>
              <option value="">Все статусы</option>
              <option value="active">Активные</option>
              <option value="expired">Истекли</option>
              <option value="blocked">Заблокированы</option>
            </Select>
          </div>
        </div>

        {!data ? <Loading/> : data.items.length === 0 ? <Empty title="Не найдено" subtitle="Попробуйте другой запрос или фильтр."/> : (
          <div className="overflow-x-auto">
            <table className="w-full text-sm">
              <thead>
                <tr className="text-[11px] uppercase tracking-wider text-m-mute border-b border-m-line">
                  <th className="text-left font-medium px-5 py-3">Пользователь</th>
                  <th className="text-left font-medium px-3 py-3">TG-ID</th>
                  <th className="text-right font-medium px-3 py-3">Баланс</th>
                  <th className="text-left font-medium px-3 py-3">Подписка</th>
                  <th className="text-right font-medium px-3 py-3">Пополнений</th>
                  <th className="text-left font-medium px-3 py-3">Статус</th>
                  <th className="px-5 py-3"></th>
                </tr>
              </thead>
              <tbody>
                {data.items.map(u => {
                  const st = frUserStatus(u);
                  return (
                    <tr key={u.id} className="border-b border-m-line last:border-0 hover:bg-white/[0.02] cursor-pointer" onClick={() => setOpenId(u.id)}>
                      <td className="px-5 py-3">
                        <div className="font-medium text-m-text">{u.tg_name}</div>
                        <div className="text-xs text-m-mute">@{u.tg_username}</div>
                      </td>
                      <td className="px-3 py-3 text-m-mute font-mono text-xs">{u.tg_id}</td>
                      <td className="px-3 py-3 text-right font-mono">{RUBfr(u.balance)}</td>
                      <td className="px-3 py-3">
                        {u.days_left > 0
                          ? <span className="text-m-text">{u.days_left} дн.</span>
                          : <span className="text-m-err">истекла</span>}
                        <span className="text-xs text-m-dim ml-2">{DATEfr(u.expire_at)}</span>
                      </td>
                      <td className="px-3 py-3 text-right font-mono">{u.topups_count}</td>
                      <td className="px-3 py-3">
                        {st === 'active'  && <Badge tone="ok" dot>активна</Badge>}
                        {st === 'expired' && <Badge tone="warn">истекла</Badge>}
                        {st === 'blocked' && <Badge tone="err">заблокирован</Badge>}
                      </td>
                      <td className="px-5 py-3 text-right text-m-dim">
                        <Icon d={ICONS.chevR} size={14}/>
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
        )}

        {data && totalPages > 1 && (
          <div className="flex items-center justify-between px-5 py-3 border-t border-m-line">
            <div className="text-xs text-m-mute">Страница {page} из {totalPages}</div>
            <div className="flex items-center gap-2">
              <Button size="sm" variant="secondary" disabled={page <= 1} onClick={() => setPage(p => p - 1)} icon={<Icon d={ICONS.chevL} size={14}/>}>Назад</Button>
              <Button size="sm" variant="secondary" disabled={page >= totalPages} onClick={() => setPage(p => p + 1)}>
                Вперёд<Icon d={ICONS.chevR} size={14}/>
              </Button>
            </div>
          </div>
        )}
      </Card>

      {openId && <FrUserDetail userId={openId} onClose={() => setOpenId(null)} onChanged={load}/>}
    </div>
  );
}

function FrUserDetail({ userId, onClose, onChanged }) {
  const [u, setU] = React.useState(null);
  const [msgOpen, setMsgOpen] = React.useState(false);
  const [grantOpen, setGrantOpen] = React.useState(false);
  const [promoOpen, setPromoOpen] = React.useState(false);

  React.useEffect(() => { frApi(`/users/${userId}`).then(setU); }, [userId]);

  const refresh = async () => { const r = await frApi(`/users/${userId}`); setU(r); onChanged && onChanged(); };

  return (
    <>
      <SidePanel open onClose={onClose} title={u ? u.tg_name : 'Пользователь'} width="w-[560px]">
        {!u ? <Loading/> : (
          <div className="flex flex-col gap-5">
            <div className="flex items-center gap-3">
              <div className="h-12 w-12 rounded-xl bg-m-accent/15 border border-m-accent/30 flex items-center justify-center text-m-accent font-semibold">
                {u.tg_name.slice(0, 1)}
              </div>
              <div className="flex-1">
                <div className="font-semibold">{u.tg_name}</div>
                <div className="text-xs text-m-mute">@{u.tg_username} · ID {u.id}</div>
              </div>
              {frUserStatus(u) === 'active' && <Badge tone="ok" dot>активна</Badge>}
              {frUserStatus(u) === 'expired' && <Badge tone="warn">истекла</Badge>}
              {frUserStatus(u) === 'blocked' && <Badge tone="err">заблокирован</Badge>}
            </div>

            <div className="grid grid-cols-3 gap-3">
              <div className="rounded-xl bg-m-bg border border-m-line p-3.5">
                <div className="text-[11px] uppercase tracking-wider text-m-mute">Баланс</div>
                <div className="font-mono font-semibold mt-1">{RUBfr(u.balance)}</div>
              </div>
              <div className="rounded-xl bg-m-bg border border-m-line p-3.5">
                <div className="text-[11px] uppercase tracking-wider text-m-mute">Подписка</div>
                <div className="font-semibold mt-1">{u.days_left > 0 ? `${u.days_left} дн.` : <span className="text-m-err">истекла</span>}</div>
                <div className="text-[11px] text-m-dim">{DATEfr(u.expire_at)}</div>
              </div>
              <div className="rounded-xl bg-m-bg border border-m-line p-3.5">
                <div className="text-[11px] uppercase tracking-wider text-m-mute">Оплат</div>
                <div className="font-semibold mt-1">{u.topups_count}</div>
              </div>
            </div>

            <div>
              <div className="text-[11px] uppercase tracking-wider text-m-mute mb-2">Действия</div>
              <div className="grid grid-cols-1 gap-2">
                <FrActionRow
                  icon={ICONS.msg}
                  label="Написать сообщение"
                  hint="От имени вашего бота"
                  always
                  onClick={() => setMsgOpen(true)}
                />
                <FrActionRow
                  icon={ICONS.gift}
                  label="Выдать дни подписки"
                  hint={FR_API.FR_PERMS.allow_grant_days
                    ? 'Бесплатно, на ваш счёт'
                    : 'Недоступно — запросите доступ у владельца'}
                  allowed={FR_API.FR_PERMS.allow_grant_days}
                  onClick={() => setGrantOpen(true)}
                />
                <FrActionRow
                  icon={ICONS.sparkles}
                  label="Создать промокод"
                  hint={FR_API.FR_PERMS.allow_promo
                    ? 'Одноразовый, на N дней'
                    : 'Недоступно — запросите доступ у владельца'}
                  allowed={FR_API.FR_PERMS.allow_promo}
                  onClick={() => setPromoOpen(true)}
                />
              </div>
            </div>

            <div>
              <div className="text-[11px] uppercase tracking-wider text-m-mute mb-2">История оплат</div>
              <div className="rounded-xl bg-m-bg border border-m-line overflow-hidden">
                <table className="w-full text-sm">
                  <thead>
                    <tr className="text-[11px] uppercase tracking-wider text-m-mute border-b border-m-line">
                      <th className="text-left font-medium px-3 py-2">Дата</th>
                      <th className="text-left font-medium px-3 py-2">Метод</th>
                      <th className="text-right font-medium px-3 py-2">Сумма</th>
                      <th className="text-right font-medium px-3 py-2">Статус</th>
                    </tr>
                  </thead>
                  <tbody>
                    {u.topups.map((t, i) => (
                      <tr key={i} className="border-b border-m-line last:border-0">
                        <td className="px-3 py-2 text-m-mute text-xs">{DATETIMEfr(t.created_at)}</td>
                        <td className="px-3 py-2">{t.method}</td>
                        <td className="px-3 py-2 text-right font-mono">{RUBfr(t.amount)}</td>
                        <td className="px-3 py-2 text-right">
                          {t.status === 'paid' && <Badge tone="ok">оплачено</Badge>}
                          {t.status === 'pending' && <Badge tone="warn">в ожидании</Badge>}
                          {t.status === 'failed' && <Badge tone="err">ошибка</Badge>}
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            </div>
          </div>
        )}
      </SidePanel>

      {msgOpen && <FrMessageDialog userId={userId} onClose={() => setMsgOpen(false)}/>}
      {grantOpen && <FrGrantDialog userId={userId} onClose={() => setGrantOpen(false)} onDone={refresh}/>}
      {promoOpen && <FrPromoDialog userId={userId} onClose={() => setPromoOpen(false)}/>}
    </>
  );
}

function FrActionRow({ icon, label, hint, allowed = true, always = false, onClick }) {
  const enabled = always || allowed;
  return (
    <button
      onClick={enabled ? onClick : undefined}
      disabled={!enabled}
      className={
        'group w-full flex items-center gap-3 px-3.5 py-3 rounded-xl border transition text-left ' +
        (enabled
          ? 'bg-white/[0.03] hover:bg-white/[0.07] border-m-line'
          : 'bg-white/[0.015] border-m-line opacity-60 cursor-not-allowed')
      }
    >
      <span className={
        'h-9 w-9 rounded-lg flex items-center justify-center ' +
        (enabled ? 'bg-m-accent/12 text-m-accent' : 'bg-white/[0.04] text-m-dim')
      }>
        <Icon d={icon} size={16}/>
      </span>
      <span className="flex-1 min-w-0">
        <div className="text-sm font-medium text-m-text flex items-center gap-2">
          {label}
          {!enabled && !always && <Badge tone="mute">недоступно</Badge>}
        </div>
        <div className={'text-xs ' + (enabled ? 'text-m-mute' : 'text-m-dim')}>{hint}</div>
      </span>
      {enabled && <Icon d={ICONS.chevR} size={14} className="text-m-dim group-hover:text-m-text"/>}
    </button>
  );
}

function FrMessageDialog({ userId, onClose }) {
  const [text, setText] = React.useState('');
  const [loading, setLoading] = React.useState(false);
  const t = useToast();
  const send = async () => {
    setLoading(true);
    try {
      await frApi(`/users/${userId}/message`, { method: 'POST', body: { text } });
      t.ok('Сообщение отправлено');
      onClose();
    } catch (e) {
      t.err(e.message || 'Не удалось отправить');
    } finally { setLoading(false); }
  };
  return (
    <Modal open onClose={onClose} title="Сообщение пользователю" width="max-w-lg"
      footer={<>
        <Button variant="secondary" onClick={onClose}>Отмена</Button>
        <Button onClick={send} loading={loading} disabled={!text.trim()} icon={<Icon d={ICONS.send} size={15}/>}>Отправить</Button>
      </>}
    >
      <Field label="Текст" hint="Отправится от имени вашего бота">
        <Textarea rows={6} value={text} onChange={e => setText(e.target.value)} placeholder="Здравствуйте! …"/>
      </Field>
    </Modal>
  );
}

function FrGrantDialog({ userId, onClose, onDone }) {
  const [days, setDays] = React.useState(7);
  const [loading, setLoading] = React.useState(false);
  const t = useToast();
  const send = async () => {
    setLoading(true);
    try {
      await frApi(`/users/${userId}/grant-days`, { method: 'POST', body: { days: Number(days) } });
      t.ok(`Начислено ${days} дней`);
      onDone(); onClose();
    } catch (e) {
      if (e.code === 403) t.err('Действие недоступно — запросите доступ у владельца');
      else t.err(e.message || 'Ошибка');
    } finally { setLoading(false); }
  };
  return (
    <Modal open onClose={onClose} title="Выдать дни подписки" width="max-w-md"
      footer={<>
        <Button variant="secondary" onClick={onClose}>Отмена</Button>
        <Button onClick={send} loading={loading} disabled={days <= 0} icon={<Icon d={ICONS.gift} size={15}/>}>Начислить</Button>
      </>}
    >
      <Field label="Сколько дней" hint="Целое число, 1–365">
        <Input type="number" min="1" max="365" value={days} onChange={e => setDays(e.target.value)}/>
      </Field>
      <div className="grid grid-cols-4 gap-2 mt-3">
        {[3, 7, 14, 30].map(n => (
          <button key={n} type="button" onClick={() => setDays(n)}
            className={'h-9 rounded-lg border text-sm transition ' + (Number(days) === n ? 'bg-m-accent/15 border-m-accent/40 text-m-accent' : 'bg-white/[0.03] border-m-line hover:bg-white/[0.07]')}>
            +{n} дн.
          </button>
        ))}
      </div>
    </Modal>
  );
}

function FrPromoDialog({ userId, onClose }) {
  const [days, setDays] = React.useState(7);
  const [loading, setLoading] = React.useState(false);
  const [code, setCode] = React.useState('');
  const t = useToast();
  const send = async () => {
    setLoading(true);
    try {
      const r = await frApi(`/users/${userId}/give-promo`, { method: 'POST', body: { new: { type: 'days', value: Number(days) } } });
      setCode(r.code || 'GIFT-XXXXXX');
      t.ok('Промокод создан');
    } catch (e) {
      if (e.code === 403) t.err('Действие недоступно — запросите доступ у владельца');
      else t.err(e.message || 'Ошибка');
    } finally { setLoading(false); }
  };
  const copy = () => { navigator.clipboard.writeText(code); t.ok('Скопировано'); };
  return (
    <Modal open onClose={onClose} title="Промокод на дни" width="max-w-md"
      footer={<>
        <Button variant="secondary" onClick={onClose}>Закрыть</Button>
        {!code && <Button onClick={send} loading={loading} icon={<Icon d={ICONS.sparkles} size={15}/>}>Создать</Button>}
      </>}
    >
      {!code ? (
        <>
          <Field label="Дней по промокоду">
            <Input type="number" min="1" max="365" value={days} onChange={e => setDays(e.target.value)}/>
          </Field>
          <div className="text-xs text-m-mute mt-3">Промокод одноразовый — после активации станет недействительным.</div>
        </>
      ) : (
        <div className="flex items-center gap-3 p-3 rounded-xl bg-m-bg2 border border-m-line">
          <code className="font-mono text-base text-m-accent flex-1">{code}</code>
          <Button size="sm" variant="secondary" onClick={copy} icon={<Icon d={ICONS.copy} size={14}/>}>Копировать</Button>
        </div>
      )}
    </Modal>
  );
}

// =======================================================================
// BROADCAST
// =======================================================================

function FrBroadcast() {
  const [text, setText] = React.useState('');
  const [premiumEmoji, setPremiumEmoji] = React.useState(false);
  const [mediaType, setMediaType] = React.useState('none');
  const [mediaName, setMediaName] = React.useState('');
  const [buttons, setButtons] = React.useState([]);
  const [jobs, setJobs] = React.useState([]);
  const [sending, setSending] = React.useState(false);
  const t = useToast();

  const loadJobs = React.useCallback(() => frApi('/broadcast/jobs').then(setJobs), []);
  React.useEffect(() => { loadJobs(); }, [loadJobs]);

  const send = async () => {
    setSending(true);
    try {
      await frApi('/broadcast', {
        method: 'POST',
        body: {
          text,
          media: mediaType === 'none' ? null : { type: mediaType, file_id: 'mock_' + Date.now() },
          buttons: buttons.filter(b => b.text && b.url),
          premium_emoji: premiumEmoji,
        },
      });
      t.ok('Рассылка поставлена в очередь');
      setText(''); setMediaType('none'); setMediaName(''); setButtons([]);
      loadJobs();
    } catch (e) { t.err(e.message || 'Ошибка'); }
    finally { setSending(false); }
  };

  return (
    <div className="fade-in">
      <SectionHeader title="Рассылка" subtitle="Сообщение всем вашим пользователям через бота франшизы"/>

      <div className="grid grid-cols-1 lg:grid-cols-5 gap-4">
        <div className="lg:col-span-3 flex flex-col gap-4">
          <Card>
            <div className="text-base font-semibold mb-4">Конструктор</div>
            <Field label="Текст сообщения" hint="Поддерживает Markdown / HTML, как в Telegram">
              <Textarea rows={7} value={text} onChange={e => setText(e.target.value)} placeholder="Сегодня даём -30% по коду …"/>
            </Field>

            <div className="mt-4">
              <div className="text-[12px] font-medium uppercase tracking-wide text-m-mute mb-2">Медиа</div>
              <div className="grid grid-cols-3 gap-2">
                {[
                  { v: 'none',  l: 'Без медиа', i: ICONS.close },
                  { v: 'photo', l: 'Фото',      i: ICONS.picture },
                  { v: 'video', l: 'Видео',     i: ICONS.zap },
                ].map(o => (
                  <button key={o.v} type="button" onClick={() => { setMediaType(o.v); if (o.v === 'none') setMediaName(''); }}
                    className={'flex items-center justify-center gap-2 h-10 rounded-xl border text-sm transition ' +
                      (mediaType === o.v ? 'bg-m-accent/15 border-m-accent/40 text-m-accent' : 'bg-white/[0.03] border-m-line hover:bg-white/[0.07]')}>
                    <Icon d={o.i} size={14}/> {o.l}
                  </button>
                ))}
              </div>
              {mediaType !== 'none' && (
                <div className="mt-2">
                  <label className="flex items-center gap-3 px-3 py-2.5 rounded-xl bg-m-bg2 border border-dashed border-m-line2 cursor-pointer hover:bg-white/[0.03]">
                    <Icon d={ICONS.download} size={16} className="text-m-mute"/>
                    <span className="text-sm text-m-mute flex-1 truncate">{mediaName || (mediaType === 'photo' ? 'Выберите фото…' : 'Выберите видео…')}</span>
                    <input type="file" className="hidden"
                      accept={mediaType === 'photo' ? 'image/*' : 'video/*'}
                      onChange={e => setMediaName(e.target.files[0]?.name || '')}/>
                  </label>
                </div>
              )}
            </div>

            <div className="mt-4">
              <div className="flex items-center justify-between mb-2">
                <div className="text-[12px] font-medium uppercase tracking-wide text-m-mute">Инлайн-кнопки</div>
                <Button size="sm" variant="ghost" onClick={() => setButtons(b => [...b, { text: '', url: '' }])} icon={<Icon d={ICONS.plus} size={14}/>}>Добавить</Button>
              </div>
              {buttons.length === 0 ? (
                <div className="text-xs text-m-dim px-3 py-2.5 rounded-lg bg-white/[0.02] border border-dashed border-m-line">Можно добавить до 5 кнопок-ссылок.</div>
              ) : (
                <div className="flex flex-col gap-2">
                  {buttons.map((b, i) => (
                    <div key={i} className="flex items-center gap-2">
                      <Input className="flex-1" placeholder="Текст кнопки" value={b.text} onChange={e => setButtons(arr => arr.map((x, j) => j === i ? { ...x, text: e.target.value } : x))}/>
                      <Input className="flex-[2]" placeholder="https://…" value={b.url} onChange={e => setButtons(arr => arr.map((x, j) => j === i ? { ...x, url: e.target.value } : x))}/>
                      <IconButton icon={ICONS.trash} variant="danger" onClick={() => setButtons(arr => arr.filter((_, j) => j !== i))}/>
                    </div>
                  ))}
                </div>
              )}
            </div>

            <div className="mt-5 pt-4 border-t border-m-line flex items-center justify-between gap-4 flex-wrap">
              <div className="flex items-center gap-3">
                <Switch checked={premiumEmoji} onChange={setPremiumEmoji}/>
                <div>
                  <div className="text-sm font-medium">Премиум-эмодзи</div>
                  <div className="text-xs text-m-mute">Бот должен иметь Telegram Premium</div>
                </div>
              </div>
              <Button onClick={send} loading={sending} disabled={!text.trim()} size="lg" icon={<Icon d={ICONS.send} size={16}/>}>Отправить</Button>
            </div>
          </Card>
        </div>

        <div className="lg:col-span-2 flex flex-col gap-4">
          <Card>
            <div className="text-[11px] uppercase tracking-wider text-m-mute mb-2">Предпросмотр</div>
            <div className="rounded-2xl bg-[#17212B] border border-m-line p-3.5">
              <div className="flex items-center gap-2 mb-2">
                <div className="h-7 w-7 rounded-full bg-m-accent/20 text-m-accent flex items-center justify-center text-xs font-bold">S</div>
                <div className="text-[13px] font-semibold">@speedvpn_bot</div>
              </div>
              {mediaType === 'photo' && (
                <div className="aspect-[16/10] rounded-lg bg-gradient-to-br from-m-accent/20 to-m-ok/10 border border-m-line flex items-center justify-center text-m-dim mb-2">
                  <Icon d={ICONS.picture} size={28}/>
                </div>
              )}
              {mediaType === 'video' && (
                <div className="aspect-[16/10] rounded-lg bg-gradient-to-br from-m-gold/20 to-m-accent/10 border border-m-line flex items-center justify-center text-m-dim mb-2">
                  <Icon d="M5 3l14 9-14 9V3z" fill="currentColor" sw="0" size={28}/>
                </div>
              )}
              <div className="text-[13px] text-m-text whitespace-pre-wrap leading-relaxed min-h-[40px]">
                {text || <span className="text-m-dim">Текст сообщения появится здесь…</span>}
              </div>
              {buttons.filter(b => b.text).length > 0 && (
                <div className="grid grid-cols-1 gap-1.5 mt-3">
                  {buttons.filter(b => b.text).map((b, i) => (
                    <div key={i} className="h-9 rounded-lg bg-m-accent/15 text-m-accent text-[13px] flex items-center justify-center font-medium">{b.text}</div>
                  ))}
                </div>
              )}
            </div>
          </Card>

          <Card padding="p-0">
            <div className="px-5 py-3.5 border-b border-m-line flex items-center justify-between">
              <div className="text-base font-semibold">История</div>
              <IconButton icon={ICONS.refresh} onClick={loadJobs}/>
            </div>
            <div className="divide-y divide-m-line">
              {jobs.length === 0
                ? <div className="px-5 py-8 text-center text-m-dim text-sm">Ещё не было рассылок.</div>
                : jobs.map(j => (
                <div key={j.id} className="px-5 py-3 flex items-center gap-3">
                  <div className="font-mono text-xs text-m-dim w-12">#{j.id}</div>
                  <div className="flex-1 min-w-0">
                    <div className="flex items-center gap-2">
                      {j.status === 'sent'      && <Badge tone="ok">Отправлено</Badge>}
                      {j.status === 'sending'   && <Badge tone="info" dot>Идёт</Badge>}
                      {j.status === 'scheduled' && <Badge tone="warn">Запланировано</Badge>}
                      {j.status === 'failed'    && <Badge tone="err">Ошибка</Badge>}
                    </div>
                    <div className="text-xs text-m-mute mt-1">{DATETIMEfr(j.created_at)}</div>
                  </div>
                  <div className="text-right text-xs">
                    <div className="text-m-text font-mono">{NUMfr(j.sent)}</div>
                    {j.failed > 0 && <div className="text-m-err font-mono">−{j.failed}</div>}
                  </div>
                </div>
              ))}
            </div>
          </Card>
        </div>
      </div>
    </div>
  );
}

// =======================================================================
// SETTINGS
// =======================================================================

function FrSettings() {
  const [s, setS] = React.useState(null);
  const [saving, setSaving] = React.useState(false);
  const t = useToast();
  React.useEffect(() => { frApi('/settings').then(setS); }, []);

  const upd = (patch) => setS(x => ({ ...x, ...patch }));
  const updBanner = (id, patch) => setS(x => ({ ...x, banners: x.banners.map(b => b.id === id ? { ...b, ...patch } : b) }));
  const addBanner = () => setS(x => ({ ...x, banners: [...x.banners, { id: Date.now(), title: '', body: '', active: true }] }));
  const delBanner = (id) => setS(x => ({ ...x, banners: x.banners.filter(b => b.id !== id) }));

  const save = async () => {
    setSaving(true);
    try {
      const res = await frApi('/settings', { method: 'PUT', body: s });
      if (res.settings) setS(res.settings);
      t.ok('Настройки сохранены');
    } catch (e) { t.err(e.message || 'Ошибка'); }
    finally { setSaving(false); }
  };

  if (!s) return <Loading/>;

  const priceTooLow = s.price < s.min_price;

  return (
    <div className="fade-in">
      <SectionHeader
        title="Настройки бота"
        subtitle="Цена, оформление и тексты — для пользователей вашей франшизы"
        right={<Button onClick={save} loading={saving} icon={<Icon d={ICONS.check} size={16}/>}>Сохранить</Button>}
      />

      <div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
        <Card>
          <div className="text-base font-semibold mb-4">Цена и оформление</div>
          <div className="grid grid-cols-2 gap-4">
            <Field
              label="Цена подписки, ₽"
              hint={`Не ниже минимальной ${RUBfr(s.min_price)} (сервер автоматически зажмёт меньшие значения)`}
              error={priceTooLow ? `Минимум ${RUBfr(s.min_price)}` : null}
            >
              <Input type="number" min={s.min_price} value={s.price} onChange={e => upd({ price: Number(e.target.value) })}/>
            </Field>
            <Field label="Цвет бренда" hint="Используется в боте и баннерах">
              <div className="flex items-center gap-2">
                <input type="color" value={s.brand_color} onChange={e => upd({ brand_color: e.target.value })} className="h-10 w-12 rounded-lg cursor-pointer"/>
                <Input value={s.brand_color} onChange={e => upd({ brand_color: e.target.value })} className="font-mono uppercase"/>
              </div>
            </Field>
          </div>

          <div className="mt-5">
            <Field label="Текст приветствия" hint="Показывается при первом запуске бота">
              <Textarea rows={4} value={s.welcome_text} onChange={e => upd({ welcome_text: e.target.value })}/>
            </Field>
          </div>
        </Card>

        <Card>
          <div className="text-base font-semibold mb-4">Канал и отзывы</div>
          <Field label="Обязательный канал" hint="Добавьте своего бота админом в канал — иначе проверка не работает">
            <Input value={s.required_channel_username || ''} placeholder="@speedvpn_news"
              onChange={e => upd({ required_channel_username: e.target.value })}/>
          </Field>
          <div className="mt-4">
            <Field label="Ссылка на отзыв">
              <Input value={s.review_url || ''} placeholder="https://t.me/c/…" onChange={e => upd({ review_url: e.target.value })} icon={ICONS.link}/>
            </Field>
          </div>
          <div className="mt-4">
            <Field label="Текст просьбы об отзыве">
              <Textarea rows={3} value={s.review_text || ''} onChange={e => upd({ review_text: e.target.value })}/>
            </Field>
          </div>

          <div className="mt-5 flex items-center gap-3 pt-4 border-t border-m-line">
            <Switch checked={s.stories_bonus_enabled} onChange={v => upd({ stories_bonus_enabled: v })}/>
            <div className="flex-1">
              <div className="text-sm font-medium">Бонус за сторис</div>
              <div className="text-xs text-m-mute">+3 дня за отметку бота в Stories</div>
            </div>
          </div>
        </Card>

        <Card className="lg:col-span-2" padding="p-0">
          <div className="px-5 py-4 border-b border-m-line flex items-center justify-between">
            <div>
              <div className="text-base font-semibold">Баннеры</div>
              <div className="text-xs text-m-mute mt-0.5">Появляются в боте над прайс-листом</div>
            </div>
            <Button size="sm" variant="secondary" onClick={addBanner} icon={<Icon d={ICONS.plus} size={14}/>}>Добавить</Button>
          </div>
          <div className="divide-y divide-m-line">
            {s.banners.length === 0
              ? <div className="px-5 py-8 text-center text-m-dim text-sm">Пока нет баннеров.</div>
              : s.banners.map(b => (
              <div key={b.id} className="px-5 py-4 grid grid-cols-1 md:grid-cols-[1fr_2fr_auto_auto] gap-3 items-center">
                <Input value={b.title} placeholder="Заголовок" onChange={e => updBanner(b.id, { title: e.target.value })}/>
                <Input value={b.body} placeholder="Описание" onChange={e => updBanner(b.id, { body: e.target.value })}/>
                <Switch checked={b.active} onChange={v => updBanner(b.id, { active: v })} label={b.active ? 'Вкл' : 'Выкл'}/>
                <IconButton icon={ICONS.trash} variant="danger" onClick={() => delBanner(b.id)}/>
              </div>
            ))}
          </div>
        </Card>
      </div>
    </div>
  );
}

// =======================================================================
// PAYOUTS / WITHDRAWALS
// =======================================================================

function FrWithdrawForm({ balance, onDone }) {
  const [amount, setAmount] = React.useState('');
  const [details, setDetails] = React.useState('');
  const [method, setMethod] = React.useState('card');
  const [loading, setLoading] = React.useState(false);
  const t = useToast();

  const amt = Number(amount || 0);
  const tooMuch = amt > balance;
  const tooLow  = amt > 0 && amt < 500;

  const submit = async () => {
    setLoading(true);
    try {
      await frApi('/withdraw', { method: 'POST', body: { amount: amt, details: `${method}: ${details}` } });
      t.ok('Запрос на выплату отправлен');
      setAmount(''); setDetails('');
      onDone && onDone();
    } catch (e) { t.err(e.message || 'Ошибка'); }
    finally { setLoading(false); }
  };

  return (
    <Card>
      <div className="text-base font-semibold mb-1">Запросить выплату</div>
      <div className="text-xs text-m-mute mb-5">Доступно к выводу: <span className="text-m-text font-mono">{RUBfr(balance)}</span></div>

      <Field label="Сумма, ₽" hint="Минимум 500 ₽" error={tooMuch ? 'Превышает доступный баланс' : tooLow ? 'Минимум 500 ₽' : null}>
        <Input type="number" min="500" max={balance} value={amount} placeholder="0" onChange={e => setAmount(e.target.value)}/>
      </Field>

      <div className="grid grid-cols-3 gap-2 mt-3">
        {[balance, Math.floor(balance / 2), 5000].filter(v => v > 0).map((v, i) => (
          <button key={i} type="button" onClick={() => setAmount(String(v))}
            className="h-9 rounded-lg bg-white/[0.03] border border-m-line hover:bg-white/[0.07] text-sm font-mono">
            {RUBfr(v)}
          </button>
        ))}
      </div>

      <div className="mt-5">
        <div className="text-[12px] font-medium uppercase tracking-wide text-m-mute mb-2">Метод</div>
        <div className="grid grid-cols-3 gap-2">
          {[
            { v: 'card',   l: 'Карта' },
            { v: 'ton',    l: 'TON' },
            { v: 'crypto', l: 'USDT' },
          ].map(o => (
            <button key={o.v} type="button" onClick={() => setMethod(o.v)}
              className={'h-10 rounded-xl border text-sm transition ' +
                (method === o.v ? 'bg-m-accent/15 border-m-accent/40 text-m-accent' : 'bg-white/[0.03] border-m-line hover:bg-white/[0.07]')}>
              {o.l}
            </button>
          ))}
        </div>
      </div>

      <div className="mt-4">
        <Field label="Реквизиты" hint={
          method === 'card'   ? 'Номер карты (16 цифр)'
        : method === 'ton'    ? 'TON-адрес вашего кошелька'
        :                       'USDT-адрес (TRC-20)'
        }>
          <Input value={details} onChange={e => setDetails(e.target.value)} placeholder={method === 'card' ? '0000 0000 0000 0000' : 'UQDx…'}/>
        </Field>
      </div>

      <Button className="w-full mt-5" size="lg" onClick={submit} loading={loading}
        disabled={!amt || tooMuch || tooLow || !details.trim()}
        icon={<Icon d={ICONS.wallet} size={16}/>}>
        Запросить выплату
      </Button>
    </Card>
  );
}

function FrPayouts({ initialOpen }) {
  const [dash, setDash] = React.useState(null);
  const [list, setList] = React.useState(null);

  const load = React.useCallback(async () => {
    const [d, l] = await Promise.all([frApi('/dashboard'), frApi('/withdrawals')]);
    setDash(d); setList(l);
  }, []);
  React.useEffect(() => { load(); }, [load]);

  if (!dash || !list) return <Loading/>;

  return (
    <div className="fade-in">
      <SectionHeader title="Выплаты" subtitle="Запросите вывод и следите за статусами"/>

      <div className="grid grid-cols-1 lg:grid-cols-5 gap-4">
        <div className="lg:col-span-2">
          <FrWithdrawForm balance={dash.balance} onDone={load}/>
        </div>

        <div className="lg:col-span-3">
          <Card padding="p-0">
            <div className="px-5 py-3.5 border-b border-m-line flex items-center justify-between">
              <div className="text-base font-semibold">История выплат</div>
              <Badge tone="mute">{NUMfr(list.length)}</Badge>
            </div>
            {list.length === 0 ? (
              <Empty title="Ещё не было выплат" subtitle="Запросите вывод выше — в среднем обработка занимает 1–2 рабочих дня."/>
            ) : (
              <table className="w-full text-sm">
                <thead>
                  <tr className="text-[11px] uppercase tracking-wider text-m-mute border-b border-m-line">
                    <th className="text-left font-medium px-5 py-3">Дата</th>
                    <th className="text-left font-medium px-3 py-3">Реквизиты</th>
                    <th className="text-right font-medium px-3 py-3">Сумма</th>
                    <th className="text-right font-medium px-5 py-3">Статус</th>
                  </tr>
                </thead>
                <tbody>
                  {list.map(w => (
                    <tr key={w.id} className="border-b border-m-line last:border-0">
                      <td className="px-5 py-3 text-m-mute">{DATETIMEfr(w.created_at)}</td>
                      <td className="px-3 py-3 font-mono text-xs text-m-text">{w.details}</td>
                      <td className="px-3 py-3 text-right font-mono font-semibold">{RUBfr(w.amount)}</td>
                      <td className="px-5 py-3 text-right">
                        {w.status === 'paid'     && <Badge tone="ok">выплачено</Badge>}
                        {w.status === 'pending'  && <Badge tone="warn" dot>в обработке</Badge>}
                        {w.status === 'rejected' && <Badge tone="err">отклонено</Badge>}
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            )}
          </Card>
        </div>
      </div>
    </div>
  );
}

// --------------- Exports -------------------------------------------------

Object.assign(window, {
  FrLogin, FrDashboard, FrUsers, FrBroadcast, FrSettings, FrPayouts,
});
