// Seções de acesso compartilhadas entre o drawer de edição rápida e as telas Editar/Adicionar pessoa.

function Switch({ on, onChange, label }) {
  return (
    <label className={'sw' + (on ? ' on' : '')} onClick={(e) => { e.preventDefault(); onChange(!on) }}>
      <span className="sw-track"><span className="sw-handle"></span></span>
      <span className="sw-label">{label != null ? label : (on ? 'Ativo' : 'Inativo')}</span>
    </label>
  )
}

function SelectField({ value, placeholder, options, onChange, error, desc }) {
  const [open, setOpen] = React.useState(false)
  const ref = useOutside(open, () => setOpen(false))
  return (
    <div className="sel-wrap" ref={ref}>
      <div className={'sel' + (value ? ' filled' : '') + (error ? ' error' : '')} style={open ? { borderColor: 'var(--color-primary-200)' } : null} onClick={() => setOpen(!open)}>
        <span>{value || placeholder}</span><I n={open ? 'chevron-up' : 'chevron-down'} />
      </div>
      {open && <ul className="dd">{options.map((o) => <li key={o} className={(value === o ? 'sel ' : '') + (desc ? 'opt-desc' : '')} onClick={() => { onChange(o); setOpen(false) }}>{desc ? <span><span className="opt-t">{o}</span><span className="opt-d">{desc[o]}</span></span> : o}</li>)}</ul>}
    </div>
  )
}

function MultiSelectField({ value, options, onChange, placeholder, emptyMsg }) {
  const [open, setOpen] = React.useState(false)
  const ref = useOutside(open, () => setOpen(false))
  const disp = options.filter((o) => !value.includes(o))
  return (
    <div className="sel-wrap" ref={ref}>
      <div className={'msel' + (open ? ' open' : '')} onClick={() => setOpen(!open)}>
        {value.length === 0 && <span className="msel-ph">{placeholder}</span>}
        {value.map((v) => <span key={v} className="msel-chip">{v}<I n="close" style={{ cursor: 'pointer', fontSize: 11 }} onClick={(e) => { e.stopPropagation(); onChange(value.filter((x) => x !== v)) }} /></span>)}
        <span className="msel-ic">{value.length > 0 && <I n="close" onClick={(e) => { e.stopPropagation(); onChange([]) }} />}<I n="chevron-down" /></span>
      </div>
      {open && <ul className="dd">{disp.length ? disp.map((o) => <li key={o} onClick={() => onChange([...value, o])}>{o}</li>) : <li style={{ cursor: 'default', color: 'var(--color-grayish-light)', background: 'transparent' }}>{emptyMsg || 'Todas as fazendas disponíveis já foram escolhidas'}</li>}</ul>}
    </div>
  )
}

function PerfilPopover({ perfil, all }) {
  const [open, setOpen] = React.useState(false)
  const ref = useOutside(open, () => setOpen(false))
  const { MODULOS, NIVEIS, MATRIZ, PERFIL_DESC, PERFIS } = window.CFG
  if (!perfil && !all) return <span className="perfil-link dis">Ver o que este perfil acessa</span>
  return (
    <span className="pop-wrap" ref={ref}>
      <button type="button" className="perfil-link" onClick={() => setOpen(!open)}>{all ? 'Ver o que cada perfil acessa' : 'Ver o que este perfil acessa'}</button>
      {open && <div className={'popover' + (all ? ' pop-all' : '')} role="dialog" aria-label="Acessos por perfil">
        <div className="pop-h"><div><strong>{all ? 'O que cada perfil acessa' : perfil}</strong><span>{all ? 'Nível de acesso no sistema web, por módulo.' : PERFIL_DESC[perfil]}</span></div><button className="icon-btn" style={{ width: 32, height: 32 }} onClick={() => setOpen(false)}><I n="close" /></button></div>
        {all ? <table className="mx mx-ro"><thead><tr><th>Módulo</th>{PERFIS.map((pf) => <th key={pf}>{pf}</th>)}</tr></thead><tbody>
          {MODULOS.map((m, i) => <tr key={m}><td>{m}</td>{PERFIS.map((pf) => <td key={pf}><span className={'lvl lvl-' + ({ Editar: 'e', Visualizar: 'v', Parcial: 'p', 'Sem acesso': 'n' })[MATRIZ[pf][i]]}>{MATRIZ[pf][i]}</span></td>)}</tr>)}
        </tbody></table>
        : <table className="mx mx-ro"><thead><tr><th>Módulo</th>{NIVEIS.map((n) => <th key={n}>{n}</th>)}</tr></thead><tbody>
          {MODULOS.map((m, i) => <tr key={m}><td>{m}</td>{NIVEIS.map((n) => <td key={n}><I n={MATRIZ[perfil][i] === n ? 'radio-button-on' : 'radio-button-off'} className={MATRIZ[perfil][i] === n ? 'rb-on' : 'rb-off'} /></td>)}</tr>)}
        </tbody></table>}
      </div>}
    </span>
  )
}

function CheckList({ items, value, onChange }) {
  const toggle = (it) => onChange(value.includes(it) ? value.filter((x) => x !== it) : [...value, it])
  return (
    <div className="cblist">
      {items.map((it) => {
        const on = value.includes(it)
        return <label key={it} className={'cb' + (on ? ' on' : '')} onClick={(e) => { e.preventDefault(); toggle(it) }}><I n={on ? 'checkbox-checked' : 'checkbox-unchecked'} />{it}</label>
      })}
    </div>
  )
}

function AccessSection({ title, desc, on, onToggle, flat, children }) {
  return (
    <div className={'fsec' + (flat ? ' flat' : '') + (on ? '' : ' off')}>
      <div className="fsec-head"><div><h4>{title}</h4>{desc && <p>{desc}</p>}</div><Switch on={on} onChange={onToggle} /></div>
      {children && <div className="fsec-body">{!flat && <hr />}{children}</div>}
    </div>
  )
}

function WebSection({ acc, set, flat, onReset, emailErr }) {
  return (
    <AccessSection flat={flat} title="Acesso ao sistema web" desc="Login no sistema web com e-mail e senha." on={acc.web} onToggle={(v) => set({ web: v })}>
      <div className="lbl"><label>E-mail</label><div className="inp" style={emailErr ? { borderColor: 'var(--color-danger-light)' } : null}><input placeholder="nome@grupoguanabara.com.br" value={acc.email} onChange={(e) => set({ email: e.target.value })} /></div>{emailErr && <span className="err-msg">Informe o e-mail para liberar o acesso web.</span>}</div>
      {onReset && <div><button className="btn btn-outline" onClick={onReset}>Enviar redefinição de senha</button></div>}
    </AccessSection>
  )
}

const APP_TITULO = { Boletim: 'Boletins', Maternidade: 'Maternidade', 'Manejo de Pastagem': 'Manejo de Pastagem' }
function AppSection({ acc, set, flat }) {
  const tog = (app, on) => { const v = on ? window.CFG.APPS.filter((x) => x === app || acc.app.includes(x)) : acc.app.filter((x) => x !== app); set({ app: v, appOn: v.length > 0 }) }
  return (
    <React.Fragment>
      {window.CFG.APPS.filter((app) => app !== 'Manejo de Pastagem').map((app, i) => (
        <AccessSection key={app} flat={flat} title={'Acesso ao Aplicativo de ' + (APP_TITULO[app] || app)} on={acc.app.includes(app)} onToggle={(v) => tog(app, v)} />
      ))}
    </React.Fragment>
  )
}

function FarmsSection({ acc, set, flat }) {
  const { FAZENDAS, PERFIS, PERFIL_DESC } = window.CFG
  const cols = [...PERFIS.filter((p) => p !== 'Administrador'), 'Sem acesso']
  const mapa = {}; acc.vinc.forEach(([fs, pf]) => fs.forEach((f) => { if (pf) mapa[f] = pf }))
  const setFarm = (f, pf) => {
    const m = { ...mapa }; if (pf === 'Sem acesso') delete m[f]; else m[f] = pf
    set({ vinc: agrupar(FAZENDAS.filter((x) => m[x]).map((x) => [x, m[x]])) })
  }
  const linhas = FAZENDAS.map((f) => [f, mapa[f] || 'Sem acesso', (pf) => setFarm(f, pf)])
  const n = Object.keys(mapa).length
  return (
    <div className={'fsec' + (flat ? ' flat' : '')}>
      <div className="fsec-head"><div><h4>Fazendas e perfis</h4><p>Marque o perfil da pessoa em cada fazenda.</p></div></div>
      <div className="fsec-body">
        {!flat && <hr />}
        <div className="fsec-head" style={{ alignItems: 'center' }}><div><h4 style={{ fontSize: 'var(--font-size-normal)' }}>Administrador do sistema</h4><p>Acesso total a todas as fazendas, inclusive Configurações.</p></div><Switch on={acc.admin} onChange={(v) => set({ admin: v })} /></div>
        {acc.admin ? <div className="ro-note"><I n="information-circle-outline" />Administradores acessam todas as fazendas.</div> : <React.Fragment>
        <div className="tcard" style={{ boxShadow: 'none', border: 'var(--border-table-hairline)' }}>
          <table className="mx pm">
            <thead><tr><th>Fazenda</th>{cols.map((c) => <th key={c}><span className="pm-h">{c}{PERFIL_DESC[c] && <span className="tt" style={{ border: 0 }}><I n="information-circle-outline" /><span className="tt-box">{PERFIL_DESC[c]}</span></span>}</span></th>)}</tr></thead>
            <tbody>{linhas.map(([f, cur, on]) => (
              <tr key={f} className={cur === 'Sem acesso' ? 'pm-off' : ''}><td>{f}</td>
                {cols.map((c) => <td key={c}><button type="button" className="pm-rb" aria-label={f + ': ' + c} aria-pressed={cur === c} onClick={() => on(c)}><I n={cur === c ? 'radio-button-on' : 'radio-button-off'} className={cur === c ? 'rb-on' : 'rb-off'} /></button></td>)}
              </tr>))}</tbody>
          </table>
        </div>
        <div className="pm-foot" style={{ justifyContent: 'flex-end' }}><PerfilPopover perfil={null} all /></div>
        </React.Fragment>}
      </div>
    </div>
  )
}

const agrupar = (pares) => { const out = []; pares.forEach(([f, pf]) => { const g = out.find((x) => x[1] === pf); g ? g[0].push(f) : out.push([[f], pf]) }); return out }
const accFromPessoa = (p) => p ? ({
  web: p.web, email: p.email || '', appOn: p.app.length > 0, app: [...p.app],
  all: false, perfilAll: '', admin: p.perfil === 'Administrador',
  vinc: p.perfil === 'Administrador' ? [] : p.fazendas === 'all' ? [[[...window.CFG.FAZENDAS], p.perfil]] : agrupar(p.perfis ? p.perfis.map((v) => [...v]) : p.fazendas.map((f) => [f, p.perfil])),
}) : ({ web: false, email: '', appOn: false, app: [], all: false, perfilAll: '', admin: false, vinc: [] })

const accToPessoa = (a) => {
  const pares = a.vinc.filter((v) => v[1]).flatMap((v) => v[0].map((f) => [f, v[1]]))
  const distintos = [...new Set(pares.map((v) => v[1]))]
  if (a.admin) return { web: a.web, email: a.email, app: a.appOn ? a.app : [], fazendas: 'all', perfil: 'Administrador', perfis: undefined }
  return {
    web: a.web, email: a.email, app: a.appOn ? a.app : [],
    fazendas: a.all ? 'all' : pares.map((v) => v[0]),
    perfil: a.all ? (a.perfilAll || 'Executor') : (pares[0] ? pares[0][1] : 'Executor'),
    perfis: !a.all && distintos.length > 1 ? pares : undefined,
  }
}
const ERRO_ACESSO = 'Ative o acesso web ou ao menos um aplicativo.'

function useAcc(p) {
  const [acc, setAcc] = React.useState(() => accFromPessoa(p))
  return [acc, (patch) => setAcc((a) => ({ ...a, ...patch }))]
}

function DrawerShell({ title, sub, onClose, children, err, foot }) {
  return (
    <React.Fragment>
      <div className="backdrop" onClick={onClose}></div>
      <aside className="drawer pd" role="dialog" aria-label={title}>
        <div className="pd-close"><button type="button" aria-label="Fechar drawer" onClick={onClose}><I n="close" /></button></div>
        <div className="pd-title"><h4>{title}</h4>{sub && <p>{sub}</p>}</div>
        <div className="pd-body">{children}</div>
        {err && <div className="form-err"><I n="alert-circle-outline" />{err}</div>}
        <div className="pd-foot">{foot}</div>
      </aside>
    </React.Fragment>
  )
}

function PessoaDrawer({ pessoa, onClose, onSave, onDesativar, flash }) {
  const novo = !pessoa
  const erp = pessoa && pessoa.origem === 'ERP'
  const [acc, set] = useAcc(pessoa)
  const [dados, setDados] = React.useState(() => ({ nome: pessoa ? pessoa.nome : '', cracha: pessoa ? pessoa.cracha : '', nascimento: pessoa ? pessoa.nascimento || '' : '' }))
  const [erro, setErro] = React.useState(null)
  const [tentou, setTentou] = React.useState(false)
  React.useEffect(() => { if (erro && (acc.web || acc.appOn)) setErro(null) }, [acc.web, acc.appOn])
  const salvar = () => {
    setTentou(true)
    if (!acc.web && !acc.appOn) return setErro(ERRO_ACESSO)
    if (!dados.nome.trim() || (acc.web && !acc.email.trim()) || (acc.appOn && !dados.nascimento.trim())) return
    onSave(pessoa, { ...dados, ...accToPessoa(acc) })
  }
  const nomeErr = tentou && !dados.nome.trim()
  const emailErr = tentou && acc.web && !acc.email.trim()
  const nascErr = tentou && acc.appOn && !dados.nascimento.trim()
  const errs = { nome: nomeErr && 'Informe o nome.', nascimento: nascErr && 'Informe a data de nascimento. Ela é a senha do aplicativo.' }
  const campo = (label, k, ph) => erp
    ? <div className="lbl"><label>{label}</label><div className="ro"><span>{dados[k]}</span><i className="lock" title="Somente leitura"></i></div>{errs[k] && <span className="err-msg">{errs[k]}</span>}</div>
    : <div className="lbl"><label>{label}</label><div className="inp" style={errs[k] ? { borderColor: 'var(--color-danger-light)' } : null}><input placeholder={ph} value={dados[k]} onChange={(e) => setDados({ ...dados, [k]: e.target.value })} /></div>{errs[k] && <span className="err-msg">{errs[k]}</span>}</div>
  return (
    <DrawerShell title={novo ? 'Adicionar pessoa' : 'Editar pessoa'} sub={novo ? null : pessoa.nome + ' · Matrícula ' + pessoa.cracha} onClose={onClose} err={erro}
      foot={novo
        ? <React.Fragment><button className="btn btn-ghost" onClick={onClose}>Cancelar</button><button className="btn btn-primary" onClick={salvar}>Adicionar pessoa</button></React.Fragment>
        : <React.Fragment>{pessoa.ativo ? <button className="btn btn-destructive" onClick={() => onDesativar(pessoa)}>Desativar pessoa</button> : <span></span>}<div className="ft-right"><button className="btn btn-ghost" onClick={onClose}>Cancelar</button><button className="btn btn-primary" onClick={salvar}>Salvar alterações</button></div></React.Fragment>}>
      <div className="fsec flat">
        <div className="fsec-head"><div><h4>Dados pessoais</h4></div></div>
        <div className="fsec-body">
          <div className="pd-row3">{campo('Nome completo', 'nome', 'Inserir nome')}{campo('Matrícula', 'cracha', 'Inserir matrícula')}{campo('Data de nascimento', 'nascimento', 'DD/MM/AAAA')}</div>
          {erp && <div className="ro-note"><I n="information-circle-outline" />Dados sincronizados pela planilha do ERP. Altere na origem.</div>}
        </div>
      </div>
      <WebSection flat acc={acc} set={set} emailErr={emailErr} />
      <AppSection flat acc={acc} set={set} />
      <FarmsSection flat acc={acc} set={set} />
    </DrawerShell>
  )
}

function Tri({ value, onChange }) {
  return <div className="tri">{['Manter como está', 'Liberar', 'Remover'].map((o) => <button key={o} type="button" className={value === o ? 'on' : ''} onClick={() => onChange(o)}>{o}</button>)}</div>
}

function BulkDrawer({ pessoas, onClose, onApply }) {
  const { APPS, FAZENDAS, PERFIS } = window.CFG
  const [apps, setApps] = React.useState(() => Object.fromEntries(APPS.map((a) => [a, 'Manter como está'])))
  const [vinc, setVinc] = React.useState(false)
  const [faz, setFaz] = React.useState([])
  const [perf, setPerf] = React.useState('')
  const n = pessoas.length
  const mudou = Object.values(apps).some((v) => v !== 'Manter como está') || (vinc && faz.length && perf)
  const vincIncompleto = vinc && (!faz.length || !perf)
  return (
    <DrawerShell title="Editar acessos" sub={n + ' pessoas selecionadas: ' + pessoas.map((p) => p.nome).join(', ')} onClose={onClose}
      foot={<React.Fragment><button className="btn btn-ghost" onClick={onClose}>Cancelar</button><button className="btn btn-primary" disabled={!mudou || vincIncompleto} onClick={() => onApply(pessoas, apps, vinc && faz.length && perf ? [faz, perf] : null)}>{'Aplicar a ' + n + ' pessoas'}</button></React.Fragment>}>
      <div className="fsec flat">
        <div className="fsec-head"><div><h4>Acesso aos aplicativos</h4><p>Escolha o que muda em cada app. "Manter como está" preserva o acesso atual de cada pessoa.</p></div></div>
        <div className="fsec-body">
          <div className="bulk-apps">
            {APPS.map((a) => {
              const tem = pessoas.filter((p) => p.app.includes(a)).length
              return <div className="bulk-app" key={a}><div><strong>{a}</strong><small>{tem === 0 ? 'Nenhuma tem hoje' : tem === n ? 'Todas têm hoje' : tem + ' de ' + n + ' têm hoje'}</small></div><Tri value={apps[a]} onChange={(v) => setApps({ ...apps, [a]: v })} /></div>
            })}
          </div>
          <div className="ro-note"><I n="information-circle-outline" />O login no aplicativo usa o número da matrícula.</div>
        </div>
      </div>
      <div className="fsec flat">
        <div className="fsec-head"><div><h4>Fazendas e perfis</h4><p>Os vínculos atuais são mantidos. Se a pessoa já tiver a fazenda, o perfil dela nessa fazenda é atualizado.</p></div></div>
        <div className="fsec-body">
          <label className={'cb' + (vinc ? ' on' : '')} onClick={(e) => { e.preventDefault(); setVinc(!vinc) }}><I n={vinc ? 'checkbox-checked' : 'checkbox-unchecked'} />Adicionar vínculo de fazenda</label>
          {vinc && <div className="link-list">
            <div className="link-head" style={{ gridTemplateColumns: 'minmax(0,1fr) minmax(0,1fr)' }}><span className="cap">Fazendas</span><span className="cap">Perfil de acesso</span></div>
            <div className="link-row" style={{ alignItems: 'start', gridTemplateColumns: 'minmax(0,1fr) minmax(0,1fr)' }}><MultiSelectField value={faz} placeholder="Selecione as fazendas" options={FAZENDAS} onChange={setFaz} /><SelectField value={perf} placeholder="Selecione o perfil" options={PERFIS.filter((p) => p !== 'Administrador')} desc={window.CFG.PERFIL_DESC} onChange={setPerf} /></div>
            <PerfilPopover perfil={perf} />
          </div>}
        </div>
      </div>
    </DrawerShell>
  )
}

function DesativarModal({ pessoa, pessoas, onCancel, onConfirm }) {
  if (pessoas) {
    return (
      <React.Fragment>
        <div className="backdrop" style={{ zIndex: 165 }} onClick={onCancel}></div>
        <div className="modal" role="dialog">
          <h2>Desativar {pessoas.length} pessoas?</h2>
          <p>Elas perdem o acesso ao sistema web e aos aplicativos. Os registros feitos por elas são mantidos.</p>
          <p className="note" style={{ fontSize: 'var(--font-size-normal)' }}>{pessoas.map((p) => p.nome).join(', ')}</p>
          <div className="modal-actions"><button className="btn btn-ghost" onClick={onCancel}>Cancelar</button><button className="btn btn-destructive" onClick={() => onConfirm(pessoas)}>Desativar</button></div>
        </div>
      </React.Fragment>
    )
  }
  const ela = pessoa.g === 'f' ? 'Ela' : 'Ele'
  return (
    <React.Fragment>
      <div className="backdrop" style={{ zIndex: 165 }} onClick={onCancel}></div>
      <div className="modal" role="dialog" aria-label={'Desativar ' + pessoa.nome}>
        <h2>Desativar {pessoa.nome}?</h2>
        <p>{ela} perde o acesso ao sistema web e aos aplicativos. Os registros feitos por {ela.toLowerCase()} são mantidos.</p>
        <p className="note" style={{ fontSize: 'var(--font-size-normal)' }}>A pessoa continua no histórico e pode ser reativada pelo menu de ações da lista.</p>
        <div className="modal-actions"><button className="btn btn-ghost" onClick={onCancel}>Cancelar</button><button className="btn btn-destructive" onClick={() => onConfirm([pessoa])}>Desativar</button></div>
      </div>
    </React.Fragment>
  )
}

Object.assign(window, { DrawerShell, MultiSelectField, PerfilPopover, Switch, SelectField, CheckList, AccessSection, WebSection, AppSection, FarmsSection, PessoaDrawer, BulkDrawer, DesativarModal })
