/* global React, Ic, CloudGate, PageHeader, CrudToolbar, RowActions, AuditCell, Pill, Drawer, TextField, SelectField, TextAreaField, FieldRow, CustomFieldsSection, LookupManager, gradFor, initialsOf */
const { useState: useState6, useMemo: useMemo6 } = React;

// =================== LOCATION TYPES ===================
function LocationTypesPage() {
  return (
    <div className="page">
      <PageHeader title="Location types" sub="Categories assigned to locations (Dock, Storage, Process, …)."/>
      <LookupManager data={CloudGate.DB.LocationTypes} nameField="LocationTypeName" label="Location types" sub="Used by Locations" icon={<Ic.pin width="14" height="14"/>} entity="locationtypes" dbKey="LocationTypes"/>
    </div>
  );
}

// =================== LOOKUPS HUB (small lookup tables) ===================
// Company types live here too (moved out of their own Admin page).
function LookupsPage() {
  return (
    <div className="page">
      <PageHeader title="Lookups" sub="System-wide reference values: company types, levels, statuses and tag types."/>
      <div style={{display:'grid', gridTemplateColumns:'1fr 1fr', gap:18}}>
        <LookupManager data={CloudGate.DB.CompanyTypes}   nameField="CompanyTypeName" label="Company types"   sub="Owner, Tenant, Customer …"   entity="companytypes"   dbKey="CompanyTypes"/>
        <LookupManager data={CloudGate.DB.UserLevels}     nameField="Level"  label="User levels"     sub="Permission tiers"            entity="userlevels"     dbKey="UserLevels"/>
        <LookupManager data={CloudGate.DB.ReaderTypes}    nameField="Type"   label="Reader types"    sub="Hardware models"             entity="readertypes"    dbKey="ReaderTypes"/>
        <LookupManager data={CloudGate.DB.ReaderStatuses} nameField="Status" label="Reader statuses" sub="Online · Offline · Error"    entity="readerstatuses" dbKey="ReaderStatuses"/>
        <LookupManager data={CloudGate.DB.TagTypes}       nameField="Type"   label="Tag types"       sub="RFID, Barcode, …"            entity="tagtypes"       dbKey="TagTypes"/>
        <LookupManager data={CloudGate.DB.AssetStatuses}  nameField="Status" label="Asset statuses"  sub="Active / Non-active"         entity="assetstatuses"  dbKey="AssetStatuses"/>
      </div>
    </div>
  );
}

// =================== COMPANIES ===================
function CompaniesPage() {
  // SystemAdmin sees every Company; TenantAdmin only their Tenant's;
  // anyone else only their own.  All handled by CloudGate.visibleCompanies().
  const [rows, setRows] = useState6(CloudGate.visibleCompanies());
  const [q, setQ] = useState6('');
  const [typeFilter, setTypeFilter] = useState6('all');
  const [editing, setEditing] = useState6(null);
  const [showNew, setShowNew] = useState6(false);

  const filtered = rows.filter(r =>
    (!q || r.Name.toLowerCase().includes(q.toLowerCase())) &&
    (typeFilter === 'all' || r.CompanyTypeId === +typeFilter)
  );

  const save = async (row) => {
    const saved = await CloudGate.apiSave('companies', row);
    if (!saved) return;
    setRows(rs => row.Id ? rs.map(r => r.Id === saved.Id ? saved : r) : [...rs, saved]);
    CloudGate.DB.Companies = row.Id
      ? CloudGate.DB.Companies.map(r => r.Id === saved.Id ? saved : r)
      : [...CloudGate.DB.Companies, saved];
    setEditing(null); setShowNew(false);
  };
  const remove = async (id) => {
    if (!await CloudGate.apiDelete('companies', id)) return;
    setRows(rs => rs.filter(r => r.Id !== id));
    CloudGate.DB.Companies = CloudGate.DB.Companies.filter(r => r.Id !== id);
  };

  return (
    <div className="page">
      {(() => {
        // Only SystemAdmin and TenantAdmin actually see a network of
        // companies — CustomerAdmin and below are scoped to their own
        // single Company, so both the title and the subtitle change.
        const role = window.__currentUser?.role;
        const isMulti = (role === 'SystemAdmin' || role === 'TenantAdmin');
        const title    = isMulti ? 'Companies' : 'Company';
        const subtitle = isMulti
          ? 'Customers, suppliers and carriers in your network.'
          : 'Your company';
        // A "customer" (CustomerAdmin and below) may not create a new company —
        // only Tenant/System admins.  The API enforces this too (CanEditDevices).
        return <PageHeader title={title} sub={subtitle}
                  onNew={CloudGate.canCreateCompany() ? () => setShowNew(true) : undefined}
                  newLabel="New company" onExport={() => {}}/>;
      })()}
      <div className="card">
        <CrudToolbar q={q} onQ={setQ} placeholder="Search by name…" count={filtered.length} total={rows.length}
          filters={
            <select className="select" value={typeFilter} onChange={e => setTypeFilter(e.target.value)}>
              <option value="all">All types</option>
              {CloudGate.DB.CompanyTypes.map(t => <option key={t.Id} value={t.Id}>{t.CompanyTypeName}</option>)}
            </select>
          }/>
        <table className="tbl feature">
          <thead><tr>
            <th style={{width:32}}><input type="checkbox"/></th>
            <th>Company</th>
            <th>Type</th>
            <th>Default location</th>
            <th className="num">Users</th>
            {CloudGate.isAdmin() && <th>Modified</th>}
            <th style={{width:90}}></th>
          </tr></thead>
          <tbody>
            {filtered.map(r => {
              const type = CloudGate.DB.CompanyTypes.find(t => t.Id === r.CompanyTypeId);
              const loc = CloudGate.DB.Locations.find(l => l.Id === r.LocationId);
              const userCount = CloudGate.DB.Users.filter(u => u.CompanyId === r.Id).length;
              const tone = type?.CompanyTypeName === 'Customer' ? 'brand' : type?.CompanyTypeName === 'Supplier' ? 'cyan' : 'pink';
              return (
                <tr key={r.Id}>
                  <td><input type="checkbox"/></td>
                  <td>
                    <div className="cell-id">
                      <div className="cell-avatar" style={{background: gradFor(r.Name)}}>{initialsOf(r.Name)}</div>
                      <div className="meta">
                        <div className="name">{r.Name}</div>
                        {CloudGate.isAdmin() && <div className="sub">ID #{r.Id}</div>}
                      </div>
                    </div>
                  </td>
                  <td><Pill tone={tone}>{type?.CompanyTypeName || '—'}</Pill></td>
                  <td style={{fontSize:13}}>{loc ? <span><span style={{fontFamily:'var(--mono)', fontSize:11.5, color:'var(--text-muted)'}}>{loc.code} · </span>{loc.Name}</span> : '—'}</td>
                  <td className="num">{userCount}</td>
                  {CloudGate.isAdmin() && <td><AuditCell modified={r.Modified}/></td>}
                  <td>{CloudGate.canEdit() && <RowActions onEdit={() => setEditing(r)} onDelete={() => remove(r.Id)}/>}</td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
      {(editing || showNew) && <CompanyDrawer row={editing} onClose={() => { setEditing(null); setShowNew(false); }} onSave={save}/>}
    </div>
  );
}

function CompanyDrawer({ row, onClose, onSave }) {
  // For an existing Company, pickers should only show that Company's own
  // Locations.  For a new one (no Id yet) the Default-location picker has no
  // sensible scope, so we render it disabled until the Company itself is
  // saved.
  const ownLocations = row?.Id
    ? (CloudGate.DB.Locations || []).filter(l => l.CompanyId === row.Id)
    : [];
  const [form, setForm] = useState6(row || { Name:'', CompanyTypeId: 1,
                                              TenantId: window.__currentUser?.tenantId,
                                              LocationId: null });
  // Only a SystemAdmin can change a Company's Tenant (cross-tenant reassignment).
  // Other roles see the Tenant as read-only text or not at all.
  const isSysAdmin = window.__currentUser?.role === 'SystemAdmin';
  const tenants    = CloudGate.DB.Tenants || [];
  const tenantName = tenants.find(t => t.Id === form.TenantId)?.TenantName ?? '—';
  return (
    <Drawer title={form.Name || 'New company'} subtitle={row ? 'Edit company' : 'New company'} onClose={onClose} onSave={() => onSave(form)} saveLabel={row ? 'Save changes' : 'Create company'}>
      <TextField label="Name" value={form.Name} onChange={v => setForm({...form, Name:v})} required maxLength={256}/>
      <FieldRow>
        <SelectField label="Company type" value={form.CompanyTypeId} onChange={v => setForm({...form, CompanyTypeId:+v})} required
          options={CloudGate.DB.CompanyTypes.map(t => ({ value: t.Id, label: t.CompanyTypeName }))}/>
        <SelectField label="Default location" value={form.LocationId ?? ''}
          onChange={v => setForm({...form, LocationId: v === '' ? null : +v})}
          options={[{ value:'', label: row?.Id ? '— none —' : '— save company first —' },
                    ...ownLocations.map(l => ({ value: l.Id, label: l.Name }))]}
          hint={row?.Id ? null : 'Default location can be set after the Company is created.'}/>
      </FieldRow>
      {isSysAdmin ? (
        <SelectField label="Tenant" value={form.TenantId ?? ''}
          onChange={v => setForm({...form, TenantId: v === '' ? null : +v})}
          options={tenants.map(t => ({ value: t.Id, label: t.TenantName }))}
          hint="Only System administrators can reassign a Company to a different Tenant."/>
      ) : (
        <div className="field">
          <label>Tenant</label>
          <div style={{padding:'8px 10px', background:'var(--surface-2)', border:'1px solid var(--border)', borderRadius:6, fontSize:13, color:'var(--text-muted)'}}>
            {tenantName}
            <span style={{marginLeft:8, fontSize:11}}>· read-only (System administrator only)</span>
          </div>
        </div>
      )}
      <CustomFieldsSection entityName="Company" entityId={row?.Id}/>
    </Drawer>
  );
}

// =================== USERS ===================
function UsersPage() {
  const [rows, setRows] = useState6(CloudGate.byActiveCompany(CloudGate.DB.Users));
  const [q, setQ] = useState6('');
  const [levelFilter, setLevelFilter] = useState6('all');
  const [companyFilter, setCompanyFilter] = useState6('all');
  const [editing, setEditing] = useState6(null);
  const [showNew, setShowNew] = useState6(false);

  const filtered = rows.filter(r =>
    (!q || r.UserName.toLowerCase().includes(q.toLowerCase()) || r.Email.toLowerCase().includes(q.toLowerCase())) &&
    (levelFilter === 'all' || r.UserLevelId === +levelFilter) &&
    (companyFilter === 'all' || r.CompanyId === +companyFilter)
  );

  const save = async (row) => {
    const saved = await CloudGate.apiSave('users', row);
    if (!saved) return;
    setRows(rs => row.Id ? rs.map(r => r.Id === saved.Id ? saved : r) : [...rs, saved]);
    CloudGate.DB.Users = row.Id
      ? CloudGate.DB.Users.map(r => r.Id === saved.Id ? saved : r)
      : [...CloudGate.DB.Users, saved];
    setEditing(null); setShowNew(false);
  };
  const remove = async (id) => {
    if (!await CloudGate.apiDelete('users', id)) return;
    setRows(rs => rs.filter(r => r.Id !== id));
    CloudGate.DB.Users = CloudGate.DB.Users.filter(r => r.Id !== id);
  };

  return (
    <div className="page">
      <PageHeader title="Users" sub="Accounts, roles and company assignments." onNew={() => setShowNew(true)} newLabel="New user" onExport={() => {}}/>
      <div className="card">
        <CrudToolbar q={q} onQ={setQ} placeholder="Search by username or email…" count={filtered.length} total={rows.length}
          filters={<>
            <select className="select" value={levelFilter} onChange={e => setLevelFilter(e.target.value)}>
              <option value="all">All levels</option>
              {CloudGate.DB.UserLevels.map(l => <option key={l.Id} value={l.Id}>{l.Level}</option>)}
            </select>
            <select className="select" value={companyFilter} onChange={e => setCompanyFilter(e.target.value)}>
              <option value="all">All companies</option>
              {CloudGate.visibleCompanies().map(c => <option key={c.Id} value={c.Id}>{c.Name}</option>)}
            </select>
          </>}/>
        <table className="tbl feature">
          <thead><tr>
            <th style={{width:32}}><input type="checkbox"/></th>
            <th>User</th>
            <th>Email</th>
            <th>Level</th>
            <th>Company</th>
            {CloudGate.isAdmin() && <th>Modified</th>}
            <th style={{width:90}}></th>
          </tr></thead>
          <tbody>
            {filtered.map(r => {
              const level = CloudGate.DB.UserLevels.find(l => l.Id === r.UserLevelId);
              const company = CloudGate.DB.Companies.find(c => c.Id === r.CompanyId);
              const tone = level?.Level === 'SystemAdmin' ? 'err' : level?.Level === 'CustomerAdmin' ? 'brand' : level?.Level === 'Operator' ? 'info' : 'default';
              return (
                <tr key={r.Id}>
                  <td><input type="checkbox"/></td>
                  <td>
                    <div className="cell-id">
                      <div className="cell-avatar" style={{background: gradFor(r.UserName)}}>{initialsOf(r.UserName.replace('.', ' '))}</div>
                      <div className="meta">
                        <div className="name">{r.UserName}</div>
                        {CloudGate.isAdmin() && <div className="sub">ID #{r.Id}</div>}
                      </div>
                    </div>
                  </td>
                  <td style={{fontFamily:'var(--mono)', fontSize:12}}>{r.Email}</td>
                  <td><Pill tone={tone}>{level?.Level || '—'}</Pill></td>
                  <td>{company?.Name || '—'}</td>
                  {CloudGate.isAdmin() && <td><AuditCell modified={r.Modified}/></td>}
                  <td>{CloudGate.canEdit() && <RowActions onEdit={() => setEditing(r)} onDelete={() => remove(r.Id)}/>}</td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
      {(editing || showNew) && <UserDrawer row={editing} onClose={() => { setEditing(null); setShowNew(false); }} onSave={save}/>}
    </div>
  );
}

function UserDrawer({ row, onClose, onSave }) {
  // New users default to the active Company (the one currently selected in
  // the topbar).  The Company picker is restricted to the set the current
  // user is allowed to see — TenantAdmins can move a user across companies
  // within their tenant, lower roles see only their own.
  const visibleCos = CloudGate.visibleCompanies();
  const defaultCo  = visibleCos[0]?.Id;
  const [form, setForm] = useState6(row || { UserName:'', Email:'', CompanyId: defaultCo, UserLevelId: 3 });
  const [pw, setPw] = useState6('');

  // For an EXISTING user the Username is shown as plain text (NOT an <input>),
  // and renaming goes through a browser prompt() — NOT a revealed text field.
  // The reason: this user's password manager autofills the saved login into
  // ANY username <input> the moment it appears in the DOM (even on-demand),
  // overriding autocomplete/readonly/type tricks.  A prompt() dialog is not a
  // page field, so the manager can't touch it.  New users still type directly.
  const doRename = () => {
    const next = window.prompt('Enter the new username:', form.UserName);
    if (next == null) return;                 // cancelled
    const trimmed = next.trim();
    if (trimmed && trimmed !== form.UserName) setForm({ ...form, UserName: trimmed });
  };

  // Guard against silently renaming an EXISTING user — the usual culprit is a
  // password manager autofilling a saved login into this form (which renamed
  // Admin → Viewer2).  A user renaming THEMSELVES is allowed without a prompt.
  const handleSave = () => {
    if (row && form.UserName !== row.UserName) {
      const isSelf = window.__currentUser?.id != null && window.__currentUser.id === row.Id;
      if (!isSelf && !window.confirm(
            `Change this user's username from "${row.UserName}" to "${form.UserName}"?\n\n` +
            `If you didn't intend this, it may be browser / password-manager autofill — click Cancel.`)) {
        return;
      }
    }
    onSave(pw ? { ...form, Password: pw } : form);
  };

  return (
    <Drawer title={form.UserName || 'New user'} subtitle={row ? 'Edit user' : 'New user'} onClose={onClose} onSave={handleSave} saveLabel={row ? 'Save changes' : 'Create user'}>
      <FieldRow>
        {/* Existing user: Username is read-only text + a Rename button that opens
            a prompt() — there is never a username <input> in the page for a
            password manager to autofill.  New users type directly. */}
        {row ? (
          <div className="field">
            <label>Username <span style={{color:'var(--err)'}}>*</span></label>
            <div style={{display:'flex', alignItems:'center', gap:8}}>
              <div className="input" style={{flex:1, minWidth:0, display:'flex', alignItems:'center', cursor:'default'}}>{form.UserName}</div>
              <button type="button" className="btn" onClick={doRename}
                      style={{height:32, padding:'0 12px', whiteSpace:'nowrap'}}>Rename</button>
            </div>
          </div>
        ) : (
          <TextField label="Username" value={form.UserName} onChange={v => setForm({...form, UserName:v})} required maxLength={128} noAutofill/>
        )}
        <TextField label="Email" value={form.Email} onChange={v => setForm({...form, Email:v})} required maxLength={256} type="email" noAutofill/>
      </FieldRow>
      <FieldRow>
        <SelectField label="Company" value={form.CompanyId} onChange={v => setForm({...form, CompanyId:+v})} required
          options={visibleCos.map(c => ({ value: c.Id, label: c.Name }))}/>
        <SelectField label="User level" value={form.UserLevelId} onChange={v => setForm({...form, UserLevelId:+v})} required
          options={CloudGate.DB.UserLevels.map(l => ({ value: l.Id, label: l.Level }))}/>
      </FieldRow>
      <TextField label={row ? 'New password (leave blank to keep)' : 'Password'} value={pw} onChange={setPw} type="password" required={!row} hint="Hashed with BCrypt on save."/>
      <CustomFieldsSection entityName="User" entityId={row?.Id}/>
    </Drawer>
  );
}

window.LocationTypesPage = LocationTypesPage;
window.LookupsPage = LookupsPage;
window.CompaniesPage = CompaniesPage;
window.UsersPage = UsersPage;
