/* ============================================================
   AGENDA — Clientes, Serviços, Equipe (CRUD via API)
   ============================================================ */

/* ---------------- CLIENTES ---------------- */
function ClientsScreen(ctx) {
  const { terms, clients, companies, team, appts, openNewAppt, toast, services, settings = {} } = ctx;
  const DB = window.DB;
  const [mode, setMode] = React.useState('clientes');
  const [q, setQ] = React.useState(ctx.clientQ || '');
  const [tag, setTag] = React.useState('Todos');
  const [proF, setProF] = React.useState(ctx.clientPro || 'all');
  const [page, setPage] = React.useState(1);
  const [sel, setSel] = React.useState(null);
  const [selCompany, setSelCompany] = React.useState(null);
  const [editing, setEditing] = React.useState(null); // cliente em edição
  const [adding, setAdding] = React.useState(false);
  const [editingCompany, setEditingCompany] = React.useState(null);
  const [addingCompany, setAddingCompany] = React.useState(false);
  const [addingForCompany, setAddingForCompany] = React.useState(null);
  const f = { privacyConsentAt: '', privacyConsentSource: '', privacyNotes: '', notes: '' };
  const set = () => () => {};

  const defaultCategories = ['Novo', 'Ativo', 'VIP', 'Corporativo', 'Inativo'];
  const savedCategories = (() => {
    try {
      const parsed = JSON.parse(settings.client_categories || '[]');
      return Array.isArray(parsed) ? parsed.map((item) => String(item || '').trim()).filter(Boolean) : [];
    } catch { return []; }
  })();
  const categories = [...new Set([...(savedCategories.length ? savedCategories : defaultCategories), ...clients.map((c) => String(c.tag || '').trim()).filter(Boolean)])];
  const tags = ['Todos', ...categories];
  const tagCls = { VIP: 'violet', Ativo: 'green', Novo: 'blue', Corporativo: 'amber', Inativo: 'red' };
  const qText = q.toLowerCase();
  const qDigits = DB.mask.digits(q);
  const filtered = clients.filter(c =>
    (tag === 'Todos' || c.tag === tag) &&
    (proF === 'all' || c.proId === proF) &&
    (c.name.toLowerCase().includes(qText) || c.email.toLowerCase().includes(qText) || c.phone.includes(q) ||
      (c.companyName || '').toLowerCase().includes(qText) || (c.companyEmail || '').toLowerCase().includes(qText) ||
      (c.companyCnpj || '').includes(q) || (qDigits && DB.mask.digits(c.companyCnpj || '').includes(qDigits)))
  );
  const pageSize = 20;
  const totalPages = Math.max(1, Math.ceil(filtered.length / pageSize));
  const currentPage = Math.min(page, totalPages);
  const pageStart = (currentPage - 1) * pageSize;
  const paginatedClients = filtered.slice(pageStart, pageStart + pageSize);
  const pageItems = (() => {
    if (totalPages <= 7) return Array.from({ length: totalPages }, (_, index) => index + 1);
    if (currentPage <= 4) return [1, 2, 3, 4, 5, 'end-gap', totalPages];
    if (currentPage >= totalPages - 3) return [1, 'start-gap', ...Array.from({ length: 5 }, (_, index) => totalPages - 4 + index)];
    return [1, 'start-gap', currentPage - 1, currentPage, currentPage + 1, 'end-gap', totalPages];
  })();
  React.useEffect(() => setPage(1), [q, tag, proF, mode]);
  React.useEffect(() => {
    if (page > totalPages) setPage(totalPages);
  }, [page, totalPages]);
  const filteredCompanies = companies.filter(c =>
    c.name.toLowerCase().includes(qText) || (c.email || '').toLowerCase().includes(qText) ||
    (c.phone || '').includes(q) || (c.cnpj || '').includes(q) ||
    (qDigits && DB.mask.digits(c.cnpj || '').includes(qDigits))
  );
  const proOf = (id) => team.find(p => p.id === id);
  const ini = (n) => n.split(' ').map(x => x[0]).slice(0, 2).join('').toUpperCase();
  const colorFor = (id) => DB.colors[id % DB.colors.length];
  const employeesOf = (companyId) => clients.filter(c => c.companyId === companyId).sort((a, b) => a.name.localeCompare(b.name));

  const clientAppts = (id) => appts.filter(a => a.clientId === id).sort((a, b) => b.date.localeCompare(a.date));

  const saveClient = async (data) => {
    try {
      const payload = addingForCompany ? { ...data, companyId: addingForCompany.id } : data;
      if (editing) { await ctx.updateClient(editing.id, payload); toast('Dados atualizados!'); }
      else { await ctx.addClient(payload); toast(terms.client + ' cadastrado!'); }
      setAdding(false); setEditing(null); setAddingForCompany(null);
    } catch (e) { toast(e.message, 'x'); }
  };

  const addClientCategory = async (value) => {
    const name = String(value || '').trim().replace(/\s+/g, ' ');
    if (!name) return null;
    const existing = categories.find((item) => item.toLocaleLowerCase('pt-BR') === name.toLocaleLowerCase('pt-BR'));
    if (existing) {
      toast('Essa categoria já está cadastrada.', 'info');
      return existing;
    }
    try {
      await ctx.saveClientCategories([...categories, name]);
      toast('Categoria cadastrada!');
      return name;
    } catch (e) {
      toast(e.message || 'Não foi possível cadastrar a categoria.', 'x');
      return null;
    }
  };

  const deleteClientCategory = async (name) => {
    const linked = clients.filter((client) => client.tag === name).length;
    if (linked > 0) {
      toast(`A categoria "${name}" possui ${linked} aluno${linked === 1 ? '' : 's'} vinculado${linked === 1 ? '' : 's'}.`, 'x');
      return false;
    }
    if (categories.length <= 1) {
      toast('Mantenha ao menos uma categoria.', 'x');
      return false;
    }
    if (!window.confirm(`Excluir a categoria "${name}"?`)) return false;
    try {
      await ctx.saveClientCategories(categories.filter((item) => item !== name));
      if (tag === name) setTag('Todos');
      toast('Categoria excluída!');
      return true;
    } catch (e) {
      toast(e.message || 'Não foi possível excluir a categoria.', 'x');
      return false;
    }
  };

  const saveCompany = async (data) => {
    try {
      if (editingCompany) { await ctx.updateCompany(editingCompany.id, data); toast('Empresa atualizada!'); }
      else { await ctx.addCompany(data); toast('Empresa cadastrada!'); }
      setAddingCompany(false); setEditingCompany(null);
    } catch (e) { toast(e.message, 'x'); }
  };

  const removeClient = (c) => {
    if (!window.confirm(`Excluir ${c.name}? Os ${terms.appt.toLowerCase()}s vinculados ficarão sem ${terms.client.toLowerCase()}.`)) return;
    setSel(null);
    ctx.deleteClient(c.id);
  };

  const removeCompany = (c) => {
    if (!window.confirm(`Excluir ${c.name}?`)) return;
    setSelCompany(null);
    ctx.deleteCompany(c.id);
  };

  return (
    <div className="content-inner fadein">
      <Header title={terms.clients} sub={`${clients.length} ${terms.clients.toLowerCase()} · ${companies.length} empresas`} action={
        mode === 'empresas'
          ? <window.Button variant="primary" icon="plus" onClick={() => setAddingCompany(true)}>Nova empresa</window.Button>
          : <window.Button variant="primary" icon="plus" onClick={() => setAdding(true)}>Novo {terms.client.toLowerCase()}</window.Button>
      } />

      <div className="row between wrap" style={{ marginBottom: 14, gap: 10 }}>
        <div className="seg">
          <button className={mode === 'clientes' ? 'active' : ''} onClick={() => setMode('clientes')}>{terms.clients}</button>
          <button className={mode === 'empresas' ? 'active' : ''} onClick={() => setMode('empresas')}>Empresas</button>
        </div>
        <div style={{ display: 'none' }}>
        {false && <window.SectionLabel style={{ gridColumn: '1 / -1', margin: '6px 0 0' }}>LGPD</window.SectionLabel>}
        {false && <window.Field label="Consentimento registrado em" optional>
          <window.Input type="date" value={f.privacyConsentAt} onChange={set('privacyConsentAt')} />
        </window.Field>}
        {false && <window.Field label="Origem / base do registro" optional>
          <window.Input placeholder="Ex.: formulário, WhatsApp, contrato, ficha assinada" value={f.privacyConsentSource} onChange={set('privacyConsentSource')} />
        </window.Field>}
        <window.Field label="Observações de privacidade" optional full>
          <window.Textarea placeholder="Ex.: titular pediu contato só por WhatsApp, consentimento arquivado em papel, restrição de uso..." value={f.privacyNotes} onChange={set('privacyNotes')} />
        </window.Field>

        <window.SectionLabel style={{ gridColumn: '1 / -1', margin: '6px 0 0' }}>LGPD</window.SectionLabel>
        <window.Field label="Consentimento registrado em" optional>
          <window.Input type="date" value={f.privacyConsentAt} onChange={set('privacyConsentAt')} />
        </window.Field>
        <window.Field label="Origem / base do registro" optional>
          <window.Input placeholder="Ex.: formulário, WhatsApp, contrato, ficha assinada" value={f.privacyConsentSource} onChange={set('privacyConsentSource')} />
        </window.Field>
        <window.Field label="Observações de privacidade" optional full>
          <window.Textarea placeholder="Ex.: titular pediu contato só por WhatsApp, consentimento arquivado em papel, restrição de uso..." value={f.privacyNotes} onChange={set('privacyNotes')} />
        </window.Field>
        <window.SectionLabel style={{ gridColumn: '1 / -1', margin: '6px 0 0' }}>LGPD</window.SectionLabel>
        <window.Field label="Consentimento registrado em" optional>
          <window.Input type="date" value={f.privacyConsentAt} onChange={set('privacyConsentAt')} />
        </window.Field>
        <window.Field label="Origem / base do registro" optional>
          <window.Input placeholder="Ex.: formulário, WhatsApp, contrato, ficha assinada" value={f.privacyConsentSource} onChange={set('privacyConsentSource')} />
        </window.Field>
        <window.Field label="Observações de privacidade" optional full>
          <window.Textarea placeholder="Ex.: titular pediu contato só por WhatsApp, consentimento arquivado em papel, restrição de uso..." value={f.privacyNotes} onChange={set('privacyNotes')} />
        </window.Field>
        <window.SectionLabel style={{ gridColumn: '1 / -1', margin: '6px 0 0' }}>LGPD</window.SectionLabel>
        <window.Field label="Consentimento registrado em" optional>
          <window.Input type="date" value={f.privacyConsentAt} onChange={set('privacyConsentAt')} />
        </window.Field>
        <window.Field label="Origem / base do registro" optional>
          <window.Input placeholder="Ex.: formulário, WhatsApp, contrato, ficha assinada" value={f.privacyConsentSource} onChange={set('privacyConsentSource')} />
        </window.Field>
        <window.Field label="Observações de privacidade" optional full>
          <window.Textarea placeholder="Ex.: titular pediu contato só por WhatsApp, consentimento arquivado em papel, restrição de uso..." value={f.privacyNotes} onChange={set('privacyNotes')} />
        </window.Field>
        <window.Field label="Observações" optional full><window.Textarea placeholder="Preferências, alergias, anotações…" value={f.notes} onChange={set('notes')} /></window.Field>
        </div>
      </div>

      {mode === 'clientes' && <div className="card" style={{ overflow: 'hidden' }}>
        <div className="row between wrap" style={{ padding: 14, gap: 12, borderBottom: '1px solid var(--border)' }}>
          <div className="row wrap" style={{ gap: 7 }}>
            {tags.map(t => <button key={t} className={'chip' + (tag === t ? ' active' : '')} onClick={() => setTag(t)}>{t}</button>)}
          </div>
          <div className="row" style={{ gap: 8 }}>
            <window.Select value={proF} onChange={e => setProF(e.target.value === 'all' ? 'all' : Number(e.target.value))} style={{ minWidth: 170 }}>
              <option value="all">{terms.pros}</option>
              {team.filter((p) => !p.systemIdentity && !p.archived).map(p => <option key={p.id} value={p.id}>{p.name}</option>)}
            </window.Select>
            <div className="input-icon" style={{ minWidth: 240 }}>
              <window.Icon name="search" size={16} />
              <input className="input" placeholder="Buscar por nome, empresa, e-mail, telefone…" value={q} onChange={e => setQ(e.target.value)} />
            </div>
          </div>
        </div>

        {filtered.length === 0 ? <window.Empty title="Nenhum resultado" desc="Tente outro termo ou filtro." /> : (
          <div style={{ overflowX: 'auto' }}>
            <table className="tbl">
              <thead><tr>
                <th>{terms.client}</th><th>Contato</th><th>{terms.pro}</th><th>Categoria</th><th>Visitas</th><th>Total gasto</th><th></th>
              </tr></thead>
              <tbody>
                {paginatedClients.map(c => (
                  <tr key={c.id} style={{ cursor: 'pointer' }} onClick={() => setSel(c)}>
                    <td>
                      <div className="row" style={{ gap: 11 }}>
                        <window.Avatar initials={ini(c.name)} color={colorFor(c.id)} size={38} />
                        <div>
                          <div style={{ fontWeight: 600 }}>{c.name}</div>
                          <div className="muted" style={{ fontSize: 12 }}>
                            {c.companyName ? c.companyName + (c.companyRole ? ' · ' + c.companyRole : '') : terms.client + ' desde ' + c.since}
                          </div>
                        </div>
                      </div>
                    </td>
                    <td><div style={{ fontSize: 12.5 }}>{c.phone}</div><div className="muted" style={{ fontSize: 12 }}>{c.email}</div></td>
                    <td>{(() => {
                      const p = proOf(c.proId);
                      return p ? (
                        <div className="row" style={{ gap: 7 }}>
                          <window.Avatar initials={p.initials} color={p.color} size={26} />
                          <span style={{ fontSize: 12.5 }}>{p.name.replace('Dra. ', '')}</span>
                        </div>
                      ) : <span className="muted" style={{ fontSize: 12 }}>—</span>;
                    })()}</td>
                    <td><window.Badge cls={tagCls[c.tag] || 'plain'} dot>{c.tag}</window.Badge></td>
                    <td className="mono">{c.visits}</td>
                    <td className="mono" style={{ fontWeight: 600 }}>{DB.money0(c.spent)}</td>
                    <td onClick={e => e.stopPropagation()}>
                      <div className="row" style={{ gap: 4, justifyContent: 'flex-end' }}>
                        <button className="iconbtn" style={{ width: 32, height: 32 }} title="Agendar" onClick={() => openNewAppt({ clientId: c.id })}><window.Icon name="calendar" size={16} /></button>
                        <button className="iconbtn" style={{ width: 32, height: 32 }} title="WhatsApp" onClick={() => window.waOpen(c.phone)}><window.Icon name="whatsapp" size={16} /></button>
                      </div>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
        {filtered.length > 0 && <div className="row between wrap" style={{ padding: '12px 14px', gap: 10, borderTop: '1px solid var(--border)' }}>
          <div className="muted" style={{ fontSize: 12.5 }}>
            Mostrando {pageStart + 1}–{Math.min(pageStart + pageSize, filtered.length)} de {filtered.length}
          </div>
          <div className="row wrap" style={{ gap: 6, justifyContent: 'flex-end' }}>
            <button className="chip" disabled={currentPage === 1} onClick={() => setPage(currentPage - 1)}
              style={{ opacity: currentPage === 1 ? .45 : 1, cursor: currentPage === 1 ? 'default' : 'pointer' }}>
              Anterior
            </button>
            {pageItems.map((item, index) => typeof item === 'number'
              ? <button key={item} className={'chip' + (currentPage === item ? ' active' : '')} onClick={() => setPage(item)} aria-label={`Página ${item}`}>{item}</button>
              : <span key={`${item}-${index}`} className="muted" style={{ minWidth: 18, textAlign: 'center' }}>…</span>
            )}
            <button className="chip" disabled={currentPage === totalPages} onClick={() => setPage(currentPage + 1)}
              style={{ opacity: currentPage === totalPages ? .45 : 1, cursor: currentPage === totalPages ? 'default' : 'pointer' }}>
              Próxima
            </button>
          </div>
        </div>}
      </div>}

      {mode === 'empresas' && <CompaniesPanel
        companies={filteredCompanies}
        employeesOf={employeesOf}
        setSelCompany={setSelCompany}
        setEditingCompany={setEditingCompany}
        setAddingForCompany={setAddingForCompany}
        removeCompany={removeCompany}
        openNewAppt={openNewAppt}
      />}

      {sel && <ClientDrawer ctx={ctx} c={clients.find(x => x.id === sel.id) || sel} appts={clientAppts(sel.id)} onClose={() => setSel(null)} color={colorFor(sel.id)} ini={ini}
        onEdit={() => setEditing(clients.find(x => x.id === sel.id) || sel)} onRemove={() => removeClient(sel)} />}
      {selCompany && <CompanyDrawer company={companies.find(x => x.id === selCompany.id) || selCompany} employees={employeesOf(selCompany.id)}
        onClose={() => setSelCompany(null)} onEdit={() => setEditingCompany(companies.find(x => x.id === selCompany.id) || selCompany)}
        onRemove={() => removeCompany(selCompany)} onAddEmployee={() => setAddingForCompany(companies.find(x => x.id === selCompany.id) || selCompany)}
        onEditEmployee={(c) => setEditing(c)} openNewAppt={openNewAppt} />}
      {(adding || editing || addingForCompany) && <ClientModal terms={terms} team={team} companies={companies} services={services} categories={categories} initial={editing} lockedCompany={addingForCompany}
        canManageBilling={!!(ctx.user && ctx.user.hasFinance && ctx.user.isPrimaryAdmin)}
        onAddCategory={addClientCategory} onDeleteCategory={deleteClientCategory}
        onClose={() => { setAdding(false); setEditing(null); setAddingForCompany(null); }} onSave={saveClient} />}
      {(addingCompany || editingCompany) && <CompanyModal initial={editingCompany} onClose={() => { setAddingCompany(false); setEditingCompany(null); }} onSave={saveCompany} />}
    </div>
  );
}

function CompaniesPanel({ companies, employeesOf, setSelCompany, setEditingCompany, setAddingForCompany, removeCompany, openNewAppt }) {
  return (
    <div className="card" style={{ overflow: 'hidden' }}>
      {companies.length === 0 ? <window.Empty icon="building" title="Nenhuma empresa cadastrada" desc="Cadastre a primeira empresa para vincular funcionários." /> : (
        <div style={{ overflowX: 'auto' }}>
          <table className="tbl">
            <thead><tr>
              <th>Empresa</th><th>Contato</th><th>Funcionários</th><th>CNPJ</th><th></th>
            </tr></thead>
            <tbody>
              {companies.map(c => {
                const employees = employeesOf(c.id);
                return (
                  <tr key={c.id} style={{ cursor: 'pointer' }} onClick={() => setSelCompany(c)}>
                    <td>
                      <div className="row" style={{ gap: 11 }}>
                        <div className="ic" style={{ width: 38, height: 38, borderRadius: 10, background: 'var(--primary-soft)', color: 'var(--primary)', display: 'grid', placeItems: 'center', flex: 'none' }}><window.Icon name="building" size={18} /></div>
                        <div><div style={{ fontWeight: 600 }}>{c.name}</div><div className="muted" style={{ fontSize: 12 }}>{[c.city, c.uf].filter(Boolean).join('/') || 'Empresa cadastrada'}</div></div>
                      </div>
                    </td>
                    <td><div style={{ fontSize: 12.5 }}>{c.phone || '—'}</div><div className="muted" style={{ fontSize: 12 }}>{c.email || '—'}</div></td>
                    <td><span className="badge plain"><window.Icon name="users" size={13} /> {employees.length}</span></td>
                    <td className="mono" style={{ fontSize: 12 }}>{c.cnpj || '—'}</td>
                    <td onClick={e => e.stopPropagation()}>
                      <div className="row" style={{ gap: 4, justifyContent: 'flex-end' }}>
                        <button className="iconbtn" style={{ width: 32, height: 32 }} title="Adicionar funcionário" onClick={() => setAddingForCompany(c)}><window.Icon name="plus" size={16} /></button>
                        {employees[0] && <button className="iconbtn" style={{ width: 32, height: 32 }} title="Agendar" onClick={() => openNewAppt({ clientId: employees[0].id })}><window.Icon name="calendar" size={16} /></button>}
                        <window.Menu trigger={<button className="iconbtn" style={{ width: 32, height: 32 }}><window.Icon name="dots" size={16} /></button>}>
                          <button onClick={() => setEditingCompany(c)}><window.Icon name="edit" size={15} /> Editar empresa</button>
                          <div className="sep" />
                          <button className="danger" onClick={() => removeCompany(c)}><window.Icon name="trash" size={15} /> Excluir</button>
                        </window.Menu>
                      </div>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
}

function CompanyDrawer({ company, employees, onClose, onEdit, onRemove, onAddEmployee, onEditEmployee, openNewAppt }) {
  return (
    <window.Drawer onClose={onClose}
      head={
        <div className="row between">
          <div className="row" style={{ gap: 12 }}>
            <div className="ic" style={{ width: 48, height: 48, borderRadius: 12, background: 'var(--primary-soft)', color: 'var(--primary)', display: 'grid', placeItems: 'center' }}><window.Icon name="building" size={22} /></div>
            <div><h3 style={{ fontSize: 17 }}>{company.name}</h3><div className="muted" style={{ fontSize: 12.5 }}>{employees.length} funcionários vinculados</div></div>
          </div>
          <div className="row" style={{ gap: 4 }}>
            <window.Menu trigger={<button className="iconbtn"><window.Icon name="dots" size={17} /></button>}>
              <button onClick={onEdit}><window.Icon name="edit" size={15} /> Editar empresa</button>
              <div className="sep" />
              <button className="danger" onClick={onRemove}><window.Icon name="trash" size={15} /> Excluir</button>
            </window.Menu>
            <button className="iconbtn" onClick={onClose}><window.Icon name="x" size={18} /></button>
          </div>
        </div>
      }
      footer={<window.Button variant="primary" icon="plus" block onClick={onAddEmployee}>Adicionar funcionário</window.Button>}>
      <SectionLabel>Dados da empresa</SectionLabel>
      {company.cnpj && <InfoRow icon="doc" label="CNPJ" value={company.cnpj} />}
      <InfoRow icon="phone" label="Telefone" value={company.phone || '—'} />
      <InfoRow icon="mail" label="E-mail" value={company.email || '—'} />
      {(company.address || company.city || company.cep) && <InfoRow icon="pin" label="Endereço"
        value={[[company.address, company.addressNum].filter(Boolean).join(', '), company.district, [company.city, company.uf].filter(Boolean).join('/'), company.cep].filter(Boolean).join(' · ') || '—'} />}
      {company.notes && <><SectionLabel>Observações</SectionLabel><div className="card card-pad muted" style={{ padding: 12, fontSize: 12.5 }}>{company.notes}</div></>}

      <SectionLabel style={{ marginTop: 18 }}>Funcionários</SectionLabel>
      <div className="stack" style={{ gap: 8 }}>
        {employees.length === 0 && <div className="muted" style={{ fontSize: 12.5 }}>Nenhum funcionário cadastrado nesta empresa.</div>}
        {employees.map(e => (
          <div className="card" key={e.id} style={{ padding: '10px 12px', display: 'flex', alignItems: 'center', gap: 10 }}>
            <window.Avatar initials={e.name.split(' ').map(x => x[0]).slice(0, 2).join('').toUpperCase()} color="blue" size={32} />
            <div style={{ flex: 1 }}>
              <div style={{ fontSize: 12.5, fontWeight: 600 }}>{e.name}</div>
              <div className="muted" style={{ fontSize: 11.5 }}>{e.companyRole || 'Sem cargo'} · {e.phone || e.email || 'sem contato'}</div>
            </div>
            <button className="iconbtn" style={{ width: 30, height: 30 }} title="Agendar" onClick={() => { onClose(); openNewAppt({ clientId: e.id }); }}><window.Icon name="calendar" size={15} /></button>
            <button className="iconbtn" style={{ width: 30, height: 30 }} title="Editar" onClick={() => onEditEmployee(e)}><window.Icon name="edit" size={15} /></button>
          </div>
        ))}
      </div>
    </window.Drawer>
  );
}

function CompanyModal({ initial, onClose, onSave }) {
  const DB = window.DB;
  const [f, setF] = React.useState(initial
    ? { name: initial.name, cnpj: initial.cnpj, phone: initial.phone, email: initial.email, cep: initial.cep, address: initial.address, addressNum: initial.addressNum, district: initial.district, city: initial.city, uf: initial.uf, notes: initial.notes }
    : { name: '', cnpj: '', phone: '', email: '', cep: '', address: '', addressNum: '', district: '', city: '', uf: '', notes: '' });
  const [saving, setSaving] = React.useState(false);
  const [cep, setCep] = React.useState({ loading: false, found: null });
  const set = (k) => (e) => setF((p) => ({ ...p, [k]: e.target.value }));
  const onCep = async (e) => {
    const masked = e.target.value;
    setF((p) => ({ ...p, cep: masked }));
    setCep({ loading: false, found: null });
    if (DB.mask.digits(masked).length === 8) {
      setCep({ loading: true, found: null });
      const addr = await window.viaCEP(masked);
      if (addr) {
        setF((p) => ({ ...p, address: addr.address, district: addr.district, city: addr.city, uf: addr.uf }));
        setCep({ loading: false, found: true });
      } else {
        setCep({ loading: false, found: false });
      }
    }
  };
  const save = async () => { if (!f.name || saving) return; setSaving(true); await onSave(f); setSaving(false); };
  return (
    <window.Modal wide title={initial ? 'Editar empresa' : 'Nova empresa'} sub="Dados da empresa e contatos principais" onClose={onClose}
      footer={<><div style={{ flex: 1 }} /><window.Button variant="ghost" onClick={onClose}>Cancelar</window.Button>
        <window.Button variant="primary" icon="check" disabled={saving} onClick={save}>{saving ? 'Salvando…' : 'Salvar'}</window.Button></>}>
      <div className="form-grid">
        <window.Field label="Nome da empresa" full><window.Input placeholder="Ex.: Contalex" value={f.name} onChange={set('name')} autoFocus /></window.Field>
        <window.Field label="CNPJ" optional><window.MaskInput mask="cnpj" placeholder="00.000.000/0000-00" value={f.cnpj} onChange={set('cnpj')} /></window.Field>
        <window.Field label="Telefone" optional><window.MaskInput mask="phone" placeholder="(11) 3000-0000" value={f.phone} onChange={set('phone')} /></window.Field>
        <window.Field label="E-mail" optional><window.Input placeholder="contato@empresa.com" value={f.email} onChange={set('email')} /></window.Field>
        <window.SectionLabel style={{ gridColumn: '1 / -1', margin: '6px 0 0' }}>Endereço</window.SectionLabel>
        <window.Field label="CEP" optional>
          <window.MaskInput mask="cep" placeholder="00000-000" value={f.cep} onChange={onCep} />
          {cep.loading && <div className="field-hint" style={{ color: 'var(--text-3)' }}><window.Icon name="search" size={12} /> Buscando endereço…</div>}
          {cep.found === true && <div className="field-hint ok"><window.Icon name="check" size={12} /> Endereço preenchido</div>}
          {cep.found === false && <div className="field-hint err"><window.Icon name="info" size={12} /> CEP não encontrado</div>}
        </window.Field>
        <window.Field label="Logradouro" optional><window.Input placeholder="Rua, avenida…" value={f.address} onChange={set('address')} /></window.Field>
        <window.Field label="Número" optional><window.Input placeholder="Nº" value={f.addressNum} onChange={set('addressNum')} /></window.Field>
        <window.Field label="Bairro" optional><window.Input placeholder="Bairro" value={f.district} onChange={set('district')} /></window.Field>
        <window.Field label="Cidade" optional><window.Input placeholder="Cidade" value={f.city} onChange={set('city')} /></window.Field>
        <window.Field label="UF" optional><window.Input placeholder="UF" maxLength={2} value={f.uf} onChange={(e) => setF((p) => ({ ...p, uf: e.target.value.toUpperCase().slice(0, 2) }))} /></window.Field>
        <window.Field label="Observações" optional full><window.Textarea placeholder="Dados importantes da empresa…" value={f.notes} onChange={set('notes')} /></window.Field>
      </div>
    </window.Modal>
  );
}

/* ---------------- FORNECEDORES ---------------- */
function SuppliersScreen(ctx) {
  const { suppliers = [], transactions = [], toast } = ctx;
  const DB = window.DB;
  const [q, setQ] = React.useState('');
  const [sel, setSel] = React.useState(null);
  const [adding, setAdding] = React.useState(false);
  const [editing, setEditing] = React.useState(null);

  const qText = String(q || '').toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '');
  const qDigits = DB.mask.digits(q);
  const filtered = suppliers.filter((s) => {
    const hay = [
      s.name,
      s.email,
      s.phone,
      s.document,
      s.notes,
    ].join(' ').toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '');
    const digitsHay = DB.mask.digits([s.phone, s.document].join(' '));
    return hay.includes(qText) || (qDigits && digitsHay.includes(qDigits));
  });

  const statsOf = (supplierId) => {
    const linked = transactions.filter((t) => Number(t.supplierId || 0) === Number(supplierId) && t.value < 0);
    const paid = linked.filter((t) => t.status === 'pago').reduce((sum, t) => sum + Math.abs(Number(t.value) || 0), 0);
    const pending = linked.filter((t) => t.status === 'pendente').reduce((sum, t) => sum + Math.abs(Number(t.value) || 0), 0);
    return { count: linked.length, paid, pending };
  };

  const save = async (data) => {
    try {
      if (editing) {
        await ctx.updateSupplier(editing.id, data);
        toast('Fornecedor atualizado!');
      } else {
        await ctx.addSupplier(data);
        toast('Fornecedor cadastrado!');
      }
      setAdding(false);
      setEditing(null);
    } catch (e) {
      toast(e.message, 'x');
    }
  };

  const remove = async (supplier) => {
    if (!window.confirm(`Excluir ${supplier.name}?`)) return;
    try {
      await ctx.deleteSupplier(supplier.id);
      toast('Fornecedor removido!');
      setSel(null);
    } catch (e) {
      toast(e.message, 'x');
    }
  };

  return (
    <div className="content-inner fadein">
      <Header title="Fornecedores" sub={`${suppliers.length} fornecedores cadastrados`} action={
        <window.Button variant="primary" icon="plus" onClick={() => setAdding(true)}>Novo fornecedor</window.Button>
      } />

      <div className="card" style={{ overflow: 'hidden' }}>
        <div className="row between wrap" style={{ padding: 14, gap: 12, borderBottom: '1px solid var(--border)' }}>
          <div className="row" style={{ gap: 8 }}>
            <h3 style={{ fontSize: 14.5 }}>Lista de fornecedores</h3>
            <span className="badge plain">{filtered.length}</span>
          </div>
          <div className="input-icon" style={{ flex: '1 0 320px', minWidth: 260, maxWidth: 460 }}>
            <window.Icon name="search" size={16} />
            <input className="input" placeholder="Buscar por nome, telefone, e-mail, documento..." value={q} onChange={(e) => setQ(e.target.value)} />
          </div>
        </div>

        {filtered.length === 0 ? <window.Empty icon="building" title="Nenhum fornecedor encontrado" desc="Cadastre o primeiro fornecedor para vincular despesas." /> : (
          <div style={{ overflowX: 'auto' }}>
            <table className="tbl">
              <thead><tr>
                <th>Fornecedor</th><th>Contato</th><th>Documento</th><th>Despesas</th><th style={{ textAlign: 'right' }}>Pago</th><th></th>
              </tr></thead>
              <tbody>
                {filtered.map((s) => {
                  const stats = statsOf(s.id);
                  return (
                    <tr key={s.id} style={{ cursor: 'pointer' }} onClick={() => setSel(s)}>
                      <td>
                        <div className="row" style={{ gap: 11 }}>
                          <div className="ic" style={{ width: 38, height: 38, borderRadius: 10, background: 'var(--primary-soft)', color: 'var(--primary)', display: 'grid', placeItems: 'center', flex: 'none' }}>
                            <window.Icon name="building" size={18} />
                          </div>
                          <div style={{ minWidth: 0 }}>
                            <div style={{ fontWeight: 600 }}>{s.name}</div>
                            <div className="muted" style={{ fontSize: 12 }}>{s.notes ? s.notes : 'Fornecedor cadastrado'}</div>
                          </div>
                        </div>
                      </td>
                      <td>
                        <div style={{ fontSize: 12.5 }}>{s.phone || '-'}</div>
                        <div className="muted" style={{ fontSize: 12 }}>{s.email || '-'}</div>
                      </td>
                      <td className="mono" style={{ fontSize: 12.5 }}>{s.document || '-'}</td>
                      <td><span className="badge plain"><window.Icon name="wallet" size={12} /> {stats.count}</span></td>
                      <td className="mono" style={{ textAlign: 'right', fontWeight: 600 }}>{DB.money(stats.paid)}</td>
                      <td onClick={(e) => e.stopPropagation()}>
                        <div className="row" style={{ gap: 4, justifyContent: 'flex-end' }}>
                          <button className="iconbtn" style={{ width: 32, height: 32 }} title="Editar" onClick={() => setEditing(s)}><window.Icon name="edit" size={16} /></button>
                          <button className="iconbtn" style={{ width: 32, height: 32 }} title="Excluir" onClick={() => remove(s)}><window.Icon name="trash" size={16} /></button>
                        </div>
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
        )}
      </div>

      {sel && <SupplierDrawer supplier={suppliers.find((x) => x.id === sel.id) || sel} stats={statsOf(sel.id)} onClose={() => setSel(null)} onEdit={() => setEditing(suppliers.find((x) => x.id === sel.id) || sel)} onRemove={() => remove(sel)} />}
      {(adding || editing) && <SupplierModal initial={editing} onClose={() => { setAdding(false); setEditing(null); }} onSave={save} />}
    </div>
  );
}

function SupplierDrawer({ supplier, stats, onClose, onEdit, onRemove }) {
  return (
    <window.Drawer
      onClose={onClose}
      head={
        <div className="row between">
          <div className="row" style={{ gap: 12 }}>
            <div className="ic" style={{ width: 48, height: 48, borderRadius: 12, background: 'var(--primary-soft)', color: 'var(--primary)', display: 'grid', placeItems: 'center' }}><window.Icon name="building" size={22} /></div>
            <div><h3 style={{ fontSize: 17 }}>{supplier.name}</h3><div className="muted" style={{ fontSize: 12.5 }}>{stats.count} despesas vinculadas</div></div>
          </div>
          <div className="row" style={{ gap: 4 }}>
            <window.Menu trigger={<button className="iconbtn"><window.Icon name="dots" size={17} /></button>}>
              <button onClick={onEdit}><window.Icon name="edit" size={15} /> Editar fornecedor</button>
              <div className="sep" />
              <button className="danger" onClick={onRemove}><window.Icon name="trash" size={15} /> Excluir</button>
            </window.Menu>
            <button className="iconbtn" onClick={onClose}><window.Icon name="x" size={18} /></button>
          </div>
        </div>
      }
      footer={<window.Button variant="primary" icon="edit" block onClick={onEdit}>Editar fornecedor</window.Button>}>
      <div className="grid-3" style={{ gridTemplateColumns: '1fr 1fr 1fr', marginBottom: 18 }}>
        {[
          ['Despesas', stats.count],
          ['Pago', window.DB.money(stats.paid)],
          ['Pendente', window.DB.money(stats.pending)],
        ].map(([label, value]) => (
          <div className="card card-pad" key={label} style={{ padding: 12, textAlign: 'center' }}>
            <div style={{ fontFamily: 'var(--font-display)', fontSize: 17, fontWeight: 600 }}>{value}</div>
            <div className="muted" style={{ fontSize: 11 }}>{label}</div>
          </div>
        ))}
      </div>

      <SectionLabel>Contato</SectionLabel>
      <InfoRow icon="phone" label="Telefone" value={supplier.phone || '-'} />
      <InfoRow icon="mail" label="E-mail" value={supplier.email || '-'} />
      <InfoRow icon="doc" label="Documento" value={supplier.document || '-'} />
      {supplier.notes && <><SectionLabel>Observacoes</SectionLabel><div className="card card-pad muted" style={{ padding: 12, fontSize: 12.5 }}>{supplier.notes}</div></>}
    </window.Drawer>
  );
}

function SupplierModal({ initial, onClose, onSave }) {
  const [f, setF] = React.useState(initial
    ? { name: initial.name, phone: initial.phone, email: initial.email, document: initial.document, notes: initial.notes }
    : { name: '', phone: '', email: '', document: '', notes: '' });
  const [saving, setSaving] = React.useState(false);
  const set = (k) => (e) => setF((prev) => ({ ...prev, [k]: e.target.value }));
  const save = async () => {
    if (!f.name.trim() || saving) return;
    setSaving(true);
    try { await onSave(f); } finally { setSaving(false); }
  };
  return (
    <window.Modal title={initial ? 'Editar fornecedor' : 'Novo fornecedor'} sub="Dados de contato do fornecedor" onClose={onClose}
      footer={<><div style={{ flex: 1 }} /><window.Button variant="ghost" onClick={onClose}>Cancelar</window.Button>
        <window.Button variant="primary" icon="check" disabled={saving || !f.name.trim()} onClick={save}>{saving ? 'Salvando...' : 'Salvar'}</window.Button></>}>
      <div className="form-grid">
        <window.Field label="Nome" full><window.Input placeholder="Nome do fornecedor" value={f.name} onChange={set('name')} autoFocus /></window.Field>
        <window.Field label="Telefone" optional><window.MaskInput mask="phone" placeholder="(11) 90000-0000" value={f.phone} onChange={set('phone')} /></window.Field>
        <window.Field label="E-mail" optional><window.Input placeholder="contato@fornecedor.com" value={f.email} onChange={set('email')} /></window.Field>
        <window.Field label="CPF/CNPJ" optional><window.Input placeholder="Documento" value={f.document} onChange={set('document')} /></window.Field>
        <window.Field label="Observacoes" optional full><window.Textarea placeholder="Dados importantes sobre este fornecedor..." value={f.notes} onChange={set('notes')} /></window.Field>
      </div>
    </window.Modal>
  );
}

function ClientDrawer({ ctx, c, appts, onClose, color, ini, onEdit, onRemove }) {
  const DB = window.DB; const { terms, services, team, statusMap, openNewAppt } = ctx;
  const [cancelFutureOpen, setCancelFutureOpen] = React.useState(false);
  const [cancellingFuture, setCancellingFuture] = React.useState(false);
  const [emails, setEmails] = React.useState(null);
  const [viewEmail, setViewEmail] = React.useState(null);
  const [privacyBusy, setPrivacyBusy] = React.useState(false);

  React.useEffect(() => {
    window.API.clients.emails(c.id).then(res => setEmails(res.emails || [])).catch(() => setEmails([]));
  }, [c.id]);
  const svc = (id) => services.find(s => s.id === id);
  const pro = (id) => team.find(p => p.id === id);
  const extras = terms.extra;
  const hasCompany = c.companyName || c.companyRole || c.companyCnpj || c.companyPhone || c.companyEmail;
  const todayISO = DB.iso(DB.today);
  const historyAppts = appts
    .filter((a) => a.date <= todayISO)
    .sort((a, b) => (String(b.date) + String(b.start)).localeCompare(String(a.date) + String(a.start)));
  const recentHistoryAppts = historyAppts.slice(0, 5);
  const futureAppts = appts.filter((a) => a.date >= todayISO && ['pendente', 'confirmado'].includes(a.status));
  const futureSeries = [...new Set(futureAppts.map((a) => a.seriesId).filter(Boolean))].map((seriesId) => {
    const items = futureAppts.filter((a) => a.seriesId === seriesId).sort((a, b) => a.date.localeCompare(b.date));
    const first = items[0];
    return { id: seriesId, count: items.length, first, service: svc(first.serviceId), professional: pro(first.proId) };
  });
  const currentPlanUsage = (() => {
    const plan = svc(c.planId);
    const limit = Math.max(0, Number(c.planFrequency || (plan && plan.planFrequency)) || 0);
    if (!plan || limit <= 0) return null;
      const target = new Date(DB.iso(DB.today) + 'T12:00');
    const period = c.planPeriod || plan.planPeriod || 'semana';
    let start;
    let end;
    if (period === 'mes') {
      const dueDay = Math.max(1, Math.min(31, Number(c.planDueDay) || 1));
      const anchor = (year, month) => new Date(year, month, Math.min(dueDay, new Date(year, month + 1, 0).getDate()), 12);
      start = anchor(target.getFullYear(), target.getMonth());
      if (target < start) start = anchor(target.getFullYear(), target.getMonth() - 1);
      const next = anchor(start.getFullYear(), start.getMonth() + 1);
      end = new Date(next); end.setDate(end.getDate() - 1);
    } else {
      start = new Date(target); start.setDate(target.getDate() - ((target.getDay() + 6) % 7));
      end = new Date(start); end.setDate(start.getDate() + 6);
    }
    const startISO = DB.iso(start);
    const endISO = DB.iso(end);
    const used = appts.filter((a) => {
      if (a.status === 'cancelado' || a.quotaAction === 'extra' || a.quotaAction === 'replacement' || a.date < startISO || a.date > endISO) return false;
      const service = svc(a.serviceId);
      return service && (Number(service.planFrequency) > 0 || Number(service.id) === Number(c.planId));
    }).length;
    return { used, limit, startISO, endISO };
  })();
  const cancelFuture = async (seriesId = 0) => {
    const target = seriesId ? 'esta série' : `todos os ${terms.appt.toLowerCase()}s futuros`;
    if (!window.confirm(`Cancelar ${target} de ${c.name}? O histórico anterior será preservado.`)) return;
    setCancellingFuture(true);
    try {
      const res = await ctx.cancelClientFuture(c.id, seriesId);
      ctx.toast(`${res.cancelled} ${res.cancelled === 1 ? terms.appt.toLowerCase() : terms.appt.toLowerCase() + 's'} cancelado${res.cancelled === 1 ? '' : 's'}.`);
      setCancelFutureOpen(false);
    } catch (e) {
      ctx.toast(e.message, 'x');
    }
    setCancellingFuture(false);
  };
  const exportPersonalData = async () => {
    try {
      const res = await window.API.clients.export(c.id);
      const stamp = new Date().toISOString().slice(0, 10);
      window.downloadJSON(`titular-${c.id}-${stamp}.json`, res.export || {});
      ctx.toast('Pacote de dados exportado.');
    } catch (e) {
      ctx.toast(e.message || 'Não foi possível exportar os dados.', 'x');
    }
  };
  const anonymizePersonalData = async () => {
    if (privacyBusy) return;
    if (!window.confirm(`Anonimizar os dados pessoais de ${c.name}? O histórico operacional será mantido, mas contato, documento e anotações pessoais serão removidos.`)) return;
    setPrivacyBusy(true);
    try {
      await ctx.anonymizeClient(c.id);
      ctx.toast('Dados pessoais anonimizados.');
      onClose();
    } catch (e) {
      ctx.toast(e.message || 'Não foi possível anonimizar este cadastro.', 'x');
    }
    setPrivacyBusy(false);
  };
  return (
    <>
    <window.Drawer onClose={() => cancelFutureOpen ? setCancelFutureOpen(false) : onClose()}
      head={
        <div className="row between">
          <div className="row" style={{ gap: 12 }}>
            <window.Avatar initials={ini(c.name)} color={color} size={48} />
            <div><h3 style={{ fontSize: 17 }}>{c.name}</h3><div className="muted" style={{ fontSize: 12.5 }}>{terms.client} · desde {c.since}</div></div>
          </div>
          <div className="row" style={{ gap: 4 }}>
            <window.Menu trigger={<button className="iconbtn"><window.Icon name="dots" size={17} /></button>}>
              <button onClick={onEdit}><window.Icon name="edit" size={15} /> Editar dados</button>
              <button onClick={exportPersonalData}><window.Icon name="download" size={15} /> Exportar dados do titular</button>
              <button onClick={anonymizePersonalData}><window.Icon name="userX" size={15} /> Anonimizar dados pessoais</button>
              {ctx.user && ctx.user.role !== 'pro' && futureAppts.length > 0 && <button onClick={() => setCancelFutureOpen(true)}><window.Icon name="calendar" size={15} /> Cancelar {terms.appt.toLowerCase()}s futuros</button>}
              <div className="sep" />
              <button className="danger" onClick={onRemove}><window.Icon name="trash" size={15} /> Excluir</button>
            </window.Menu>
            <button className="iconbtn" onClick={onClose}><window.Icon name="x" size={18} /></button>
          </div>
        </div>
      }
      footer={<>
        <window.Button variant="primary" icon="calendar" block onClick={() => { onClose(); openNewAppt({ clientId: c.id }); }}>{['Aula', 'Consulta', 'Sessão'].includes(terms.appt) ? 'Nova' : 'Novo'} {terms.appt.toLowerCase()}</window.Button>
        <window.Button variant="outline" icon="whatsapp" onClick={() => window.waOpen(c.phone)}>WhatsApp</window.Button>
      </>}>
      <div className="grid-3" style={{ gridTemplateColumns: '1fr 1fr 1fr', marginBottom: 18 }}>
        {[['Visitas', c.visits], ['Total gasto', DB.money0(c.spent)], ['Ticket médio', DB.money0(Math.round(c.spent / Math.max(1, c.visits)))]].map(([l, v]) => (
          <div className="card card-pad" key={l} style={{ padding: 12, textAlign: 'center' }}>
            <div style={{ fontFamily: 'var(--font-display)', fontSize: 17, fontWeight: 600 }}>{v}</div>
            <div className="muted" style={{ fontSize: 11 }}>{l}</div>
          </div>
        ))}
      </div>

      <SectionLabel>Contato</SectionLabel>
      <InfoRow icon="phone" label="Telefone" value={c.phone || '—'} />
      <InfoRow icon="mail" label="E-mail" value={c.email || '—'} />
      {c.cpf && <InfoRow icon="doc" label="CPF" value={c.cpf} />}
      {(c.address || c.city || c.cep) && <InfoRow icon="pin" label="Endereço"
        value={[[c.address, c.addressNum].filter(Boolean).join(', '), c.district, [c.city, c.uf].filter(Boolean).join('/'), c.cep].filter(Boolean).join(' · ') || '—'} />}
      <InfoRow icon="user" label={terms.pro + ' vinculado'} value={(pro(c.proId) || {}).name || 'Sem vínculo'} />
      {terms.id === 'pilates' && <>
        <SectionLabel>Plano e Aulas</SectionLabel>
        <InfoRow icon="check" label="Plano vinculado" value={(svc(c.planId) || {}).name || 'Nenhum plano (avulso)'} />
        {c.planId > 0 && <>
          {currentPlanUsage && <InfoRow icon="check" label="Uso no período atual" value={`${currentPlanUsage.used}/${currentPlanUsage.limit} aulas · ${new Date(currentPlanUsage.startISO + 'T12:00').toLocaleDateString('pt-BR')} a ${new Date(currentPlanUsage.endISO + 'T12:00').toLocaleDateString('pt-BR')}`} />}
          {c.planFrequency > 0 && <InfoRow icon="calendar" label="Frequência permitida" value={`${c.planFrequency}x`} />}
          {c.planPeriod && <InfoRow icon="history" label="Período do limite" value={c.planPeriod === 'mes' ? 'Por ciclo mensal' : 'Por semana'} />}
          {c.planDueDay > 0 && <InfoRow icon="calendar" label="Vencimento" value={`Dia ${c.planDueDay}`} />}
          {c.planPrice > 0 && <InfoRow icon="card" label="Valor do plano" value={DB.money(c.planPrice)} />}
          {c.extraClassPrice > 0 && <InfoRow icon="card" label="Valor da aula extra" value={DB.money(c.extraClassPrice)} />}
          {c.monthlyBillingEnabled && <InfoRow icon="refresh" label="Cobrança mensal" value="Automática · lançada como a receber" />}
        </>}
        <InfoRow icon="refresh" label="Créditos de reposição" value={`${Number(c.replacementCredits) || 0} disponível${Number(c.replacementCredits) === 1 ? '' : 'is'}`} />
      </>}
      {(terms.id !== 'pilates' || !c.planId) && c.monthlyBillingEnabled && <>
        <SectionLabel>Mensalidade</SectionLabel>
        <InfoRow icon="refresh" label="Cobrança" value="Automática · lançada como a receber" />
        <InfoRow icon="calendar" label="Vencimento" value={`Dia ${c.planDueDay}`} />
        <InfoRow icon="card" label="Valor mensal" value={DB.money(c.planPrice || 0)} />
      </>}
      {extras.includes('convenio') && <InfoRow icon="card" label="Convênio" value={c.convenio || '—'} />}
      {extras.includes('prontuario') && <InfoRow icon="doc" label="Prontuário" value={c.prontuario ? '#' + c.prontuario : '—'} />}
      <SectionLabel style={{ marginTop: 18 }}>LGPD</SectionLabel>
      <InfoRow icon="check" label="Consentimento registrado em" value={c.privacyConsentAt ? new Date(String(c.privacyConsentAt).replace(' ', 'T')).toLocaleDateString('pt-BR') : 'Não informado'} />
      <InfoRow icon="info" label="Origem / base do registro" value={c.privacyConsentSource || 'Não informado'} />
      {c.anonymizedAt && <InfoRow icon="userX" label="Anonimizado em" value={new Date(String(c.anonymizedAt).replace(' ', 'T')).toLocaleString('pt-BR')} />}
      {c.privacyNotes && <div className="card card-pad muted" style={{ padding: 12, fontSize: 12.5 }}>{c.privacyNotes}</div>}
      {hasCompany && <>
        <SectionLabel>Empresa</SectionLabel>
        <InfoRow icon="building" label="Empresa" value={c.companyName || '—'} />
        {c.companyRole && <InfoRow icon="briefcase" label="Cargo" value={c.companyRole} />}
        {c.companyCnpj && <InfoRow icon="doc" label="CNPJ" value={c.companyCnpj} />}
        {c.companyPhone && <InfoRow icon="phone" label="Telefone da empresa" value={c.companyPhone} />}
        {c.companyEmail && <InfoRow icon="mail" label="E-mail da empresa" value={c.companyEmail} />}
      </>}
      {c.notes && <><SectionLabel>Observações</SectionLabel><div className="card card-pad muted" style={{ padding: 12, fontSize: 12.5 }}>{c.notes}</div></>}

      {emails && emails.length > 0 && (
        <>
          <SectionLabel style={{ marginTop: 18 }}>E-mails Enviados ({emails.length})</SectionLabel>
          <div className="stack" style={{ gap: 8 }}>
            {emails.map(em => (
              <div className="card" key={em.id} style={{ padding: '10px 12px', display: 'flex', alignItems: 'center', gap: 10, cursor: 'pointer' }} onClick={() => setViewEmail(em)}>
                <div className="ic" style={{ width: 36, height: 36, borderRadius: 10, background: 'var(--surface-2)', display: 'grid', placeItems: 'center', color: 'var(--text-2)', flex: 'none' }}><window.Icon name="mail" size={16} /></div>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: 12.5, fontWeight: 600, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{em.subject}</div>
                  <div className="muted" style={{ fontSize: 11.5 }}>{new Date(em.sent_at.replace(' ', 'T')).toLocaleString('pt-BR', { day: '2-digit', month: 'short', hour: '2-digit', minute: '2-digit' })} · Para: {em.to_email}</div>
                </div>
                <window.Icon name="chevRight" size={16} style={{ color: 'var(--text-3)' }} />
              </div>
            ))}
          </div>
        </>
      )}

      <SectionLabel style={{ marginTop: 18 }}>Histórico ({historyAppts.length})</SectionLabel>
      <div className="stack" style={{ gap: 8 }}>
        {historyAppts.length === 0 && <div className="muted" style={{ fontSize: 12.5 }}>Sem {terms.appt.toLowerCase()}s registrados.</div>}
        {recentHistoryAppts.map(a => {
          const s = a.manualServiceName ? { name: a.manualServiceName, price: a.manualServicePrice || 0, color: 'violet' } : svc(a.serviceId), p = pro(a.proId), st = statusMap[a.status] || { label: a.status || 'Sem status', cls: 'plain' };
          if (!s || !p) return null;
          return (
            <div className="card" key={a.id} style={{ padding: '10px 12px', display: 'flex', alignItems: 'center', gap: 10, borderLeft: `3px solid var(--ev-${s.color})` }}>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 12.5, fontWeight: 600 }}>{s.name}</div>
                <div className="muted" style={{ fontSize: 11.5 }}>{new Date(a.date + 'T00:00').toLocaleDateString('pt-BR', { day: '2-digit', month: 'short' })} · {a.start}–{window.apptEnd(a)} · {p.name.replace('Dra. ', '')}</div>
                <div className="row" style={{ gap: 5, marginTop: 5, flexWrap: 'wrap' }}>
                  {a.quotaAction === 'extra' && <window.Badge cls="amber">Aula extra {Number(a.extraClassPrice) > 0 ? `· ${DB.money(a.extraClassPrice)}` : ''}</window.Badge>}
                  {a.quotaAction === 'replacement' && <window.Badge cls="blue">Crédito de reposição usado</window.Badge>}
                  {a.replacementCreditGranted && <window.Badge cls="green">Crédito gerado no cancelamento</window.Badge>}
                </div>
              </div>
              <window.Badge cls={st.cls}>{st.label}</window.Badge>
            </div>
          );
        })}
        {historyAppts.length > 5 && <window.Button variant="outline" icon="history" block onClick={() => { onClose(); ctx.openClientHistory(c.id); }}>
          Ver histórico completo ({historyAppts.length})
        </window.Button>}
      </div>
    </window.Drawer>
    {cancelFutureOpen && <window.Modal title={`Cancelar ${terms.appt.toLowerCase()}s futuros`} sub={`Escolha o que encerrar para ${c.name}`} onClose={() => setCancelFutureOpen(false)}
      footer={<><div style={{ flex: 1 }} /><window.Button variant="ghost" onClick={() => setCancelFutureOpen(false)}>Voltar</window.Button></>}>
      <div className="stack" style={{ gap: 10 }}>
        <button type="button" className="card" disabled={cancellingFuture} onClick={() => cancelFuture(0)}
          style={{ padding: 14, textAlign: 'left', display: 'flex', alignItems: 'center', gap: 12, cursor: 'pointer', background: 'var(--danger-soft)', borderColor: 'color-mix(in srgb, var(--danger) 30%, var(--border))' }}>
          <div className="ic" style={{ width: 38, height: 38, borderRadius: 10, display: 'grid', placeItems: 'center', color: 'var(--danger)' }}><window.Icon name="x" size={18} /></div>
          <div style={{ flex: 1 }}><div style={{ fontWeight: 600 }}>Cancelar todos os {terms.appt.toLowerCase()}s futuros</div><div className="muted" style={{ fontSize: 12 }}>{futureAppts.length} {terms.appt.toLowerCase()}{futureAppts.length === 1 ? '' : 's'} · todas as séries e ocorrências avulsas</div></div>
        </button>
        {futureSeries.length > 0 && <window.SectionLabel style={{ margin: '8px 0 0' }}>Ou selecione uma série</window.SectionLabel>}
        {futureSeries.map((series) => (
          <button type="button" className="card" key={series.id} disabled={cancellingFuture} onClick={() => cancelFuture(series.id)}
            style={{ padding: 14, textAlign: 'left', display: 'flex', alignItems: 'center', gap: 12, cursor: 'pointer', background: 'var(--surface)' }}>
            <div className="ic" style={{ width: 38, height: 38, borderRadius: 10, background: 'var(--surface-2)', display: 'grid', placeItems: 'center', color: 'var(--text-2)' }}><window.Icon name="refresh" size={17} /></div>
            <div style={{ flex: 1 }}>
              <div style={{ fontWeight: 600 }}>{series.service ? series.service.name : 'Série recorrente'}</div>
              <div className="muted" style={{ fontSize: 12 }}>{series.professional ? series.professional.name + ' · ' : ''}{series.count} futura{series.count === 1 ? '' : 's'} · próxima em {new Date(series.first.date + 'T12:00').toLocaleDateString('pt-BR')}</div>
            </div>
            <window.Icon name="chevRight" size={16} style={{ color: 'var(--text-3)' }} />
          </button>
        ))}
      </div>
    </window.Modal>}
    {viewEmail && (
      <window.Modal title={viewEmail.subject} sub={`Enviado em ${new Date(viewEmail.sent_at.replace(' ', 'T')).toLocaleString('pt-BR')} para ${viewEmail.to_email}`} onClose={() => setViewEmail(null)} wide
        footer={<><div style={{ flex: 1 }} /><window.Button variant="primary" onClick={() => setViewEmail(null)}>Fechar</window.Button></>}>
        <div style={{ padding: 16, background: '#fff', color: '#000', borderRadius: 8, border: '1px solid var(--border)' }}>
          <iframe 
            srcDoc={viewEmail.body_html} 
            style={{ width: '100%', height: '500px', border: 'none' }} 
            title="E-mail Content" 
          />
        </div>
      </window.Modal>
    )}
    </>
  );
}

function ClientModal({ terms, team, companies = [], services = [], categories = [], lockedCompany, initial, canManageBilling = false, onAddCategory, onDeleteCategory, onClose, onSave }) {
  const DB = window.DB;
  const [f, setF] = React.useState({
    name: initial ? initial.name : '', phone: initial ? initial.phone : '', email: initial ? initial.email : '',
    tag: initial ? initial.tag : (categories[0] || 'Novo'), convenio: initial ? initial.convenio : '', prontuario: initial ? initial.prontuario : '', notes: initial ? initial.notes : '',
    cpf: initial ? (initial.cpf || '') : '', cep: initial ? (initial.cep || '') : '',
    companyId: lockedCompany ? lockedCompany.id : (initial && initial.companyId ? initial.companyId : 0),
    companyName: initial ? (initial.companyName || '') : '', companyRole: initial ? (initial.companyRole || '') : '',
    companyCnpj: initial ? (initial.companyCnpj || '') : '', companyPhone: initial ? (initial.companyPhone || '') : '',
    companyEmail: initial ? (initial.companyEmail || '') : '',
    address: initial ? (initial.address || '') : '', addressNum: initial ? (initial.addressNum || '') : '',
    district: initial ? (initial.district || '') : '', city: initial ? (initial.city || '') : '', uf: initial ? (initial.uf || '') : '',
    proId: initial && initial.proId ? initial.proId : 0,
    planId: initial && initial.planId ? initial.planId : 0,
    planFrequency: initial && initial.planFrequency ? initial.planFrequency : '',
    planPeriod: initial && initial.planPeriod ? initial.planPeriod : 'semana',
    planDueDay: initial && initial.planDueDay ? initial.planDueDay : '',
    planPrice: initial && typeof initial.planPrice === 'number' ? initial.planPrice : 0,
    extraClassPrice: initial && typeof initial.extraClassPrice === 'number' ? initial.extraClassPrice : 0,
    monthlyBillingEnabled: initial ? !!initial.monthlyBillingEnabled : false,
    privacyConsentAt: initial && initial.privacyConsentAt ? String(initial.privacyConsentAt).slice(0, 10) : '',
    privacyConsentSource: initial ? (initial.privacyConsentSource || '') : '',
    privacyNotes: initial ? (initial.privacyNotes || '') : '',
  });
  const [saving, setSaving] = React.useState(false);
  const [cep, setCep] = React.useState({ loading: false, found: null }); // found: true/false/null
  const [categoryOpen, setCategoryOpen] = React.useState(false);
  const [categoryName, setCategoryName] = React.useState('');
  const [categoryBusy, setCategoryBusy] = React.useState(false);
  const set = (k, num) => (e) => setF((p) => ({ ...p, [k]: num ? Number(e.target.value) : e.target.value }));
  const setPlan = (e) => {
    const pid = Number(e.target.value);
    const s = services.find(x => x.id === pid);
    setF(p => ({
      ...p,
      planId: pid,
      planFrequency: s && s.planFrequency ? s.planFrequency : (p.planFrequency || ''),
      planPeriod: s && s.planPeriod ? s.planPeriod : (p.planPeriod || 'semana'),
      planPrice: s && typeof s.price === 'number' ? s.price : (p.planPrice || 0),
      extraClassPrice: p.extraClassPrice || 0,
      planDueDay: p.planDueDay || ''
    }));
  };
  const setCompany = (e) => {
    const id = Number(e.target.value);
    const c = companies.find(x => x.id === id);
    setF((p) => ({
      ...p,
      companyId: id,
      companyName: c ? c.name : '',
      companyCnpj: c ? c.cnpj : '',
      companyPhone: c ? c.phone : '',
      companyEmail: c ? c.email : '',
    }));
  };
  const createCategory = async () => {
    if (!categoryName.trim() || categoryBusy || !onAddCategory) return;
    setCategoryBusy(true);
    const created = await onAddCategory(categoryName);
    if (created) {
      setF((p) => ({ ...p, tag: created }));
      setCategoryName('');
    }
    setCategoryBusy(false);
  };
  const removeCategory = async (category) => {
    if (categoryBusy || !onDeleteCategory) return;
    setCategoryBusy(true);
    const removed = await onDeleteCategory(category);
    if (removed && f.tag === category) {
      setF((p) => ({ ...p, tag: categories.find((item) => item !== category) || '' }));
    }
    setCategoryBusy(false);
  };

  // CPF: estado de validação (null = vazio/incompleto)
  const cpfDigits = DB.mask.digits(f.cpf);
  const cpfValid = cpfDigits.length === 11 ? DB.validateCPF(f.cpf) : null;

  // CEP: ao completar 8 dígitos, busca endereço e preenche o formulário
  const onCep = async (e) => {
    const masked = e.target.value;
    setF((p) => ({ ...p, cep: masked }));
    setCep({ loading: false, found: null });
    if (DB.mask.digits(masked).length === 8) {
      setCep({ loading: true, found: null });
      const addr = await window.viaCEP(masked);
      if (addr) {
        setF((p) => ({ ...p, address: addr.address, district: addr.district, city: addr.city, uf: addr.uf }));
        setCep({ loading: false, found: true });
      } else {
        setCep({ loading: false, found: false });
      }
    }
  };

  const save = async () => {
    if (!f.name || saving || cpfValid === false || billingInvalid) return;
    setSaving(true);
    const payload = { ...f };
    if (!canManageBilling) delete payload.monthlyBillingEnabled;
    await onSave(payload);
    setSaving(false);
  };
  const billingInvalid = canManageBilling && f.monthlyBillingEnabled && (!(Number(f.planDueDay) >= 1 && Number(f.planDueDay) <= 31) || !(Number(f.planPrice) > 0));
  return (
    <window.Modal wide title={initial ? `Editar ${terms.client.toLowerCase()}` : `Novo ${terms.client.toLowerCase()}`} sub="Dados de contato, empresa e endereço" onClose={onClose}
      footer={<><div style={{ flex: 1 }} /><window.Button variant="ghost" onClick={onClose}>Cancelar</window.Button>
        <window.Button variant="primary" icon="check" disabled={saving || cpfValid === false || billingInvalid} onClick={save}>{saving ? 'Salvando…' : 'Salvar'}</window.Button></>}>
      <div className="form-grid">
        <window.Field label="Nome completo" full><window.Input placeholder="Ex.: Maria Silva" value={f.name} onChange={set('name')} autoFocus /></window.Field>
        <window.Field label="Telefone"><window.MaskInput mask="phone" placeholder="(11) 90000-0000" value={f.phone} onChange={set('phone')} /></window.Field>
        <window.Field label="CPF" optional>
          <window.MaskInput mask="cpf" placeholder="000.000.000-00" value={f.cpf} onChange={set('cpf')}
            className={'input' + (cpfValid === false ? ' invalid' : '')} />
          {cpfValid === true && <div className="field-hint ok"><window.Icon name="check" size={12} /> CPF válido</div>}
          {cpfValid === false && <div className="field-hint err"><window.Icon name="info" size={12} /> CPF inválido</div>}
        </window.Field>
        <window.Field label="E-mail" optional><window.Input placeholder="email@exemplo.com" value={f.email} onChange={set('email')} /></window.Field>
        <window.Field label="Categoria" full>
          <div className="row" style={{ gap: 8, alignItems: 'stretch' }}>
            <window.Select value={f.tag} onChange={set('tag')} style={{ flex: 1 }}>
              {categories.map((category) => <option key={category} value={category}>{category}</option>)}
            </window.Select>
            <button type="button" className="iconbtn bordered" title="Cadastrar ou excluir categorias" onClick={() => setCategoryOpen((open) => !open)} style={{ width: 40, height: 40, flex: 'none' }}>
              <window.Icon name="plus" size={17} />
            </button>
          </div>
          {categoryOpen && (
            <div className="card" style={{ marginTop: 8, padding: 10 }}>
              <div className="row" style={{ gap: 8 }}>
                <window.Input placeholder="Nome da nova categoria" value={categoryName} maxLength={30}
                  onChange={(e) => setCategoryName(e.target.value)} onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); createCategory(); } }} />
                <window.Button variant="primary" size="sm" icon="plus" disabled={categoryBusy || !categoryName.trim()} onClick={createCategory}>Adicionar</window.Button>
              </div>
              <div className="stack" style={{ gap: 6, marginTop: 10 }}>
                {categories.map((category) => (
                  <div key={category} className="row between" style={{ padding: '7px 9px', borderRadius: 8, background: 'var(--surface-2)' }}>
                    <span style={{ fontSize: 13 }}>{category}</span>
                    <button type="button" className="iconbtn" title="Excluir categoria" disabled={categoryBusy} onClick={() => removeCategory(category)} style={{ width: 28, height: 28, color: 'var(--danger)' }}>
                      <window.Icon name="trash" size={14} />
                    </button>
                  </div>
                ))}
              </div>
            </div>
          )}
        </window.Field>
        {terms.extra.includes('convenio') && <window.Field label="Convênio" optional><window.Input placeholder="Ex.: Unimed" value={f.convenio} onChange={set('convenio')} /></window.Field>}
        {terms.extra.includes('prontuario') && <window.Field label="Prontuário" optional><window.Input placeholder="Ex.: 2026-001" value={f.prontuario} onChange={set('prontuario')} /></window.Field>}
        <window.Field label={terms.pro + ' vinculado'} optional full>
          <window.Select value={f.proId} onChange={set('proId', true)}>
            <option value={0}>Sem vínculo — definir ao agendar</option>
            {team.filter((p) => !p.systemIdentity && !p.archived).map(p => <option key={p.id} value={p.id}>{p.name}{p.specialty ? ' · ' + p.specialty : ''}</option>)}
          </window.Select>
        </window.Field>

        {terms.id === 'pilates' && (
          <window.Field label="Plano vinculado" optional full>
            <window.Select value={f.planId} onChange={setPlan}>
              <option value={0}>Nenhum plano (avulso)</option>
              {services && services.map(s => (
                <option key={s.id} value={s.id}>{s.name} ({s.planFrequency ? `${s.planFrequency}x por ${s.planPeriod || 'semana'}` : 'Frequência livre'})</option>
              ))}
            </window.Select>
          </window.Field>
        )}
        {terms.id === 'pilates' && f.planId > 0 && (
          <div style={{ gridColumn: '1 / -1', display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(145px, 1fr))', gap: 12 }}>
            <window.Field label="Quantidade permitida"><window.Input type="number" min="1" max="31" value={f.planFrequency} onChange={set('planFrequency', true)} placeholder="Ex.: 2" /></window.Field>
            <window.Field label="Período do limite">
              <window.Select value={f.planPeriod || 'semana'} onChange={set('planPeriod')}>
                <option value="semana">Por semana</option>
                <option value="mes">Por mês / ciclo</option>
              </window.Select>
            </window.Field>
            <window.Field label="Valor da aula extra"><window.MoneyInput value={f.extraClassPrice} onChange={(n) => setF((p) => ({ ...p, extraClassPrice: n }))} /></window.Field>
          </div>
        )}

        {(canManageBilling || (terms.id === 'pilates' && f.planId > 0)) && <>
          <window.SectionLabel style={{ gridColumn: '1 / -1', margin: '6px 0 0' }}>Mensalidade</window.SectionLabel>
          {canManageBilling && <div className="card" style={{ gridColumn: '1 / -1', padding: 13, display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 14 }}>
            <div>
              <div style={{ fontWeight: 600, fontSize: 13.5 }}>Gerar cobrança mensal automaticamente</div>
              <div className="muted" style={{ fontSize: 12, marginTop: 2 }}>Cria um lançamento a receber em cada vencimento, sem precisar lançar manualmente.</div>
            </div>
            <window.Switch on={f.monthlyBillingEnabled} onClick={() => setF((p) => ({ ...p, monthlyBillingEnabled: !p.monthlyBillingEnabled }))} />
          </div>}
          {(f.monthlyBillingEnabled || (terms.id === 'pilates' && f.planId > 0)) && <>
            <window.Field label="Dia do vencimento" optional={!f.monthlyBillingEnabled}>
              <window.Input type="number" min="1" max="31" value={f.planDueDay} disabled={!canManageBilling && f.monthlyBillingEnabled} onChange={set('planDueDay', true)} placeholder="Ex.: 10" />
            </window.Field>
            <window.Field label="Valor mensal">
              <window.MoneyInput value={f.planPrice} disabled={!canManageBilling && f.monthlyBillingEnabled} onChange={(n) => setF((p) => ({ ...p, planPrice: n }))} />
            </window.Field>
            {f.monthlyBillingEnabled && <div className="field-hint" style={{ gridColumn: '1 / -1', marginTop: -5 }}>
              A primeira cobrança será criada no próximo vencimento e as seguintes serão geradas automaticamente. Se o dia não existir no mês, será usado o último dia.
            </div>}
            {billingInvalid && <div className="field-hint err" style={{ gridColumn: '1 / -1', marginTop: -5 }}>
              <window.Icon name="info" size={12} /> Informe um dia entre 1 e 31 e um valor maior que zero.
            </div>}
          </>}
        </>}

        <window.SectionLabel style={{ gridColumn: '1 / -1', margin: '6px 0 0' }}>Empresa</window.SectionLabel>
        <window.Field label="Empresa" optional full>
          <window.Select value={f.companyId || 0} onChange={setCompany} disabled={!!lockedCompany}>
            <option value={0}>Sem empresa vinculada</option>
            {companies.map(c => <option key={c.id} value={c.id}>{c.name}</option>)}
          </window.Select>
        </window.Field>
        <window.Field label="Cargo" optional><window.Input placeholder="Ex.: Gerente financeiro" value={f.companyRole} onChange={set('companyRole')} /></window.Field>
        {!f.companyId && <>
          <window.Field label="Empresa avulsa" optional><window.Input placeholder="Nome da empresa" value={f.companyName} onChange={set('companyName')} /></window.Field>
          <window.Field label="CNPJ" optional><window.MaskInput mask="cnpj" placeholder="00.000.000/0000-00" value={f.companyCnpj} onChange={set('companyCnpj')} /></window.Field>
          <window.Field label="Telefone da empresa" optional><window.MaskInput mask="phone" placeholder="(11) 3000-0000" value={f.companyPhone} onChange={set('companyPhone')} /></window.Field>
          <window.Field label="E-mail da empresa" optional><window.Input placeholder="empresa@exemplo.com" value={f.companyEmail} onChange={set('companyEmail')} /></window.Field>
        </>}

        <window.SectionLabel style={{ gridColumn: '1 / -1', margin: '6px 0 0' }}>Endereço</window.SectionLabel>
        <window.Field label="CEP" optional>
          <window.MaskInput mask="cep" placeholder="00000-000" value={f.cep} onChange={onCep} />
          {cep.loading && <div className="field-hint" style={{ color: 'var(--text-3)' }}><window.Icon name="search" size={12} /> Buscando endereço…</div>}
          {cep.found === true && <div className="field-hint ok"><window.Icon name="check" size={12} /> Endereço preenchido</div>}
          {cep.found === false && <div className="field-hint err"><window.Icon name="info" size={12} /> CEP não encontrado</div>}
        </window.Field>
        <window.Field label="Logradouro" optional><window.Input placeholder="Rua, avenida…" value={f.address} onChange={set('address')} /></window.Field>
        <window.Field label="Número" optional><window.Input placeholder="Nº" value={f.addressNum} onChange={set('addressNum')} /></window.Field>
        <window.Field label="Bairro" optional><window.Input placeholder="Bairro" value={f.district} onChange={set('district')} /></window.Field>
        <window.Field label="Cidade" optional><window.Input placeholder="Cidade" value={f.city} onChange={set('city')} /></window.Field>
        <window.Field label="UF" optional><window.Input placeholder="UF" maxLength={2} value={f.uf} onChange={(e) => setF((p) => ({ ...p, uf: e.target.value.toUpperCase().slice(0, 2) }))} /></window.Field>

        <window.Field label="Observações" optional full><window.Textarea placeholder="Preferências, alergias, anotações…" value={f.notes} onChange={set('notes')} /></window.Field>
      </div>
    </window.Modal>
  );
}

/* ---------------- SERVIÇOS ---------------- */
function commissionLabel(type, value, DB = window.DB) {
  if (type === 'percentage') return `${Number(value) || 0}%`;
  if (type === 'fixed') return DB.money(Number(value) || 0);
  return 'Sem comissão definida';
}

function CommissionFields({ type, value, onChange, typeLabel = 'Tipo de comissão' }) {
  const displayedValue = Number(value) === 0 ? '' : value;
  return <>
    <window.Field label={typeLabel}>
      <window.Select value={type || 'none'} onChange={(e) => onChange(e.target.value, e.target.value === 'none' ? 0 : (type === 'none' ? '' : value))}>
        <option value="none">Sem comissão padrão</option>
        <option value="percentage">Porcentagem</option>
        <option value="fixed">Valor fixo</option>
      </window.Select>
    </window.Field>
    {type !== 'none' && <window.Field label={type === 'percentage' ? 'Porcentagem (%)' : 'Valor fixo (R$)'}>
      <window.Input type="number" min="0" max={type === 'percentage' ? '100' : undefined} step="0.01" value={displayedValue} placeholder={type === 'percentage' ? 'Ex.: 10' : 'Ex.: 50,00'} onFocus={(e) => e.target.select()} onChange={(e) => onChange(type, e.target.value === '' ? '' : Number(e.target.value))} />
      <div className="field-hint">Digite diretamente {type === 'percentage' ? 'a porcentagem, sem o símbolo %' : 'o valor em reais'}.</div>
    </window.Field>}
  </>;
}

function ServicesScreen(ctx) {
  const { terms, services, team, toast } = ctx;
  const DB = window.DB;
  const [adding, setAdding] = React.useState(false);
  const [editing, setEditing] = React.useState(null);
  const cats = [...new Set(services.map(s => s.cat))];

  const save = async (data) => {
    try {
      if (editing) { await ctx.updateService(editing.id, data); toast(terms.service + ' atualizado!'); }
      else { await ctx.addService(data); toast('Salvo com sucesso!'); }
      setAdding(false); setEditing(null);
    } catch (e) { toast(e.message, 'x'); }
  };

  const remove = (s) => {
    if (!window.confirm(`Excluir "${s.name}"?`)) return;
    ctx.deleteService(s.id);
  };

  return (
    <div className="content-inner fadein">
      <Header title={terms.services} sub={`${services.length} ${terms.services.toLowerCase()} · ${cats.length} categorias`} action={
        <window.Button variant="primary" icon="plus" onClick={() => setAdding(true)}>Novo {terms.service.toLowerCase()}</window.Button>
      } />
      {services.length === 0 && <window.Empty icon="tag" title={'Nenhum ' + terms.service.toLowerCase()} desc="Cadastre o primeiro para começar a agendar." />}
      {cats.map(cat => (
        <div key={cat} style={{ marginBottom: 22 }}>
          <div className="row" style={{ gap: 8, marginBottom: 12 }}>
            <h3 style={{ fontSize: 14 }}>{cat}</h3>
            <span className="badge plain">{services.filter(s => s.cat === cat).length}</span>
          </div>
          <div className="grid-3">
            {services.filter(s => s.cat === cat).map(s => (
              <div className="card card-pad" key={s.id} style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
                <div className="row between">
                  <div className="ic" style={{ width: 40, height: 40, borderRadius: 11, background: `var(--ev-${s.color}-bg)`, color: `var(--ev-${s.color})`, display: 'grid', placeItems: 'center' }}>
                    <window.Icon name="zap" size={18} />
                  </div>
                  <window.Menu trigger={<button className="iconbtn" style={{ width: 30, height: 30 }}><window.Icon name="dots" size={16} /></button>}>
                    <button onClick={() => setEditing(s)}><window.Icon name="edit" size={15} /> Editar</button>
                    <button onClick={() => ctx.duplicateService(s)}><window.Icon name="copy" size={15} /> Duplicar</button>
                    <div className="sep" />
                    <button className="danger" onClick={() => remove(s)}><window.Icon name="trash" size={15} /> Excluir</button>
                  </window.Menu>
                </div>
                <div>
                  <div style={{ fontWeight: 600, fontSize: 14.5 }}>{s.name}</div>
                  <div className="muted" style={{ fontSize: 12.5, marginTop: 2 }}>{s.desc}</div>
                  {terms.id === 'pilates' && s.commissionType !== 'none' && <div className="muted" style={{ fontSize: 12, marginTop: 5 }}>Comissão padrão: {commissionLabel(s.commissionType, s.commissionValue, DB)}</div>}
                  {terms.id === 'pilates' && (s.commissionOverrides || []).length > 0 && <div className="muted" style={{ fontSize: 12, marginTop: 2 }}>{s.commissionOverrides.length} ajuste{(s.commissionOverrides || []).length === 1 ? '' : 's'} por instrutor</div>}
                </div>
                <div className="row between" style={{ marginTop: 'auto', paddingTop: 10, borderTop: '1px solid var(--border)' }}>
                  <span className="badge plain"><window.Icon name="clock" size={13} /> {s.dur} min</span>
                  <span className="mono" style={{ fontWeight: 700, fontSize: 15, fontFamily: 'var(--font-display)' }}>{s.price === 0 ? 'Interno' : DB.money0(s.price)}</span>
                </div>
              </div>
            ))}
          </div>
        </div>
      ))}
      {(adding || editing) && <ServiceModal terms={terms} team={team} initial={editing} onClose={() => { setAdding(false); setEditing(null); }} onSave={save} />}
    </div>
  );
}

function ServiceModal({ terms, team = [], initial, onClose, onSave }) {
  let catOptions = terms.id === 'escritorio'
    ? ['Compromisso', 'Reunião', 'Análise', 'Documento', 'Assessoria', 'Pacote']
    : ['Atendimento', 'Avaliação', 'Reunião', 'Pacote'];
  if (terms.id === 'pilates') {
    catOptions = ['Aula', 'Plano', 'Reposicao', 'Avaliacao', 'Experimental'];
  }
  const initialCategory = terms.id === 'pilates' && ['Plano mensal', 'Plano semanal'].includes(initial && initial.cat)
    ? 'Plano'
    : (initial && initial.cat);
  const [f, setF] = React.useState(initial
    ? { name: initial.name, cat: initialCategory, dur: initial.dur, price: initial.price, desc: initial.desc, planFrequency: initial.planFrequency || '', planPeriod: initial.planPeriod || 'semana', commissionType: initial.commissionType || 'none', commissionValue: initial.commissionValue || 0, commissionOverrides: initial.commissionOverrides || [] }
    : { name: '', cat: catOptions[0], dur: 30, price: 0, desc: '', planFrequency: '', planPeriod: 'semana', commissionType: 'none', commissionValue: 0, commissionOverrides: [] });
  const [saving, setSaving] = React.useState(false);
  const [commissionOpen, setCommissionOpen] = React.useState(false);
  const set = (k, num) => (e) => setF({ ...f, [k]: num ? Number(e.target.value) : e.target.value });
  const save = async () => { if (!f.name || saving) return; setSaving(true); await onSave(f); setSaving(false); };
  const setCommissionOverride = (proId, commissionType, commissionValue) => setF((prev) => {
    const without = (prev.commissionOverrides || []).filter((item) => Number(item.proId) !== Number(proId));
    return { ...prev, commissionOverrides: commissionType === 'none' ? without : [...without, { proId: Number(proId), commissionType, commissionValue: Number(commissionValue) || 0 }] };
  });
  return (
    <>
    <window.Modal title={initial ? `Editar ${terms.service.toLowerCase()}` : `Novo ${terms.service.toLowerCase()}`} sub="Defina duração e valor" onClose={onClose}
      footer={<><div style={{ flex: 1 }} /><window.Button variant="ghost" onClick={onClose}>Cancelar</window.Button>
        <window.Button variant="primary" icon="check" disabled={saving} onClick={save}>{saving ? 'Salvando…' : 'Salvar'}</window.Button></>}>
      <div className="form-grid">
        <window.Field label={'Nome do ' + terms.service.toLowerCase()} full><window.Input placeholder={`Ex.: ${terms.id === 'escritorio' ? 'Reunião comercial' : (terms.id === 'pilates' ? 'Aula experimental' : terms.service + ' inicial')}`} value={f.name} onChange={set('name')} autoFocus /></window.Field>
        <window.Field label="Categoria"><window.Select value={f.cat} onChange={set('cat')}>{catOptions.map(cat => <option key={cat}>{cat}</option>)}</window.Select></window.Field>
        <window.Field label="Duração (min)"><window.Input type="number" min="5" step="5" value={f.dur} onChange={set('dur', true)} /></window.Field>
        <window.Field label="Valor"><window.MoneyInput value={f.price} onChange={(n) => setF((p) => ({ ...p, price: n }))} /></window.Field>
        {terms.id === 'pilates' && <CommissionFields type={f.commissionType} value={f.commissionValue} onChange={(commissionType, commissionValue) => setF((p) => ({ ...p, commissionType, commissionValue }))} typeLabel="Comissão padrão do serviço" />}
        {terms.id === 'pilates' && <div style={{ gridColumn: '1 / -1' }}>
          <window.Button variant="outline" icon="users" onClick={() => setCommissionOpen(true)}>Ajustar comissão por instrutor{f.commissionOverrides.length ? ` (${f.commissionOverrides.length})` : ''}</window.Button>
          <div className="muted" style={{ fontSize: 12, marginTop: 6 }}>Escolha porcentagem ou valor fixo e digite manualmente. O ajuste individual tem prioridade sobre a comissão padrão deste serviço e do instrutor.</div>
        </div>}
        {terms.id === 'pilates' && f.cat === 'Plano' && (
          <>
            <window.Field label="Aulas permitidas" optional><window.Input type="number" min="1" max="31" value={f.planFrequency} onChange={set('planFrequency', true)} placeholder="Ex.: 2" /></window.Field>
            <window.Field label="Período do limite" optional>
              <window.Select value={f.planPeriod} onChange={set('planPeriod')}>
                <option value="semana">Por semana</option>
                <option value="mes">Por mês</option>
              </window.Select>
            </window.Field>
          </>
        )}
        <window.Field label="Descrição" optional full><window.Textarea placeholder="O que está incluso…" value={f.desc} onChange={set('desc')} /></window.Field>
      </div>
    </window.Modal>
    {commissionOpen && <window.Modal wide title="Comissão por instrutor" sub={`Ajustes específicos para ${f.name || terms.service.toLowerCase()}`} onClose={() => setCommissionOpen(false)}
      footer={<><div style={{ flex: 1 }} /><window.Button variant="primary" icon="check" onClick={() => setCommissionOpen(false)}>Concluir ajustes</window.Button></>}>
      <div className="stack" style={{ gap: 10 }}>
        {team.filter((p) => !p.archived && !p.systemIdentity).map((p) => {
          const override = (f.commissionOverrides || []).find((item) => Number(item.proId) === Number(p.id));
          const type = override ? override.commissionType : 'none';
          const value = override ? override.commissionValue : 0;
          return <div key={p.id} className="card card-pad commission-pro-row" style={{ display: 'grid', gridTemplateColumns: 'minmax(180px, 1fr) minmax(150px, .7fr) minmax(130px, .55fr)', gap: 10, alignItems: 'center', padding: 12 }}>
            <div className="row" style={{ gap: 9, minWidth: 0 }}><window.Avatar initials={p.initials} color={p.color} size={30} /><div><div style={{ fontWeight: 700 }}>{p.name}</div><div className="muted" style={{ fontSize: 11.5 }}>Padrão do instrutor: {commissionLabel(p.commissionType, p.commissionValue)}</div></div></div>
            <window.Select value={type} onChange={(e) => setCommissionOverride(p.id, e.target.value, value)}>
              <option value="none">Usar padrões</option><option value="percentage">Porcentagem própria</option><option value="fixed">Valor fixo próprio</option>
            </window.Select>
            {type === 'percentage' ? <window.Input type="number" min="0" max="100" step="0.01" value={Number(value) === 0 ? '' : value} placeholder="Ex.: 10" onFocus={(e) => e.target.select()} onChange={(e) => setCommissionOverride(p.id, type, e.target.value === '' ? '' : Number(e.target.value))} />
              : type === 'fixed' ? <window.Input type="number" min="0" step="0.01" value={Number(value) === 0 ? '' : value} placeholder="Ex.: 50,00" onFocus={(e) => e.target.select()} onChange={(e) => setCommissionOverride(p.id, type, e.target.value === '' ? '' : Number(e.target.value))} />
              : <span className="muted" style={{ fontSize: 12 }}>{f.commissionType !== 'none' ? `Serviço: ${commissionLabel(f.commissionType, f.commissionValue)}` : 'Padrão do instrutor'}</span>}
          </div>;
        })}
        {team.filter((p) => !p.archived && !p.systemIdentity).length === 0 && <window.Empty icon="users" title="Nenhum instrutor cadastrado" desc="Cadastre os instrutores antes de criar ajustes individuais." />}
      </div>
    </window.Modal>}
    </>
  );
}

/* ---------------- EQUIPE ---------------- */
const TEAM_WEEK_DAYS = [
  ['0', 'Dom'],
  ['1', 'Seg'],
  ['2', 'Ter'],
  ['3', 'Qua'],
  ['4', 'Qui'],
  ['5', 'Sex'],
  ['6', 'Sáb'],
];

function defaultTeamAvailability(start = '08:00', end = '18:00', lunchStart = '', lunchEnd = '') {
  return TEAM_WEEK_DAYS.reduce((acc, [key]) => {
    acc[key] = { enabled: !['0', '6'].includes(key), start, end, lunchStart, lunchEnd };
    return acc;
  }, {});
}

function availabilitySummary(p) {
  const availability = p.availability || {};
  const active = TEAM_WEEK_DAYS.filter(([key]) => availability[key] && availability[key].enabled);
  if (active.length === 0) return 'Sem dias configurados';
  if (active.length === 5 && active.every(([key]) => ['1', '2', '3', '4', '5'].includes(key))) return 'Seg a Sex';
  if (active.length === 7) return 'Todos os dias';
  return active.map(([, label]) => label).join(', ');
}

function TeamScreen(ctx) {
  const { terms, team, clients, appts, openNewAppt, toast } = ctx;
  const regularTeam = team.filter((p) => !p.systemIdentity && !p.archived);
  const ownAdminProfile = team.find((p) => p.systemIdentity && !p.archived && ctx.user && Number(p.id) === Number(ctx.user.proId));
  const visibleTeam = ownAdminProfile ? [ownAdminProfile, ...regularTeam.filter((p) => Number(p.id) !== Number(ownAdminProfile.id))] : regularTeam;
  const DB = window.DB;
  const todayISO = DB.iso(DB.today);
  const [adding, setAdding] = React.useState(false);
  const [editing, setEditing] = React.useState(null);

  const save = async (data) => {
    try {
      if (editing) { await ctx.updatePro(editing.id, data); toast('Perfil atualizado!'); }
      else { await ctx.addPro(data); toast('Cadastro adicionado em ' + terms.pros + '!'); }
      setAdding(false); setEditing(null);
    } catch (e) { toast(e.message, 'x'); }
  };

  const remove = (p) => {
    if (!window.confirm(`Remover ${p.name} de ${terms.pros}?`)) return;
    ctx.deletePro(p.id);
  };

  const maxPros = (ctx.limits && ctx.limits.maxPros) || 0;
  const maxUsers = (ctx.limits && ctx.limits.maxUsers) || 0;
  const accessLimitReached = maxUsers > 0 && ((ctx.user && ctx.user.loginUserCount) || 1) >= maxUsers;
  const atLimit = maxPros > 0 && regularTeam.length >= maxPros;
  const canAddTeam = !!(ctx.user && ctx.user.hasTeam);
  const usage = `${regularTeam.length}${maxPros > 0 ? '/' + maxPros : ''} cadastros · ${visibleTeam.filter(p => p.online).length} online agora`;

  return (
    <div className="content-inner fadein">
      <Header title={terms.pros} sub={usage} action={
        <window.Button variant="primary" icon="plus" disabled={!canAddTeam || atLimit} onClick={() => setAdding(true)}>Adicionar</window.Button>
      } />
      {!canAddTeam && (
        <div className="card" style={{ display: 'flex', gap: 10, alignItems: 'center', padding: '12px 16px', marginBottom: 16, background: 'var(--surface-2)' }}>
          <window.Icon name="info" size={18} style={{ color: 'var(--text-3)', flex: 'none' }} />
          <div style={{ fontSize: 13 }}>
            Seu plano nao inclui cadastro de equipe, mas o administrador pode ajustar o proprio horario de agenda.
          </div>
        </div>
      )}
      {atLimit && (
        <div className="card" style={{ display: 'flex', gap: 10, alignItems: 'center', padding: '12px 16px', marginBottom: 16, background: 'var(--warning-soft)', borderColor: 'var(--warning)' }}>
          <window.Icon name="info" size={18} style={{ color: 'var(--warning)', flex: 'none' }} />
          <div style={{ fontSize: 13 }}>
            <b>Limite do plano atingido.</b> Sua empresa pode ter até {maxPros} {maxPros === 1 ? 'cadastro' : 'cadastros'} em {terms.pros.toLowerCase()}. Para adicionar mais, fale com o suporte.
          </div>
        </div>
      )}
      <div className="grid-3">
        {visibleTeam.map(p => {
          const count = appts.filter(a => a.proId === p.id && a.date === todayISO && a.status !== 'cancelado').length;
          const linked = clients.filter(c => c.proId === p.id).length;
          return (
            <div className="card card-pad" key={p.id} style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
              <div className="row between">
                <div className="row" style={{ gap: 12 }}>
                  <div style={{ position: 'relative' }}>
                    <window.Avatar initials={p.initials} color={p.color} size={48} />
                    <span style={{ position: 'absolute', bottom: 0, right: 0, width: 13, height: 13, borderRadius: 99, background: p.online ? 'var(--success)' : 'var(--text-3)', border: '2.5px solid var(--surface)' }} />
                  </div>
                  <div><div style={{ fontWeight: 600, fontSize: 15 }}>{p.name}</div><div className="muted" style={{ fontSize: 12.5 }}>{p.role}</div></div>
                </div>
                <window.Menu trigger={<button className="iconbtn" style={{ width: 30, height: 30 }}><window.Icon name="dots" size={16} /></button>}>
                  <button onClick={() => setEditing(p)}><window.Icon name="edit" size={15} /> Editar perfil</button>
                  <button onClick={() => ctx.openCalendarFor(p.id)}><window.Icon name="calendar" size={15} /> Ver agenda</button>
                  <button onClick={() => ctx.openClientsFor(p.id)}><window.Icon name="users" size={15} /> Ver {terms.clients.toLowerCase()}</button>
                  <div className="sep" />
                  {!p.systemIdentity && <button className="danger" onClick={() => remove(p)}><window.Icon name="logout" size={15} /> Remover</button>}
                </window.Menu>
              </div>
              <div className="row wrap" style={{ gap: 6 }}>
                {p.specialty && <span className="badge plain"><window.Icon name="pin" size={12} /> {p.specialty}</span>}
                <span className="badge plain"><window.Icon name="calendar" size={12} /> {availabilitySummary(p)}</span>
                <span className="badge plain"><window.Icon name="clock" size={12} /> {p.start} - {p.end}</span>
                {p.lunchStart && p.lunchEnd && <span className="badge plain"><window.Icon name="clock" size={12} /> {'Almo\u00e7o'} {p.lunchStart} - {p.lunchEnd}</span>}
                {terms.id === 'pilates' && p.commissionType !== 'none' && <span className="badge plain"><window.Icon name="card" size={12} /> Comissão {commissionLabel(p.commissionType, p.commissionValue, DB)}</span>}
              </div>
              <div className="row between" style={{ paddingTop: 12, borderTop: '1px solid var(--border)' }}>
                <div className="row" style={{ gap: 16 }}>
                  <div><div className="mono" style={{ fontWeight: 700, fontSize: 17, fontFamily: 'var(--font-display)' }}>{count}</div><div className="muted" style={{ fontSize: 11 }}>hoje</div></div>
                  <div><div className="mono" style={{ fontWeight: 700, fontSize: 17, fontFamily: 'var(--font-display)' }}>{linked}</div><div className="muted" style={{ fontSize: 11 }}>{terms.clients.toLowerCase()}</div></div>
                </div>
                <window.Button size="sm" variant="outline" icon="calendar" onClick={() => openNewAppt({ proId: p.id })}>Agendar</window.Button>
              </div>
            </div>
          );
        })}
      </div>
      {(adding || editing) && <TeamModal terms={terms} team={team} initial={editing} accessLimitReached={accessLimitReached} maxUsers={maxUsers} onClose={() => { setAdding(false); setEditing(null); }} onSave={save} />}
    </div>
  );
}

function TeamModal({ terms, team = [], initial, onClose, onSave, accessLimitReached = false, maxUsers = 0 }) {
  const [f, setF] = React.useState(initial
    ? { name: initial.name, role: initial.role, specialty: initial.specialty, email: initial.email, phone: initial.phone, color: initial.color || '', start: initial.start, end: initial.end, lunchStart: initial.lunchStart || '', lunchEnd: initial.lunchEnd || '', availability: Object.keys(initial.availability || {}).length ? initial.availability : defaultTeamAvailability(initial.start, initial.end, initial.lunchStart || '', initial.lunchEnd || ''), commissionType: initial.commissionType || 'none', commissionValue: initial.commissionValue || 0, createAcesso: false, login: '', pass: '' }
    : { name: '', role: '', specialty: '', email: '', phone: '', color: '', start: '08:00', end: '18:00', lunchStart: '', lunchEnd: '', availability: defaultTeamAvailability('08:00', '18:00'), commissionType: 'none', commissionValue: 0, createAcesso: false, login: '', pass: '' });
  const [saving, setSaving] = React.useState(false);
  const set = (k) => (e) => setF({ ...f, [k]: e.target.value });
  const usedColors = (team || []).filter((p) => !p.archived && (!initial || Number(p.id) !== Number(initial.id))).map((p) => p.color);
  const setAvail = (day, key, value) => setF(prev => ({
    ...prev,
    availability: {
      ...prev.availability,
      [day]: { ...(prev.availability[day] || { enabled: false, start: prev.start, end: prev.end, lunchStart: '', lunchEnd: '' }), [key]: value },
    },
  }));
  const applyGeneralToWeek = () => setF(prev => ({
    ...prev,
    availability: TEAM_WEEK_DAYS.reduce((acc, [day]) => {
      const current = prev.availability[day] || {};
      acc[day] = { ...current, start: prev.start, end: prev.end, lunchStart: prev.lunchStart || '', lunchEnd: prev.lunchEnd || '' };
      return acc;
    }, {}),
  }));
  const save = async () => { if (!f.name || saving) return; setSaving(true); await onSave(f); setSaving(false); };
  return (
    <window.Modal title={initial ? 'Editar perfil' : `Adicionar em ${terms.pros}`} sub="Dados e horário de trabalho" onClose={onClose}
      footer={<><div style={{ flex: 1 }} /><window.Button variant="ghost" onClick={onClose}>Cancelar</window.Button>
        <window.Button variant="primary" icon="check" disabled={saving} onClick={save}>{saving ? 'Salvando…' : 'Salvar'}</window.Button></>}>
      <div className="form-grid">
        <window.Field label="Nome completo" full><window.Input placeholder="Ex.: Ana Costa" value={f.name} onChange={set('name')} autoFocus /></window.Field>
        <window.Field label="Cargo"><window.Input placeholder="Ex.: Especialista" value={f.role} onChange={set('role')} /></window.Field>
        <window.Field label="Especialidade" optional><window.Input placeholder="Ex.: Consultoria" value={f.specialty} onChange={set('specialty')} /></window.Field>
        <window.Field label="E-mail" optional><window.Input placeholder="email@empresa.com" value={f.email} onChange={set('email')} /></window.Field>
        <window.Field label="Telefone" optional><window.MaskInput mask="phone" placeholder="(11) 90000-0000" value={f.phone} onChange={set('phone')} /></window.Field>
        {terms.id === 'pilates' && <CommissionFields type={f.commissionType} value={f.commissionValue} onChange={(commissionType, commissionValue) => setF((p) => ({ ...p, commissionType, commissionValue }))} typeLabel="Comissão padrão do instrutor" />}
        <window.ColorPicker value={f.color} currentColor={initial && initial.color} usedColors={usedColors} onChange={(color) => setF((p) => ({ ...p, color }))} />
        <window.Field label="Início do expediente"><window.Input type="time" value={f.start} onChange={set('start')} /></window.Field>
        <window.Field label="Fim do expediente"><window.Input type="time" value={f.end} onChange={set('end')} /></window.Field>
        <window.Field label={'In\u00edcio do almo\u00e7o'} optional><window.Input type="time" value={f.lunchStart} onChange={set('lunchStart')} /></window.Field>
        <window.Field label={'Fim do almo\u00e7o'} optional><window.Input type="time" value={f.lunchEnd} onChange={set('lunchEnd')} /></window.Field>
      </div>
      <div style={{ marginTop: 18 }}>
        <div className="row between wrap" style={{ gap: 10, marginBottom: 10 }}>
          <div>
            <div style={{ fontWeight: 700, fontSize: 14 }}>Dias e horários de agenda</div>
            <div className="muted" style={{ fontSize: 12.5 }}>Ajuste quando este {terms.pro.toLowerCase()} atende em cada dia.</div>
          </div>
          <window.Button variant="outline" size="sm" icon="clock" onClick={applyGeneralToWeek}>Aplicar expediente</window.Button>
        </div>
        <div className="team-availability">
          <div className="team-availability-head">
            <span>Dia</span><span>Início</span><span>Fim</span><span>Almoço início</span><span>Almoço fim</span>
          </div>
          {TEAM_WEEK_DAYS.map(([day, label]) => {
            const row = f.availability[day] || { enabled: false, start: f.start, end: f.end, lunchStart: '', lunchEnd: '' };
            return (
              <div key={day} className={'team-availability-row' + (row.enabled ? '' : ' off')}>
                <label className="row" style={{ gap: 8, fontWeight: 700 }}>
                  <input type="checkbox" checked={!!row.enabled} onChange={(e) => setAvail(day, 'enabled', e.target.checked)} />
                  <span>{label}</span>
                </label>
                <window.Input type="time" value={row.start || f.start} disabled={!row.enabled} onChange={(e) => setAvail(day, 'start', e.target.value)} />
                <window.Input type="time" value={row.end || f.end} disabled={!row.enabled} onChange={(e) => setAvail(day, 'end', e.target.value)} />
                <window.Input type="time" value={row.lunchStart || ''} disabled={!row.enabled} onChange={(e) => setAvail(day, 'lunchStart', e.target.value)} />
                <window.Input type="time" value={row.lunchEnd || ''} disabled={!row.enabled} onChange={(e) => setAvail(day, 'lunchEnd', e.target.value)} />
              </div>
            );
          })}
        </div>
      </div>
      {initial && initial.userLogin ? (
        <div style={{ marginTop: 24, padding: 16, background: 'var(--surface-2)', borderRadius: 8 }}>
          <div className="row" style={{ gap: 8, fontWeight: 500 }}>
            <window.Icon name="check" size={16} style={{ color: 'var(--success)' }} />
            Este membro já tem acesso ao sistema · login: <b>{initial.userLogin}</b>
          </div>
          <div className="muted" style={{ fontSize: 12.5, marginTop: 6 }}>Para redefinir a senha, use a tela de Usuários.</div>
        </div>
      ) : (
        <div style={{ marginTop: 24, padding: 16, background: 'var(--surface-2)', borderRadius: 8 }}>
          {accessLimitReached ? (
            <div className="row" style={{ gap: 8, fontSize: 13 }}><window.Icon name="info" size={16} style={{ color: 'var(--warning)' }} /><span>Limite de {maxUsers} usuários com login atingido. Este membro pode ser cadastrado normalmente, mas sem login e senha.</span></div>
          ) : <label className="row" style={{ gap: 8, cursor: 'pointer', fontWeight: 500 }}>
              <input type="checkbox" checked={f.createAcesso} onChange={(e) => setF({ ...f, createAcesso: e.target.checked })} style={{ width: 16, height: 16 }} />
              Criar acesso ao sistema para este membro
            </label>}
          {f.createAcesso && (
            <div className="form-grid" style={{ marginTop: 16 }}>
              <window.Field label="Usuário (login)"><window.Input placeholder="Nome de usuário" value={f.login} onChange={set('login')} /></window.Field>
              <window.Field label="Senha"><window.Input type="password" placeholder="Mínimo 8 caracteres" value={f.pass} onChange={set('pass')} /></window.Field>
            </div>
          )}
        </div>
      )}
    </window.Modal>
  );
}

/* ---------- shared bits ---------- */
function Header({ title, sub, action }) {
  return (
    <div className="row between wrap" style={{ marginBottom: 20, gap: 12 }}>
      <div><h1 style={{ fontSize: 22 }}>{title}</h1><div className="muted" style={{ fontSize: 13.5, marginTop: 2 }}>{sub}</div></div>
      {action}
    </div>
  );
}
function SectionLabel({ children, style }) {
  return <div style={{ fontSize: 11, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '.05em', color: 'var(--text-3)', margin: '16px 0 9px', ...style }}>{children}</div>;
}
function InfoRow({ icon, label, value }) {
  return (
    <div className="row" style={{ gap: 11, padding: '8px 0' }}>
      <div className="ic" style={{ width: 34, height: 34, borderRadius: 9, background: 'var(--surface-2)', color: 'var(--text-2)', display: 'grid', placeItems: 'center', flex: 'none' }}><window.Icon name={icon} size={16} /></div>
      <div><div className="muted" style={{ fontSize: 11 }}>{label}</div><div style={{ fontSize: 13, fontWeight: 500 }}>{value}</div></div>
    </div>
  );
}

Object.assign(window, { ClientsScreen, SuppliersScreen, ServicesScreen, TeamScreen, ClientModal, ServiceModal, TeamModal, Header, SectionLabel, InfoRow });
