const { useEffect, useMemo, useState } = React;

async function api(path, options = {}) {
  const res = await fetch(path, {
    credentials: "include",
    headers: { "Content-Type": "application/json", ...(options.headers || {}) },
    ...options,
  });
  if (!res.ok) {
    let detail = "Ошибка запроса";
    try { detail = (await res.json()).detail || detail; } catch (_) {}
    throw new Error(Array.isArray(detail) ? detail.map(x => x.msg).join(", ") : detail);
  }
  return res.json();
}

function fmtMoney(value) {
  return new Intl.NumberFormat("ru-RU", { style: "currency", currency: "RUB", maximumFractionDigits: 2 }).format(Number(value || 0));
}
function fmtDate(value) {
  return value ? new Intl.DateTimeFormat("ru-RU", { dateStyle: "short", timeStyle: "short" }).format(new Date(value)) : "";
}
function paymentLabel(value) {
  return ({ unpaid: "Не оплачен", partially_paid: "Оплачен частично", paid: "Оплачен", canceled: "Отменен", unknown: "Неизвестно" })[value] || value;
}
function shipmentLabel(value) {
  return ({ not_shipped: "Не отгружен", partially_shipped: "Отгружен частично", shipped: "Отгружен", unknown: "Неизвестно" })[value] || value;
}
function signatureLabel(value) {
  return ({ not_signed: "Не подписан", signed: "Подписан", unknown: "Неизвестно" })[value] || value;
}

function Login({ onLogin }) {
  const [login, setLogin] = useState("");
  const [password, setPassword] = useState("");
  const [error, setError] = useState("");
  async function submit(e) {
    e.preventDefault();
    setError("");
    try { onLogin(await api("/api/auth/login", { method: "POST", body: JSON.stringify({ login, password }) })); }
    catch (err) { setError(err.message); }
  }
  return <main className="login">
    <form onSubmit={submit}>
      <div className="brand">Score</div>
      {error && <div className="toast">{error}</div>}
      <input placeholder="Логин" value={login} onChange={e => setLogin(e.target.value)} autoFocus />
      <input placeholder="Пароль" type="password" value={password} onChange={e => setPassword(e.target.value)} />
      <button className="primary">Войти</button>
    </form>
  </main>;
}

function Shell({ user, setUser }) {
  const [path, setPath] = useState(location.pathname === "/" ? "/dashboard" : location.pathname);
  useEffect(() => {
    const onPop = () => setPath(location.pathname);
    addEventListener("popstate", onPop);
    return () => removeEventListener("popstate", onPop);
  }, []);
  function nav(to) { history.pushState(null, "", to); setPath(to); }
  async function logout() { await api("/api/auth/logout", { method: "POST" }); setUser(null); }
  const page = path.startsWith("/invoices") ? <Invoices /> :
    path.startsWith("/shipping") ? <Shipping /> :
    path.startsWith("/admin/users") ? <Users /> :
    path.startsWith("/admin/organizations") ? <Organizations /> :
    path.startsWith("/admin/sync") ? <Sync /> : <Dashboard />;
  return <div className="shell">
    <aside className="sidebar">
      <div className="brand">Score</div>
      <nav className="nav">
        <a href="/dashboard" className={path.startsWith("/dashboard") ? "active" : ""} onClick={e => { e.preventDefault(); nav("/dashboard"); }}>Dashboard</a>
        <a href="/invoices" className={path.startsWith("/invoices") ? "active" : ""} onClick={e => { e.preventDefault(); nav("/invoices"); }}>Счета</a>
        <a href="/shipping" className={path.startsWith("/shipping") ? "active" : ""} onClick={e => { e.preventDefault(); nav("/shipping"); }}>Отгрузка</a>
        {user.role === "admin" && <a href="/admin/organizations" className={path.startsWith("/admin/organizations") ? "active" : ""} onClick={e => { e.preventDefault(); nav("/admin/organizations"); }}>Организации</a>}
        {user.role === "admin" && <a href="/admin/users" className={path.startsWith("/admin/users") ? "active" : ""} onClick={e => { e.preventDefault(); nav("/admin/users"); }}>Пользователи</a>}
        {user.role === "admin" && <a href="/admin/sync" className={path.startsWith("/admin/sync") ? "active" : ""} onClick={e => { e.preventDefault(); nav("/admin/sync"); }}>Синхронизация</a>}
      </nav>
      <div className="userbox">
        <div>{user.login} · {user.role}</div>
        <button onClick={logout}>Выйти</button>
      </div>
    </aside>
    <main className="main">{page}</main>
  </div>;
}

function Dashboard() {
  const [data, setData] = useState(null);
  const [error, setError] = useState("");
  useEffect(() => { api("/api/dashboard/summary").then(setData).catch(e => setError(e.message)); }, []);
  if (error) return <div className="toast">{error}</div>;
  if (!data) return <div>Загрузка...</div>;
  return <>
    <div className="topbar"><h1>Dashboard</h1></div>
    <section className="grid metrics">
      <div className="metric"><div className="label">Неоплаченных счетов</div><div className="value">{data.total_unpaid_count}</div></div>
      <div className="metric"><div className="label">Сумма неоплаченных</div><div className="value">{fmtMoney(data.total_unpaid_amount)}</div></div>
      <div className="metric"><div className="label">Без номера заказа</div><div className="value">{data.without_order_number_count}</div></div>
      <div className="metric"><div className="label">Сумма без номера</div><div className="value">{fmtMoney(data.without_order_number_amount)}</div></div>
    </section>
    <section className="grid" style={{marginTop: 14, gridTemplateColumns: "1fr 1fr"}}>
      <div className="panel"><h2>По организациям</h2><SimpleTable rows={data.by_organization} columns={[["name","Организация"],["count","Счетов"],["amount","Сумма"]]} money="amount" /></div>
      <div className="panel"><h2>Синхронизация</h2><SimpleTable rows={data.sync_statuses} columns={[["name","Организация"],["last_success_sync_at","Успешно"],["last_sync_error","Ошибка"]]} /></div>
    </section>
  </>;
}

function SimpleTable({ rows, columns, money }) {
  function cellValue(value) {
    if (typeof value === "boolean") return value ? "Да" : "Нет";
    return String(value ?? "");
  }
  return <div className="table-wrap"><table><thead><tr>{columns.map(c => <th key={c[0]}>{c[1]}</th>)}</tr></thead><tbody>
    {rows.map((row, i) => <tr key={i}>{columns.map(c => <td key={c[0]} className={money === c[0] ? "money" : ""}>{money === c[0] ? fmtMoney(row[c[0]]) : cellValue(row[c[0]])}</td>)}</tr>)}
  </tbody></table></div>;
}

function Invoices() {
  const [rows, setRows] = useState([]);
  const [orgs, setOrgs] = useState([]);
  const [selected, setSelected] = useState(null);
  const [filters, setFilters] = useState({ organization_id: "", order_number: "" });
  const [error, setError] = useState("");
  async function load() {
    const qs = new URLSearchParams(Object.entries(filters).filter(([,v]) => v));
    setRows(await api(`/api/invoices?${qs}`));
  }
  useEffect(() => { load().catch(e => setError(e.message)); }, [filters]);
  useEffect(() => { api("/api/organizations").then(setOrgs).catch(() => setOrgs([])); }, []);
  return <>
    <div className="topbar"><h1>Счета</h1><div className="row"><button onClick={() => location.href="/api/invoices/export/xlsx"}>XLSX</button><button onClick={() => location.href="/api/invoices/export/pdf"}>PDF</button></div></div>
    {error && <div className="toast">{error}</div>}
    <div className="toolbar">
      <select value={filters.organization_id} onChange={e => setFilters({...filters, organization_id: e.target.value})}><option value="">Все организации</option>{orgs.map(o => <option key={o.id} value={o.id}>{o.name}</option>)}</select>
      <select value={filters.order_number} onChange={e => setFilters({...filters, order_number: e.target.value})}><option value="">Все номера заказа</option><option value="missing">Нет номера</option><option value="present">Есть номер</option></select>
      <button className="icon" title="Обновить" onClick={load}>↻</button>
    </div>
    <div className="table-wrap"><table><thead><tr><th>Организация</th><th>Номер</th><th>Дата</th><th className="money">Сумма</th><th>Оплата</th><th>Контрагент</th><th>Комментарий 1С</th><th>Номер заказа</th><th>Комментарии</th><th>Синхронизация</th></tr></thead><tbody>
      {rows.map(r => <tr key={r.id} onClick={() => setSelected(r)}><td>{r.organization_name}</td><td>{r.number}</td><td>{fmtDate(r.date)}</td><td className="money">{fmtMoney(r.amount)}</td><td>{paymentLabel(r.payment_status)}</td><td>{r.counterparty_name}</td><td>{r.one_c_comment}</td><td>{r.order_number || <span className="muted">нет</span>}</td><td>{r.comments_count}</td><td>{fmtDate(r.last_seen_at)}</td></tr>)}
    </tbody></table></div>
    {selected && <InvoiceDrawer invoice={selected} close={() => { setSelected(null); load(); }} />}
  </>;
}

function Shipping() {
  const [data, setData] = useState(null);
  const [error, setError] = useState("");
  async function load() {
    setError("");
    try { setData(await api("/api/shipping")); }
    catch (e) { setError(e.message); }
  }
  useEffect(() => { load(); }, []);
  const rows = data?.rows || [];
  return <>
    <div className="topbar"><h1>Отгружено без подписи</h1><button className="icon" title="Обновить" onClick={load}>↻</button></div>
    {error && <div className="toast">{error}</div>}
    {!data ? <div>Загрузка...</div> : <>
      <section className="grid metrics">
        {data.summary.map(item => <div className="metric" key={item.status}>
          <div className="label">{item.label}</div>
          <div className="value">{item.count}</div>
          <div className="muted">{fmtMoney(item.amount)}</div>
        </div>)}
      </section>
      {data.by_organization?.length > 0 && <section className="panel" style={{marginTop: 14}}>
        <h2>По фирмам</h2>
        <SimpleTable rows={data.by_organization} columns={[["organization","Фирма"],["count","Отгрузок"],["amount","Сумма"]]} money="amount" />
      </section>}
      <div className="table-wrap" style={{marginTop: 14}}><table><thead><tr><th>Фирма</th><th>Счет</th><th>Дата</th><th className="money">Сумма</th><th>Оплата</th><th>Отгрузка</th><th>Подпись</th><th>Номер отгрузки</th><th>Контрагент</th><th>Номер заказа</th><th>Комментарий 1С</th><th>Синхронизация</th></tr></thead><tbody>
        {rows.map(row => <tr key={row.id}><td>{row.organization_name}</td><td>{row.number}</td><td>{fmtDate(row.date)}</td><td className="money">{fmtMoney(row.amount)}</td><td>{paymentLabel(row.payment_status)}</td><td>{row.shipment_status_label || shipmentLabel(row.shipment_status)}</td><td>{row.signature_status_label || signatureLabel(row.signature_status)}</td><td>{((row.shipment_numbers || row.realization_numbers || []).join(", ")) || <span className="muted">нет</span>}</td><td>{row.counterparty_name}</td><td>{row.order_number || <span className="muted">нет</span>}</td><td>{row.one_c_comment}</td><td>{fmtDate(row.last_seen_at)}</td></tr>)}
      </tbody></table></div>
    </>}
  </>;
}

function InvoiceDrawer({ invoice, close }) {
  const [detail, setDetail] = useState(invoice);
  const [comments, setComments] = useState([]);
  const [orderNumber, setOrderNumber] = useState(invoice.order_number || "");
  const [comment, setComment] = useState("");
  const [error, setError] = useState("");
  async function load() {
    setDetail(await api(`/api/invoices/${invoice.id}`));
    setComments(await api(`/api/invoices/${invoice.id}/comments`));
  }
  useEffect(() => { load().catch(e => setError(e.message)); }, []);
  async function saveOrder() {
    setError("");
    try { setDetail(await api(`/api/invoices/${invoice.id}/order-number`, { method: "PATCH", body: JSON.stringify({ order_number: orderNumber }) })); }
    catch (e) { setError(e.message); }
  }
  async function addComment() {
    setError("");
    try { await api(`/api/invoices/${invoice.id}/comments`, { method: "POST", body: JSON.stringify({ comment }) }); setComment(""); await load(); }
    catch (e) { setError(e.message); }
  }
  return <>
    <div className="drawer-backdrop" onClick={close}></div>
    <aside className="drawer">
      <div className="topbar"><h1>{detail.number}</h1><button className="icon" onClick={close}>×</button></div>
      {error && <div className="toast">{error}</div>}
      <div className="stack">
        <div><b>{detail.organization_name}</b></div>
        <div>{fmtDate(detail.date)} · {fmtMoney(detail.amount)}</div>
        <div>{detail.counterparty_name}</div>
        <div className="muted">{detail.one_c_comment}</div>
        <label>Номер заказа<input value={orderNumber} onChange={e => setOrderNumber(e.target.value.replace(/\D/g, "").slice(0, 32))} /></label>
        <button className="primary" onClick={saveOrder}>Сохранить</button>
        <h2>Комментарии</h2>
        {comments.map(c => <div className="comment" key={c.id}><b>{c.author}</b> <span className="muted">{fmtDate(c.created_at)}</span><div>{c.comment}</div></div>)}
        <textarea value={comment} onChange={e => setComment(e.target.value)} placeholder="Комментарий" />
        <button onClick={addComment}>Добавить</button>
        <h2>Технические данные</h2>
        <div className="muted">Ref_Key: {detail.ref_key}</div>
        <div className="muted">DataVersion: {detail.data_version}</div>
      </div>
    </aside>
  </>;
}

function Organizations() {
  const empty = { name: "", odata_base_url: "", invoice_entity_set: "Document_СчетНаОплатуПокупателю", one_c_username: "", one_c_password: "", is_active: true, include_in_dashboards: true, sync_interval_minutes: 5, payment_strategy: "metadata_unknown" };
  const [rows, setRows] = useState([]);
  const [form, setForm] = useState(empty);
  const [message, setMessage] = useState("");
  async function load() { setRows(await api("/api/admin/organizations")); }
  useEffect(() => { load(); }, []);
  async function submit(e) { e.preventDefault(); await api("/api/admin/organizations", { method: "POST", body: JSON.stringify(form) }); setForm(empty); load(); }
  async function test(id) { setMessage(JSON.stringify(await api(`/api/admin/organizations/${id}/test-connection`, { method: "POST" }), null, 2)); }
  async function sync(id) { setMessage(JSON.stringify(await api(`/api/admin/organizations/${id}/sync-now`, { method: "POST" }), null, 2)); load(); }
  async function toggleDashboards(org) {
    await api(`/api/admin/organizations/${org.id}`, { method: "PATCH", body: JSON.stringify({ include_in_dashboards: !org.include_in_dashboards }) });
    await load();
  }
  return <><div className="topbar"><h1>Организации</h1></div><div className="forms">
    <form className="panel stack" onSubmit={submit}>
      <h2>Новая организация</h2>
      {Object.keys(empty).map(k => ["is_active", "include_in_dashboards"].includes(k) ? null : <input key={k} placeholder={k} value={form[k]} onChange={e => setForm({...form, [k]: e.target.value})} />)}
      <button className="primary">Добавить</button>
    </form>
    <div className="panel"><SimpleTable rows={rows} columns={[["name","Название"],["invoice_entity_set","EntitySet"],["is_active","Активна"],["include_in_dashboards","В дашбордах"],["last_success_sync_at","Синхр."],["last_sync_error","Ошибка"]]} />
      <div className="stack" style={{marginTop: 12}}>{rows.map(o => <div className="row" key={o.id}><b>{o.name}</b><button onClick={() => test(o.id)}>Проверить</button><button onClick={() => sync(o.id)}>Синхронизировать</button><button onClick={() => toggleDashboards(o)}>{o.include_in_dashboards ? "Убрать из дашбордов" : "Вернуть в дашборды"}</button></div>)}</div>
      {message && <pre>{message}</pre>}
    </div>
  </div></>;
}

function Users() {
  const [rows, setRows] = useState([]);
  const [form, setForm] = useState({ login: "", password: "", role: "user", is_active: true });
  async function load() { setRows(await api("/api/admin/users")); }
  useEffect(() => { load(); }, []);
  async function submit(e) { e.preventDefault(); await api("/api/admin/users", { method: "POST", body: JSON.stringify(form) }); setForm({ login: "", password: "", role: "user", is_active: true }); load(); }
  return <><div className="topbar"><h1>Пользователи</h1></div><div className="forms">
    <form className="panel stack" onSubmit={submit}><h2>Новый пользователь</h2><input placeholder="Логин" value={form.login} onChange={e => setForm({...form, login: e.target.value})} /><input placeholder="Пароль" type="password" value={form.password} onChange={e => setForm({...form, password: e.target.value})} /><select value={form.role} onChange={e => setForm({...form, role: e.target.value})}><option value="user">user</option><option value="admin">admin</option></select><button className="primary">Создать</button></form>
    <div className="panel"><SimpleTable rows={rows} columns={[["login","Логин"],["role","Роль"],["is_active","Активен"],["last_login_at","Последний вход"]]} /></div>
  </div></>;
}

function Sync() {
  const [result, setResult] = useState("");
  async function syncAll() { setResult(JSON.stringify(await api("/api/admin/organizations/sync-all", { method: "POST" }), null, 2)); }
  return <><div className="topbar"><h1>Синхронизация</h1><button className="primary" onClick={syncAll}>Синхронизировать все</button></div><pre>{result}</pre></>;
}

function App() {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);
  useEffect(() => { api("/api/auth/me").then(setUser).catch(() => setUser(null)).finally(() => setLoading(false)); }, []);
  if (loading) return <div className="login">Загрузка...</div>;
  return user ? <Shell user={user} setUser={setUser} /> : <Login onLogin={setUser} />;
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
