/* MBEX — Create order and order status flow */

function NetworkChips() {
  return (
    <div className="chip-row">
      <div className="choice-chip is-active">TRC-20</div>
    </div>
  );
}

const BUY_PRESETS_RUB = [5000, 10000, 50000, 100000];
const SELL_PRESETS_USDT = [300, 1000, 5000, 10000];
const TRC20_RE = /^T[a-zA-Z0-9]{33}$/;

function visitorFioValid(value) {
  return String(value || "").trim().split(/\s+/).filter(Boolean).length >= 2;
}

function cleanAmountInput(value) {
  return String(value || "").replace(/[^\d.,]/g, "");
}

function parseAmountInput(value) {
  const parsed = Number(String(value || "").replace(/\s/g, "").replace(",", ".") || 0);
  return Number.isFinite(parsed) ? parsed : 0;
}

function CreateOrderScreen({ draft, app, onConfirm, nav }) {
  const profile = app.privateState.profile || {};
  const wallets = app.privateState.wallets || [];
  const couriers = app.privateState.couriers || [];
  const referral = app.privateState.referral || {};
  const telegramUser = window.MBEX.getTelegramUser() || {};
  const defaultFio = profile.fio || `${telegramUser.last_name || ""} ${telegramUser.first_name || ""}`.trim();
  const buying = draft.dir === "buy";
  const selling = draft.dir === "sell";
  const directionAvailable = buying || selling;
  const hasInitialAmount = draft.inputValue !== "" && draft.inputValue !== null && draft.inputValue !== undefined;
  const initialAmount = hasInitialAmount && buying
    ? String(Math.round(Number(draft.inputValue || 0)))
    : (hasInitialAmount ? String(draft.inputValue) : "");
  const [amount, setAmount] = React.useState(initialAmount);
  const [fio, setFio] = React.useState(draft.fio || defaultFio);
  const [wallet, setWallet] = React.useState(wallets[0] ? wallets[0].address : "");
  const [selectedWallet, setSelectedWallet] = React.useState(wallets[0] ? wallets[0].id : null);
  const [delivery, setDelivery] = React.useState("self");
  const [courierFio, setCourierFio] = React.useState(couriers[0] ? couriers[0].fio : "");
  const [selectedCourier, setSelectedCourier] = React.useState(couriers[0] ? couriers[0].id : null);
  const [agree, setAgree] = React.useState(false);
  const liveRate = buying ? app.publicState.rates.buy : app.publicState.rates.sell;
  const rate = Number(liveRate || draft.rate || 0);
  const amountNum = parseAmountInput(amount);
  const effectiveAmountNum = buying
    ? window.MBEX.snapRubStepAmount(amountNum, 1000)
    : amountNum;
  const networkFeeUsdt = Number(app.publicState.rates.commissionSettings?.network_fee_usdt || 0);
  const buyEstimate = buying
    ? window.MBEX.calculateBuyEstimate(effectiveAmountNum, rate, profile, referral, networkFeeUsdt)
    : (draft.buyEstimate || { walletUsdt: 0, networkFeeUsdt: 0, commissionUsdt: 0, grossUsdt: 0, commissionPct: 0 });
  const sellEstimate = selling
    ? window.MBEX.calculateSellEstimate(effectiveAmountNum, rate, profile)
    : (draft.sellEstimate || { payoutRub: 0, commissionRub: 0, grossRub: 0, commissionPct: 0 });
  const limits = app.publicState.rates.sellLimits || { min_usdt: 65, max_usdt: 100000 };
  const minSell = Number(limits.min_usdt || 65);
  const maxSell = Number(limits.max_usdt || 100000);
  const buyEnabled = app.publicState.rates.tradeAvailability?.buy_enabled !== false;
  const sellEnabled = app.publicState.rates.tradeAvailability?.sell_enabled !== false;
  const kycVerified = Boolean(profile.verified);

  React.useEffect(() => {
    setFio(draft.fio || defaultFio);
  }, [defaultFio, draft.fio]);

  React.useEffect(() => {
    if (wallets.length && !wallet) {
      setWallet(wallets[0].address);
      setSelectedWallet(wallets[0].id);
    }
  }, [wallet, wallets]);

  React.useEffect(() => {
    if (couriers.length && !courierFio) {
      setCourierFio(couriers[0].fio || "");
      setSelectedCourier(couriers[0].id);
    }
  }, [courierFio, couriers]);

  React.useEffect(() => {
    if (!kycVerified && delivery === "courier") {
      setDelivery("self");
    }
  }, [delivery, kycVerified]);

  function onAmountChange(event) {
    setAmount(cleanAmountInput(event.target.value));
  }

  function onAmountBlur() {
    if (!buying || amountNum <= 0) {
      return;
    }
    setAmount(String(window.MBEX.snapRubStepAmount(amountNum, 1000)));
  }

  async function pasteWallet() {
    if (!navigator.clipboard || !navigator.clipboard.readText) {
      app.pushToast("Вставьте адрес вручную", "error");
      return;
    }
    try {
      const text = (await navigator.clipboard.readText()).trim();
      if (!text) {
        app.pushToast("Буфер обмена пуст", "error");
        return;
      }
      setWallet(text);
      setSelectedWallet(null);
    } catch (error) {
      app.pushToast("Не удалось прочитать буфер. Вставьте адрес вручную.", "error");
    }
  }

  function submit() {
    if (!valid) {
      app.pushToast(validationMessage, "error");
      return;
    }
    onConfirm({
      dir: draft.dir,
      sumRub: effectiveAmountNum,
      sumUsdt: effectiveAmountNum,
      fio: fio.trim(),
      wallet: wallet.trim(),
      delivery,
      courierFio: delivery === "courier" ? courierFio.trim() : "",
    });
  }

  const currentEnabled = buying ? buyEnabled : sellEnabled;
  const amountOk = buying
    ? amountNum > 0 && effectiveAmountNum >= 1000
    : amountNum >= minSell && amountNum <= maxSell;
  const fioOk = visitorFioValid(fio);
  const walletOk = buying ? TRC20_RE.test(wallet.trim()) : true;
  const courierOk = delivery !== "courier" || (kycVerified && visitorFioValid(courierFio));
  const valid = currentEnabled && amountOk && fioOk && walletOk && courierOk && agree;
  const validationMessage = !currentEnabled
    ? (buying ? "Покупка USDT временно недоступна" : "Продажа USDT временно недоступна")
    : !amountOk
      ? (buying ? "Минимальная сумма покупки — 1 000 ₽" : `Сумма продажи должна быть от ${window.MBEX.fmtUsdt(minSell)} до ${window.MBEX.fmtUsdt(maxSell)} USDT`)
      : !fioOk
        ? "Укажите фамилию и имя клиента"
        : !walletOk
          ? "Укажите корректный TRC-20 адрес: T + 33 символа"
          : !courierOk
            ? (!kycVerified
              ? "Чтобы оформить заявку на другого получателя, сначала пройдите KYC"
              : "Укажите фамилию и имя получателя")
            : !agree
              ? "Подтвердите правила заявки"
              : "";
  const receiveText = buying
    ? `${window.MBEX.fmtUsdt(buyEstimate.walletUsdt || 0)} USDT`
    : `${window.MBEX.fmtRub(sellEstimate.payoutRub || 0)} ₽`;
  const summaryMode = buying ? "Покупка" : "Продажа";
  const summaryMeta = `1 USDT = ${window.MBEX.fmtRub2(rate)} ₽`;
  const summaryPayText = buying
    ? `${window.MBEX.fmtRub(effectiveAmountNum)} ₽`
    : `${window.MBEX.fmtUsdt(effectiveAmountNum)} USDT`;

  if (!directionAvailable) {
    return (
      <div className="body">
        <EmptyState
          icon={<Icons.info size={28} />}
          title="Сценарий недоступен"
          text="Создайте заявку на покупку или продажу USDT."
        />
      </div>
    );
  }

  return (
    <div className="body">
      <div className="stack screen-enter">
        <div className="create-summary-card">
          <div className="create-summary-head">
            <Pill cls="pill-accent">{summaryMode}</Pill>
            <span className="num">{summaryMeta}</span>
          </div>
          <div className="create-summary-main">
            <div>
              <span>Вы платите</span>
              <strong className="num">{summaryPayText}</strong>
            </div>
            <Icons.chevR size={22} sw={2.2} />
            <div>
              <span>Вы получаете</span>
              <strong className="num">{receiveText}</strong>
            </div>
          </div>
        </div>

        {buying ? (
          <>
            <div className="card card-pad buy-create-card stack-sm">
              <div>
                <span className="field-lbl">Сумма покупки</span>
                <span className="muted-3 create-amount-hint">Минимум 1 000 ₽, шаг 500 ₽</span>
                <div className="buy-input-shell">
                  <input
                    className="amount-input num"
                    data-testid="order-amount-input"
                    inputMode="numeric"
                    placeholder="Введите сумму"
                    value={amount}
                    onChange={onAmountChange}
                    onBlur={onAmountBlur}
                  />
                  <div className="cur-chip">
                    <Coin kind="rub" />
                    RUB
                  </div>
                </div>
                <div className="preset-grid">
                  {BUY_PRESETS_RUB.map((preset) => (
                    <button
                      key={preset}
                      type="button"
                      className={Math.round(effectiveAmountNum) === preset ? "is-active" : ""}
                      onClick={() => setAmount(String(preset))}
                    >
                      {window.MBEX.fmtRub(preset)}
                    </button>
                  ))}
                </div>
              </div>
              <div className="buy-estimate-box">
                <SummaryRow label="≈ Предварительно" value={`${window.MBEX.fmtUsdt(buyEstimate.walletUsdt || 0)} USDT`} strong />
                <SummaryRow label="Комиссия" value={`${window.MBEX.fmtUsdt(buyEstimate.commissionUsdt || 0)} USDT / ${window.MBEX.fmtPct(buyEstimate.commissionPct || 0)}%`} />
                <SummaryRow label="Комиссия сети TRC-20" value={`${window.MBEX.fmtUsdt(buyEstimate.networkFeeUsdt || 0)} USDT`} />
              </div>
            </div>

            <div className="card card-pad buy-create-card stack-sm">
              <div>
                <span className="field-lbl">ФИО</span>
                <input
                  className="field"
                  data-testid="order-fio-input"
                  placeholder="Фамилия Имя Отчество"
                  value={fio}
                  onChange={(event) => setFio(event.target.value)}
                />
              </div>
              <div className="mini-tabs">
                <button className={delivery === "self" ? "is-active" : ""} type="button" onClick={() => setDelivery("self")}>
                  Приеду сам
                </button>
                <button
                  className={delivery === "courier" ? "is-active" : ""}
                  type="button"
                  disabled={!kycVerified}
                  onClick={() => setDelivery("courier")}
                >
                  Другое ФИО
                </button>
              </div>
              {!kycVerified ? (
                <div className="kyc-recipient-note">
                  <Icons.info size={16} sw={2.2} />
                  <span>Чтобы оформить заявку на другого получателя, сначала пройдите KYC.</span>
                </div>
              ) : null}
              {delivery === "courier" ? (
                <div>
                  <span className="field-lbl">ФИО получателя</span>
                  <input
                    className="field"
                    placeholder="Фамилия Имя Отчество"
                    value={courierFio}
                    onChange={(event) => {
                      setCourierFio(event.target.value);
                      setSelectedCourier(null);
                    }}
                  />
                  {couriers.length ? (
                    <div className="saved-pills">
                      {couriers.slice(0, 5).map((item) => (
                        <button
                          key={item.id}
                          type="button"
                          className={selectedCourier === item.id ? "is-active" : ""}
                          onClick={() => {
                            setSelectedCourier(item.id);
                            setCourierFio(item.fio || "");
                          }}
                        >
                          {item.fio}
                        </button>
                      ))}
                    </div>
                  ) : null}
                  {nav ? (
                    <button type="button" className="btn-link saved-manage-link" onClick={() => nav("couriers")}>
                      Управлять получателями
                    </button>
                  ) : null}
                </div>
              ) : null}
            </div>

            <div className="card card-pad buy-create-card stack-sm">
              <div>
                <span className="field-lbl">Сеть получения</span>
                <NetworkChips />
              </div>
              <div>
                <span className="field-lbl">TRC-20 кошелёк для получения USDT</span>
                <div className="wallet-input-row">
                  <input
                    className="field num"
                    data-testid="buy-wallet-input"
                    placeholder="Txxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
                    value={wallet}
                    onChange={(event) => {
                      setWallet(event.target.value);
                      setSelectedWallet(null);
                    }}
                  />
                  <button type="button" onClick={pasteWallet}>Вставить</button>
                </div>
              </div>

              {wallets.length ? (
                <div>
                  <div className="section-headline saved-section-head">
                    <span>Сохранённые кошельки</span>
                    {nav ? <button type="button" onClick={() => nav("wallets")}>Управлять</button> : null}
                  </div>
                  <div className="wallet-list">
                    {wallets.slice(0, 5).map((item) => (
                      <div
                        key={item.id}
                        className={`wallet-card ${selectedWallet === item.id ? "is-active" : ""}`}
                        onClick={() => {
                          setSelectedWallet(item.id);
                          setWallet(item.address);
                        }}
                      >
                        <div className="wallet-card-name">{item.name}</div>
                        <div className="wallet-card-addr wallet-address-full">{item.address}</div>
                      </div>
                    ))}
                  </div>
                </div>
              ) : (
                <>
                  <EmptyState
                    icon={<Icons.wallet size={24} />}
                    title="Сохранённых кошельков нет"
                    text="Вставьте TRC-20 адрес вручную. Сохранённые адреса появятся здесь после добавления в профиле."
                  />
                  {nav ? (
                    <button type="button" className="btn btn-primary btn-sm saved-empty-action" onClick={() => nav("wallets")}>
                      Добавить кошелёк
                    </button>
                  ) : null}
                </>
              )}
            </div>

            <div className="rules-check" data-testid="order-rules-check" onClick={() => setAgree((value) => !value)}>
              <span className={agree ? "is-checked" : ""}>
                {agree ? <Icons.check size={14} sw={2.6} /> : null}
              </span>
              <div>
                Я проверил сумму, ФИО и TRC-20 адрес. Понимаю, что курс и комиссия
                фиксируются по правилам MBEX при обработке заявки.
              </div>
            </div>
          </>
        ) : (
          <>
            <div className="card card-pad buy-create-card stack-sm">
              <div>
                <span className="field-lbl">Сумма продажи</span>
                <div className="buy-input-shell">
                  <input
                    className="amount-input num"
                    data-testid="order-amount-input"
                    inputMode="decimal"
                    placeholder={`От ${window.MBEX.fmtUsdt(minSell)} USDT`}
                    value={amount}
                    onChange={onAmountChange}
                  />
                  <div className="cur-chip">
                    <Coin kind="usdt" />
                    USDT
                  </div>
                </div>
                <div className="preset-grid">
                  {SELL_PRESETS_USDT.map((preset) => (
                    <button
                      key={preset}
                      type="button"
                      className={Math.round(amountNum) === preset ? "is-active" : ""}
                      onClick={() => setAmount(String(preset))}
                    >
                      {preset.toLocaleString("ru-RU")}
                    </button>
                  ))}
                </div>
              </div>
              <div className="buy-estimate-box sell-estimate-box">
                <SummaryRow label="≈ Предварительно" value={`${window.MBEX.fmtRub(sellEstimate.payoutRub || 0)} ₽`} strong />
                <SummaryRow label="Комиссия" value={`${window.MBEX.fmtRub(sellEstimate.commissionRub || 0)} ₽ / ${window.MBEX.fmtPct(sellEstimate.commissionPct || 0)}%`} />
              </div>
            </div>

            <div className="card card-pad stack-sm">
              <div>
                <span className="field-lbl">ФИО</span>
                <input
                  className="field"
                  data-testid="order-fio-input"
                  placeholder="Фамилия Имя Отчество"
                  value={fio}
                  onChange={(event) => setFio(event.target.value)}
                />
              </div>
              <div className="mini-tabs">
                <button className={delivery === "self" ? "is-active" : ""} type="button" onClick={() => setDelivery("self")}>
                  Приеду сам
                </button>
                <button
                  className={delivery === "courier" ? "is-active" : ""}
                  type="button"
                  disabled={!kycVerified}
                  onClick={() => setDelivery("courier")}
                >
                  Другое ФИО
                </button>
              </div>
              {!kycVerified ? (
                <div className="kyc-recipient-note">
                  <Icons.info size={16} sw={2.2} />
                  <span>Чтобы оформить заявку на другого получателя, сначала пройдите KYC.</span>
                </div>
              ) : null}
              {delivery === "courier" ? (
                <div>
                  <span className="field-lbl">ФИО получателя RUB</span>
                  <input
                    className="field"
                    placeholder="Фамилия Имя Отчество"
                    value={courierFio}
                    onChange={(event) => {
                      setCourierFio(event.target.value);
                      setSelectedCourier(null);
                    }}
                  />
                  {couriers.length ? (
                    <div className="saved-pills">
                      {couriers.slice(0, 5).map((item) => (
                        <button
                          key={item.id}
                          type="button"
                          className={selectedCourier === item.id ? "is-active" : ""}
                          onClick={() => {
                            setSelectedCourier(item.id);
                            setCourierFio(item.fio || "");
                          }}
                        >
                          {item.fio}
                        </button>
                      ))}
                    </div>
                  ) : null}
                  {nav ? (
                    <button type="button" className="btn-link saved-manage-link" onClick={() => nav("couriers")}>
                      Управлять получателями
                    </button>
                  ) : null}
                </div>
              ) : null}
            </div>

            <div className="card card-pad stack-sm sell-flow-card">
              <div className="field-lbl">Перевод USDT</div>
              <div className="mini-legend">
                <div className="mini-legend-row">
                  <span>Сумма перевода</span>
                  <strong>{window.MBEX.fmtUsdt(minSell)}-{window.MBEX.fmtUsdt(maxSell)} USDT</strong>
                </div>
                <div className="mini-legend-row">
                  <span>Куда отправить</span>
                  <strong>Адрес TRC-20 на 30 минут</strong>
                </div>
                <div className="mini-legend-row">
                  <span>Что дальше</span>
                  <strong>Проверим перевод и рассчитаем сумму в рублях</strong>
                </div>
              </div>
              <div className="status-note">
                Отправьте USDT в сети TRC-20 на указанный адрес в течение 30 минут.
                Адрес создан только для этой заявки. После поступления перевода мы покажем
                точную сумму к получению в рублях.
              </div>
            </div>

            <div className="rules-check" data-testid="order-rules-check" onClick={() => setAgree((value) => !value)}>
              <span className={agree ? "is-checked" : ""}>
                {agree ? <Icons.check size={14} sw={2.6} /> : null}
              </span>
              <div>
                Я понимаю, что нужно отправить USDT в сети TRC-20 в пределах указанных лимитов.
                Точная сумма к получению будет рассчитана после поступления перевода.
              </div>
            </div>
          </>
        )}

        <div style={{ padding: "8px 0 0" }}>
          {!valid ? (
            <div className="form-error-note">{validationMessage}</div>
          ) : null}
          <button className="btn btn-primary" data-testid="submit-order" disabled={!valid} onClick={submit}>
            {buying ? "Подтвердить заявку" : "Получить депозитный адрес"}
          </button>
        </div>
      </div>
    </div>
  );
}

function refundStatusText(refund) {
  if (!refund) {
    return "";
  }
  const amount = Number(refund.amount_usdt || 0);
  const amountText = amount > 0 ? `${window.MBEX.fmtUsdt(amount)} USDT` : "депозит";
  if (refund.status === "pending_review") {
    return `Обращение создано. Оператор проверяет ${amountText}.`;
  }
  if (refund.status === "approved" || refund.status === "sweeping") {
    return "Возврат одобрен. Средства переводятся на возвратный кошелёк MBEX.";
  }
  if (refund.status === "awaiting_wallet") {
    return "Оператор одобрил возврат. Укажите TRC-20 кошелёк для получения.";
  }
  if (refund.status === "sent") {
    return "Возврат отправлен вручную. Подтвердите получение после проверки транзакции.";
  }
  if (refund.status === "confirmed") {
    return "Клиент подтвердил получение возврата.";
  }
  if (refund.status === "rejected") {
    return "Обращение отклонено оператором.";
  }
  return refund.status || "Статус возврата обновляется";
}

function depositStatusText(status) {
  const labels = {
    waiting: "Ожидает USDT",
    aml_pending: "AML проверка",
    deposited: "USDT получены",
    swept: "Средства обработаны",
    refund_swept: "Готовится возврат",
    aml_failed: "AML разбор",
    limit_failed: "Сумма вне лимитов",
    expired: "Адрес истёк",
  };
  return labels[status || "waiting"] || status || "Ожидает USDT";
}

const DEPOSIT_COPY_NOTICE_SUPPRESS_KEY = "mbex_deposit_copy_notice_suppressed_until";
const DEPOSIT_COPY_NOTICE_SUPPRESS_MS = 7 * 24 * 60 * 60 * 1000;

function isDepositCopyNoticeSuppressed() {
  try {
    return Number(localStorage.getItem(DEPOSIT_COPY_NOTICE_SUPPRESS_KEY)) > Date.now();
  } catch {
    return false;
  }
}

function suppressDepositCopyNotice() {
  try {
    localStorage.setItem(
      DEPOSIT_COPY_NOTICE_SUPPRESS_KEY,
      String(Date.now() + DEPOSIT_COPY_NOTICE_SUPPRESS_MS),
    );
    return true;
  } catch {
    return false;
  }
}

function DepositCopyNotice({ address, onClose }) {
  const [suppressForWeek, setSuppressForWeek] = React.useState(false);

  React.useEffect(() => {
    const handleKeyDown = (event) => {
      if (event.key === "Escape") {
        onClose();
      }
    };
    document.addEventListener("keydown", handleKeyDown);
    return () => document.removeEventListener("keydown", handleKeyDown);
  }, [onClose]);

  function handleConfirm() {
    if (suppressForWeek) {
      suppressDepositCopyNotice();
    }
    onClose();
  }

  return ReactDOM.createPortal(
    <div className="deposit-copy-notice-overlay">
      <section
        className="deposit-copy-notice-sheet"
        role="dialog"
        aria-modal="true"
        aria-label="Предупреждение о сети перевода"
      >
        <div className="deposit-copy-notice-icon" aria-hidden="true">
          <Icons.check size={30} sw={2.8} />
        </div>
        <strong><span className="num wallet-address-full deposit-copy-address">{address}</span> скопирован</strong>
        <p>
          Отправляйте USDT на этот адрес только через сеть <b>TRC-20</b>.
          Перевод через другую сеть может привести к тому, что депозит не будет зачислен.
        </p>
        <label className="deposit-copy-notice-suppress">
          <input
            type="checkbox"
            checked={suppressForWeek}
            onChange={(event) => setSuppressForWeek(event.target.checked)}
          />
          <span>Не напоминать мне в течение 7 дней</span>
        </label>
        <button type="button" className="btn btn-primary deposit-copy-notice-confirm" onClick={handleConfirm}>
          Подтвердить
        </button>
      </section>
    </div>,
    document.body,
  );
}

function DetailValue({ label, value, copy, url, onCopied, wrapValue = false }) {
  if (value === null || value === undefined || value === "") {
    return null;
  }
  async function handleCopy(event) {
    if (!copy) {
      return;
    }
    event.stopPropagation();
    const copied = await window.MBEX.copyText(value);
    if (copied && onCopied) {
      onCopied(value);
    }
  }
  return (
    <div className={`detail-value-row${wrapValue ? " has-wrapping-value" : ""}`}>
      <span>{label}</span>
      <strong
        className={`${copy ? "is-copyable " : ""}num${wrapValue ? " wallet-address-full" : ""}`}
        onClick={handleCopy}
      >
        {value}
      </strong>
      {url ? (
        <button type="button" className="detail-link-btn" onClick={() => window.MBEX.openExternalUrl(url)}>
          <Icons.chevR size={15} sw={2.2} />
        </button>
      ) : null}
    </div>
  );
}

function OrderTimeline({ order, app }) {
  const items = window.MBEX.buildOrderTimeline(order, app.nowMs);
  const [expanded, setExpanded] = React.useState(false);
  const activeIndex = items.findIndex((item) => ["current", "warn", "error"].includes(item.state));
  const currentIndex = activeIndex >= 0 ? activeIndex : Math.max(items.length - 1, 0);
  const currentItem = items[currentIndex];
  const showNext = (
    order.serverStatus !== "cancelled"
    && currentItem
    && !["warn", "error"].includes(currentItem.state)
    && currentIndex < items.length - 1
  );
  const compactItems = items
    .slice(currentIndex, currentIndex + (showNext ? 2 : 1))
    .map((item, offset) => ({ item, index: currentIndex + offset }));
  const visibleItems = expanded
    ? items.map((item, index) => ({ item, index }))
    : compactItems;
  const canExpand = compactItems.length < items.length;

  React.useEffect(() => {
    setExpanded(false);
  }, [order.id]);

  return (
    <div className={`card card-pad order-timeline-card ${expanded ? "is-expanded" : "is-compact"}`}>
      <div className="section-headline order-timeline-header">
        <div className="order-timeline-heading">
          <span>Этапы</span>
          <small>Этап {currentIndex + 1} из {items.length}</small>
        </div>
        <Pill cls="pill-muted">{window.MBEX.orderDirectionCode(order)}</Pill>
      </div>
      <div className="order-timeline" aria-label={`Этапы заявки, этап ${currentIndex + 1} из ${items.length}`}>
        {visibleItems.map(({ item, index }, visibleIndex) => (
          <div key={`${item.title}-${index}`} className={`timeline-item is-${item.state}`}>
            {visibleIndex < visibleItems.length - 1 ? <div className="timeline-rail" /> : null}
            <div className="timeline-dot">
              {item.state === "done" ? <Icons.check size={13} sw={2.6} /> : index + 1}
            </div>
            <div className="timeline-copy" aria-current={index === currentIndex ? "step" : undefined}>
              <strong>{item.title}</strong>
              <span className={item.text === order.wallet ? "num wallet-address-full" : ""}>
                {item.text}
              </span>
            </div>
          </div>
        ))}
      </div>
      {canExpand ? (
        <button
          type="button"
          className="order-timeline-toggle"
          aria-expanded={expanded}
          onClick={() => setExpanded((value) => !value)}
        >
          <span>{expanded ? "Свернуть" : "Показать все этапы"}</span>
          <Icons.chevR size={16} sw={2.2} />
        </button>
      ) : null}
    </div>
  );
}

function OrderDetailCard({ order, app, statusMeta, onDepositCopied }) {
  const buying = order.typeKey === "buy";
  const selling = order.typeKey === "sell";
  const transfer = order.typeKey === "transfer";
  const tronscanBase = app.publicState.config?.tronscan_base;
  const route = [order.fromCity, order.toCity].filter(Boolean).join(" → ");
  const recipient = order.delivery === "courier" && order.courierFio ? order.courierFio : "";
  const visitorPassLabels = {
    pending_create: "Оформляем",
    created: "Создан, статус уточняется",
    pending_approval: "На согласовании",
    active: "Действующий",
    prepared: "Оформлен",
    ready: "Готов к выдаче",
    used: "Отработан",
    rejected: "Отклонён",
    withdraw_pending: "Отзываем",
    withdrawn: "Отозван",
    expired: "Просрочен",
    replaced: "Заменён",
    manual_review: "Проверяет оператор",
  };
  const amountRows = [
    <DetailValue key="code" label="Код заявки" value={window.MBEX.orderDisplayCode(order)} copy />,
    <DetailValue key="type" label="Тип" value={window.MBEX.orderTypeLabel(order)} />,
    (buying || selling) ? <DetailValue key="network" label="Сеть" value="Tron (TRC-20)" /> : null,
    <DetailValue key="status" label="Статус" value={statusMeta.title || order.serverStatus} />,
    <DetailValue key="created" label="Создана" value={window.MBEX.formatDateTime(order.createdAt)} />,
    <DetailValue key="amount" label={selling ? "Сумма" : "Сумма RUB"} value={window.MBEX.orderDisplayAmount(order)} />,
    order.sumUsdt > 0 ? <DetailValue key="usdt" label="USDT" value={`${window.MBEX.fmtUsdt(order.sumUsdt)} USDT`} /> : null,
    order.rate > 0 ? <DetailValue key="rate" label="Курс" value={`${window.MBEX.fmtRub2(order.rate)} ₽`} /> : null,
    order.commissionUsdt > 0 ? <DetailValue key="commission" label="Комиссия" value={`${window.MBEX.fmtUsdt(order.commissionUsdt)} USDT`} /> : null,
    buying ? <DetailValue key="network-fee" label="Комиссия сети TRC-20" value={`${window.MBEX.fmtUsdt(order.networkFeeUsdt)} USDT`} /> : null,
    order.commissionDiscountPct > 0 ? <DetailValue key="discount" label="Скидка комиссии" value={`${order.commissionDiscountPct}%`} /> : null,
    <DetailValue key="fio" label="ФИО" value={order.fio || "—"} />,
    recipient ? <DetailValue key="recipient" label="Получатель" value={recipient} /> : null,
    order.visitorPassState ? <DetailValue key="visitor-pass" label="Гостевой пропуск" value={visitorPassLabels[order.visitorPassState] || order.visitorPassState} /> : null,
    order.visitorPassVisitDate ? <DetailValue key="visitor-pass-date" label="Дата посещения" value={order.visitorPassVisitDate} /> : null,
    order.visitorPassExternalId ? <DetailValue key="visitor-pass-id" label="Номер пропуска" value={String(order.visitorPassExternalId)} copy /> : null,
    route ? <DetailValue key="route" label={transfer ? "Маршрут" : "Город"} value={route} /> : null,
  ];
  const walletRows = [
    buying && order.wallet ? (
      <DetailValue
        key="wallet"
        label="Кошелёк получения"
        value={order.wallet}
        copy
        wrapValue
        url={window.MBEX.tronscanAddress(order.wallet, tronscanBase)}
      />
    ) : null,
    selling && order.depositAddress ? (
      <DetailValue
        key="deposit-wallet"
        label="Депозитный адрес"
        value={order.depositAddress}
        copy
        wrapValue
        url={window.MBEX.tronscanAddress(order.depositAddress, tronscanBase)}
        onCopied={onDepositCopied}
      />
    ) : null,
    order.txHash ? (
      <DetailValue
        key="tx"
        label="TX hash"
        value={order.txHash}
        copy
        url={window.MBEX.tronscanTx(order.txHash, tronscanBase)}
      />
    ) : null,
    order.depositTxHash ? (
      <DetailValue
        key="deposit-tx"
        label="TX депозита"
        value={order.depositTxHash}
        copy
        url={window.MBEX.tronscanTx(order.depositTxHash, tronscanBase)}
      />
    ) : null,
  ];
  return (
    <div className="card card-pad order-detail-card">
      <div className="field-lbl">Детали заявки</div>
      <div className="detail-value-list">
        {amountRows}
        {walletRows}
      </div>
    </div>
  );
}

function OrderStatusScreen({ order, app, onCancel, onRepeat }) {
  const [refundMessage, setRefundMessage] = React.useState("");
  const [copiedDepositAddress, setCopiedDepositAddress] = React.useState("");
  const [refundWallet, setRefundWallet] = React.useState(order?.refund?.client_wallet || "");

  React.useEffect(() => {
    setRefundWallet(order?.refund?.client_wallet || "");
  }, [order]);

  React.useEffect(() => {
    setCopiedDepositAddress("");
  }, [order?.id]);

  if (!order) {
    return (
      <div className="body">
        <EmptyState
          icon={<Icons.info size={28} />}
          title="Заявка не найдена"
          text="Обновите список заявок и попробуйте открыть статус ещё раз."
        />
      </div>
    );
  }

  const statusMeta = window.MBEX.getStatusMeta(order, app.nowMs);
  const secondsLeft = window.MBEX.getOrderSecondsLeft(order, app.nowMs);
  const buying = order.typeKey === "buy";
  const selling = order.typeKey === "sell";
  const transfer = order.typeKey === "transfer";
  const StatusIcon = transfer ? Icons.swap : buying ? Icons.arrowDown : Icons.arrowUp;
  const canCancel = order.serverStatus === "pending";
  const refund = order.refund || null;
  const refundEligible = window.MBEX.isRefundEligible(order);
  const depositReady = selling && Boolean(order.depositAddress);
  const depositStatus = order.depositStatus || "waiting";

  function handleDepositCopied(address) {
    if (!isDepositCopyNoticeSuppressed()) {
      setCopiedDepositAddress(address);
    }
  }

  async function handleRefundRequest() {
    await app.requestRefund(order.id, refundMessage);
  }

  async function handleRefundWallet() {
    if (!refund) {
      return;
    }
    await app.submitRefundWallet(refund.id, refundWallet);
  }

  async function handleRefundConfirm() {
    if (!refund) {
      return;
    }
    await app.confirmRefund(refund.id);
  }

  return (
    <div className="body">
      <div className="stack screen-enter">
        <div className="card card-pad order-status-hero">
          <div className="order-status-icon">
            <StatusIcon size={28} />
          </div>
          <Pill cls={statusMeta.pillClass} dot={statusMeta.pillDot}>
            {window.MBEX.orderDirectionCode(order)}
          </Pill>
          <div className="h2">{statusMeta.title}</div>
          <div className="muted" style={{ fontSize: 13, marginTop: 5, lineHeight: 1.45 }}>
            {statusMeta.subtitle}
          </div>
          {!["completed", "cancelled"].includes(order.serverStatus) ? (
            <div className="center" style={{ justifyContent: "center", marginTop: 10, gap: 8 }}>
              <Pill cls={statusMeta.pillClass} dot={statusMeta.pillDot}>
                {secondsLeft > 0 ? window.MBEX.formatDuration(secondsLeft) : "00:00"}
              </Pill>
            </div>
          ) : null}
        </div>

        <div className="order-timeline-section">
          <OrderTimeline order={order} app={app} />
        </div>

        {transfer ? (
          <div className="card card-pad stack-sm">
            <div className="field-lbl">Маршрут перестановки</div>
            <div className="mini-legend">
              <div className="mini-legend-row">
                <span>Откуда</span>
                <strong>{order.fromCity || "уточняется"}</strong>
              </div>
              <div className="mini-legend-row">
                <span>Куда</span>
                <strong>{order.toCity || "уточняется"}</strong>
              </div>
              <div className="mini-legend-row">
                <span>Сумма</span>
                <strong>{window.MBEX.fmtRub(order.sumRub)} ₽</strong>
              </div>
            </div>
            <div className="status-note">
              Менеджер обработает перестановку и обновит статус заявки. Если нужно
              уточнить маршрут или время, напишите в поддержку.
            </div>
          </div>
        ) : null}

        {selling ? (
          <>
            <div className="order-wallet-card sell-deposit-card stack-sm">
              <div className="order-wallet-head sell-deposit-head">
                <div>
                  <span>TRC-20 депозит</span>
                  <strong>{depositReady ? "Переведите USDT на этот адрес" : "Адрес ещё готовится"}</strong>
                </div>
                <Pill cls={secondsLeft > 0 ? "pill-neg" : "wallet-timer-expired"}>
                  {secondsLeft > 0 ? window.MBEX.formatDuration(secondsLeft) : "00:00"}
                </Pill>
              </div>

              {depositReady ? (
                <CopyField
                  label="Адрес для перевода"
                  value={order.depositAddress}
                  actionLabel="Нажмите на поле, чтобы скопировать адрес"
                  wrapValue
                  onCopied={handleDepositCopied}
                />
              ) : (
                <div className="deposit-empty-address">
                  Backend создал заявку, но депозитный адрес пока не вернулся. Обновите
                  статус или свяжитесь с поддержкой, если адрес не появился.
                </div>
              )}

              <div className="order-wallet-note sell-deposit-warning">
                Переводите только USDT TRC-20. Другие сети и суммы вне лимитов
                потребуют ручного разбора.
              </div>
            </div>

            <div className="card card-pad stack-sm">
              <div className="mini-legend">
                <div className="mini-legend-row">
                  <span>Статус депозита</span>
                  <strong>{depositStatusText(depositStatus)}</strong>
                </div>
                <div className="mini-legend-row">
                  <span>Получено</span>
                  <strong>{order.depositAmountReceived > 0 ? `${window.MBEX.fmtUsdt(order.depositAmountReceived)} USDT` : "0 USDT"}</strong>
                </div>
                <div className="mini-legend-row">
                  <span>К выдаче</span>
                  <strong>{order.depositSumRubCalculated > 0 ? `${window.MBEX.fmtRub(order.depositSumRubCalculated)} ₽` : "ждём расчёт"}</strong>
                </div>
              </div>
              <button className="btn btn-primary btn-sm" onClick={() => app.refreshOrderDeposit(order.id)}>
                Обновить депозит
              </button>
              {order.depositTxHash ? (
                <CopyField label="TX депозита" value={order.depositTxHash} mono={false} />
              ) : null}
            </div>
          </>
        ) : null}

        <OrderDetailCard
          order={order}
          app={app}
          statusMeta={statusMeta}
          onDepositCopied={handleDepositCopied}
        />

        {refund ? (
          <div className="card card-pad stack-sm">
            <div className="field-lbl">Возврат проблемного депозита продажи</div>
            <div className="status-note">{refundStatusText(refund)}</div>
            {refund.status === "awaiting_wallet" ? (
              <>
                <input
                  className="field num"
                  placeholder="TRC-20 кошелёк для возврата"
                  value={refundWallet}
                  onChange={(event) => setRefundWallet(event.target.value)}
                />
                <button className="btn btn-primary btn-sm" onClick={handleRefundWallet}>
                  Сохранить кошелёк
                </button>
              </>
            ) : null}
            {refund.status === "sent" ? (
              <button className="btn btn-soft btn-sm" onClick={handleRefundConfirm}>
                Подтвердить получение
              </button>
            ) : null}
          </div>
        ) : null}

        {refundEligible && !refund ? (
          <div className="card card-pad stack-sm">
            <div className="field-lbl">Оставить обращение на возврат</div>
            <textarea
              className="textarea-field"
              placeholder="Комментарий оператору (необязательно)"
              value={refundMessage}
              onChange={(event) => setRefundMessage(event.target.value)}
            />
            <button className="btn btn-primary btn-sm" onClick={handleRefundRequest}>
              Создать обращение
            </button>
          </div>
        ) : null}

        <div className="order-status-actions">
          {canCancel ? (
            <button className="btn btn-ghost" onClick={onCancel}>
              Отменить заявку
            </button>
          ) : null}

          {!transfer ? (
            <button className="btn btn-soft" onClick={onRepeat}>
              Повторить заявку
            </button>
          ) : null}

          <button className="btn btn-soft" onClick={() => window.MBEX.openTelegramUrl(app.supportUrl)}>
            Открыть поддержку
          </button>
        </div>
      </div>
      {copiedDepositAddress ? (
        <DepositCopyNotice
          address={copiedDepositAddress}
          onClose={() => setCopiedDepositAddress("")}
        />
      ) : null}
    </div>
  );
}

window.CreateOrderScreen = CreateOrderScreen;
window.OrderStatusScreen = OrderStatusScreen;
