/* Sites screen — org-admin facing list + create. Restores the
   add/manage-sites affordance Sarah flagged as missing (bug
   85ae5e93). Reuses /api/auth/sites — GET returns the user's org's
   sites with zone counts, POST creates a new site, PUT/DELETE edit
   and remove (scoped to the caller's org). Each card links into the
   existing per-site drilldown at #site/<id>. */

function SitesScreen() {
  const [sites, setSites] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const [addOpen, setAddOpen] = useState(false);
  const [reloadTick, setReloadTick] = useState(0);

  const canManage = Auth && Auth.canManageOrg && Auth.canManageOrg();

  useEffect(() => {
    let cancelled = false;
    setLoading(true);
    apiFetch('/api/auth/sites')
      .then((r) => {
        if (cancelled) return;
        setSites(r.sites || []);
        setLoading(false);
      })
      .catch((err) => {
        if (cancelled) return;
        setError(err.message);
        setLoading(false);
      });
    return () => { cancelled = true; };
  }, [reloadTick]);

  function refresh() { setReloadTick((n) => n + 1); }

  return (
    <div className="aq-content">
      <div className="aq-content-inner" style={{ maxWidth: 1400 }}>
        <section className="aq-hero">
          <div style={{ display: 'flex', alignItems: 'flex-end', gap: 12, justifyContent: 'space-between', flexWrap: 'wrap' }}>
            <div>
              <h1>Sites</h1>
            </div>
            {canManage && (
              <button
                type="button"
                className="aq-icon-btn"
                onClick={() => setAddOpen(true)}
                title="Add site"
                aria-label="Add site"
              >
                <Icon name="plus" size={15} />
              </button>
            )}
          </div>
        </section>

        {loading && (
          <div style={{ padding: 60, textAlign: 'center', color: 'var(--aq-text-faint)' }}>
            Loading sites…
          </div>
        )}
        {error && (
          <div style={{
            padding: '10px 14px',
            background: 'color-mix(in srgb, var(--aq-danger) 12%, transparent)',
            border: '1px solid color-mix(in srgb, var(--aq-danger) 30%, transparent)',
            borderRadius: 6, color: 'var(--aq-danger)', fontSize: 12,
          }}>{error}</div>
        )}

        {!loading && !error && sites.length === 0 && (
          <div style={{
            padding: '60px 24px', textAlign: 'center',
            color: 'var(--aq-text-faint)', fontSize: 13,
            display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8,
          }}>
            <Icon name="building" size={28} />
            <div style={{ fontSize: 14, color: 'var(--aq-text)', fontFamily: 'var(--aq-ff-display)' }}>
              No sites yet
            </div>
            <div style={{ maxWidth: 420, fontSize: 12.5 }}>
              Add the first aquarium location for your organisation. Sites carry
              zones, screens, and the species that appear on them.
            </div>
            {canManage && (
              <button
                type="button"
                className="aq-btn-primary"
                style={{ marginTop: 6 }}
                onClick={() => setAddOpen(true)}
              >
                <Icon name="plus" size={13} />
                <span>Add site</span>
              </button>
            )}
          </div>
        )}

        {!loading && !error && sites.length > 0 && (
          <section style={{
            display: 'grid', gap: 12,
            gridTemplateColumns: 'repeat(auto-fill, minmax(260px, 1fr))',
            marginTop: 18,
          }}>
            {sites.map((s) => (
              <article
                key={s.id}
                onClick={() => { window.location.hash = `#site/${s.id}`; }}
                style={{
                  /* Same card surface as the dashboard / org cards. */
                  background: 'var(--aq-surface-grad), var(--aq-surface)',
                  border: '1px solid var(--aq-line)',
                  borderRadius: 'var(--aq-r-lg)',
                  boxShadow: 'var(--aq-shadow-1), var(--aq-edge-top)',
                  padding: 14,
                  cursor: 'pointer',
                  display: 'flex', flexDirection: 'column', gap: 8,
                  transition: 'border-color var(--aq-d-1) var(--aq-ease), transform var(--aq-d-1) var(--aq-ease)',
                }}
                onMouseEnter={(e) => { e.currentTarget.style.borderColor = 'var(--aq-line-bright)'; e.currentTarget.style.transform = 'translateY(-1px)'; }}
                onMouseLeave={(e) => { e.currentTarget.style.borderColor = 'var(--aq-line)'; e.currentTarget.style.transform = 'none'; }}
              >
                <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                  <div style={{
                    /* Muted monochrome disc — no accent chroma, matches the
                       org avatars. */
                    width: 32, height: 32, borderRadius: 8,
                    background: 'rgba(255,255,255,0.07)',
                    color: 'rgba(255,255,255,0.72)',
                    border: '1px solid rgba(255,255,255,0.08)',
                    display: 'grid', placeItems: 'center', flexShrink: 0,
                  }}>
                    <Icon name="building" size={14} />
                  </div>
                  <div style={{ minWidth: 0, flex: 1 }}>
                    <div style={{
                      fontFamily: 'var(--aq-ff-display)', fontSize: 14,
                      fontWeight: 500, color: 'var(--aq-text)',
                      whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
                    }}>{s.name}</div>
                    <div style={{ fontSize: 11, color: 'var(--aq-text-faint)' }}>
                      {s.city || s.country || s.timezone || 'No location set'}
                    </div>
                  </div>
                </div>
                <div style={{
                  display: 'flex', gap: 14, fontSize: 11.5,
                  color: 'var(--aq-text-dim)',
                }}>
                  <span><strong style={{ color: 'var(--aq-text)' }}>{Number(s.zone_count) || 0}</strong> zone{Number(s.zone_count) === 1 ? '' : 's'}</span>
                  {s.timezone && <span>· {s.timezone}</span>}
                </div>
              </article>
            ))}
          </section>
        )}

        <AddSiteModal
          open={addOpen}
          onClose={() => setAddOpen(false)}
          onCreated={() => { setAddOpen(false); refresh(); }}
        />
      </div>
    </div>
  );
}

/* Add-site modal — minimal form (name + city + timezone). Slug is
   derived server-side from the name. POSTs to /api/auth/sites which
   is capability-gated to settings.org (org_admin + aquaos_admin). */
// ── Reference lists for the Add Site picker ─────────────────────────────
// ISO 3166-1 country list. Curated to ~75 most-likely candidates with a
// final "Other" option falling back to free-text. Keeps the dropdown
// short enough to scroll while covering every aquarium-bearing nation
// we'd plausibly serve. Order: alphabetical by display name.
const COUNTRY_OPTIONS = [
  ['AU', 'Australia'], ['NZ', 'New Zealand'], ['US', 'United States'],
  ['CA', 'Canada'], ['GB', 'United Kingdom'], ['IE', 'Ireland'],
  ['FR', 'France'], ['DE', 'Germany'], ['ES', 'Spain'], ['PT', 'Portugal'],
  ['IT', 'Italy'], ['NL', 'Netherlands'], ['BE', 'Belgium'], ['CH', 'Switzerland'],
  ['AT', 'Austria'], ['DK', 'Denmark'], ['SE', 'Sweden'], ['NO', 'Norway'],
  ['FI', 'Finland'], ['IS', 'Iceland'], ['PL', 'Poland'], ['CZ', 'Czechia'],
  ['HU', 'Hungary'], ['GR', 'Greece'], ['TR', 'Türkiye'], ['IL', 'Israel'],
  ['AE', 'United Arab Emirates'], ['SA', 'Saudi Arabia'], ['QA', 'Qatar'],
  ['KW', 'Kuwait'], ['BH', 'Bahrain'], ['OM', 'Oman'], ['EG', 'Egypt'],
  ['ZA', 'South Africa'], ['KE', 'Kenya'], ['MA', 'Morocco'], ['TN', 'Tunisia'],
  ['NG', 'Nigeria'], ['IN', 'India'], ['LK', 'Sri Lanka'], ['MV', 'Maldives'],
  ['BD', 'Bangladesh'], ['TH', 'Thailand'], ['VN', 'Vietnam'], ['MY', 'Malaysia'],
  ['SG', 'Singapore'], ['ID', 'Indonesia'], ['PH', 'Philippines'], ['JP', 'Japan'],
  ['KR', 'South Korea'], ['CN', 'China'], ['HK', 'Hong Kong'], ['TW', 'Taiwan'],
  ['MX', 'Mexico'], ['CR', 'Costa Rica'], ['PA', 'Panama'], ['CO', 'Colombia'],
  ['EC', 'Ecuador'], ['PE', 'Peru'], ['CL', 'Chile'], ['AR', 'Argentina'],
  ['BR', 'Brazil'], ['UY', 'Uruguay'], ['BS', 'Bahamas'], ['JM', 'Jamaica'],
  ['DO', 'Dominican Republic'], ['CU', 'Cuba'], ['FJ', 'Fiji'],
  ['PG', 'Papua New Guinea'],
].sort((a, b) => a[1].localeCompare(b[1]));

// IANA timezone list — Intl.supportedValuesOf is supported by every
// browser Slate targets (Chrome 99+, Safari 15.4+, Firefox 93+). The
// fallback string covers the rare unsupported runtime so the modal
// can still be submitted with a sensible default.
function getTimezones() {
  try {
    if (typeof Intl.supportedValuesOf === 'function') {
      return Intl.supportedValuesOf('timeZone');
    }
  } catch (_) { /* fall through */ }
  return [
    'UTC', 'Australia/Sydney', 'Australia/Melbourne', 'Australia/Perth',
    'Pacific/Auckland', 'America/Los_Angeles', 'America/New_York', 'America/Chicago',
    'America/Denver', 'America/Toronto', 'Europe/London', 'Europe/Paris',
    'Europe/Berlin', 'Europe/Madrid', 'Asia/Tokyo', 'Asia/Singapore',
    'Asia/Dubai', 'Asia/Kolkata', 'Africa/Johannesburg',
  ];
}

function browserTimezone() {
  try { return Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC'; }
  catch (_) { return 'UTC'; }
}

function AddSiteModal({ open, onClose, onCreated }) {
  const [name, setName] = useState('');
  const [city, setCity] = useState('');
  const [country, setCountry] = useState('');
  const [timezone, setTimezone] = useState(() => browserTimezone());
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState(null);

  // Snapshot the timezone list once per mount — Intl.supportedValuesOf
  // is cheap but no need to recompute on every render.
  const timezones = useMemo(() => getTimezones(), []);

  useEffect(() => {
    if (!open) {
      setName(''); setCity(''); setCountry('');
      setTimezone(browserTimezone());
      setBusy(false); setErr(null);
    }
  }, [open]);

  if (!open) return null;

  async function submit() {
    setErr(null);
    if (!name.trim()) { setErr('Site name is required.'); return; }
    if (!country) { setErr('Pick a country.'); return; }
    // Guard the timezone — IANA value must be in the list. Lets the
    // user freely paste but rejects obvious typos before they reach
    // the server (which doesn't validate).
    if (!timezones.includes(timezone)) {
      setErr(`"${timezone}" isn't a valid IANA timezone. Pick one from the list.`);
      return;
    }
    setBusy(true);
    try {
      await apiFetch('/api/auth/sites', {
        method: 'POST',
        body: JSON.stringify({
          name: name.trim(),
          location: city.trim() || null,
          country: country || null,
          timezone: timezone || 'UTC',
        }),
      });
      if (onCreated) onCreated();
    } catch (e) {
      setErr(e.message);
    } finally {
      setBusy(false);
    }
  }

  return (
    <div
      onClick={(e) => { if (e.target === e.currentTarget && !busy) onClose(); }}
      style={{
        position: 'fixed', inset: 0, zIndex: 200,
        background: 'rgba(6, 7, 10, 0.78)', backdropFilter: 'blur(6px)',
        display: 'grid', placeItems: 'center', padding: 24,
      }}
    >
      <div style={{
        width: 'min(480px, 100%)',
        background: 'var(--aq-surface)',
        border: '1px solid var(--aq-line)',
        borderRadius: 14,
        display: 'flex', flexDirection: 'column', overflow: 'hidden',
      }}>
        <header style={{
          padding: '14px 18px', borderBottom: '1px solid var(--aq-line)',
          display: 'flex', alignItems: 'center', gap: 12,
        }}>
          <div style={{
            width: 28, height: 28, borderRadius: 8,
            background: 'var(--aq-accent-soft)', color: 'var(--aq-accent)',
            display: 'grid', placeItems: 'center',
          }}><Icon name="building" size={14} /></div>
          <div style={{ flex: 1 }}>
            <div style={{
              fontFamily: 'var(--aq-ff-display)', fontSize: 14,
              fontWeight: 500, color: 'var(--aq-text)',
            }}>Add site</div>
            <div style={{ fontSize: 11.5, color: 'var(--aq-text-faint)' }}>
              A new aquarium location in your organisation.
            </div>
          </div>
          <button
            className="aq-icon-btn"
            onClick={onClose}
            disabled={busy}
            aria-label="Close"
          ><Icon name="close" size={13} /></button>
        </header>

        <div style={{ padding: 18, display: 'flex', flexDirection: 'column', gap: 12 }}>
          <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 12, color: 'var(--aq-text-dim)' }}>
            <span>Name <span style={{ color: 'var(--aq-danger)' }}>*</span></span>
            <input
              value={name}
              onChange={(e) => setName(e.target.value)}
              placeholder="e.g. Harbor Bay Aquarium"
              autoFocus
              style={{
                padding: '8px 10px',
                background: 'var(--aq-surface-2)',
                border: '1px solid var(--aq-line)',
                borderRadius: 6, color: 'var(--aq-text)',
                font: 'inherit', fontSize: 13, outline: 0,
              }}
            />
          </label>
          <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 12, color: 'var(--aq-text-dim)' }}>
            <span>Country <span style={{ color: 'var(--aq-danger)' }}>*</span></span>
            <select
              value={country}
              onChange={(e) => setCountry(e.target.value)}
              style={{
                padding: '8px 10px',
                background: 'var(--aq-surface-2)',
                border: '1px solid var(--aq-line)',
                borderRadius: 6, color: 'var(--aq-text)',
                font: 'inherit', fontSize: 13, outline: 0,
              }}
            >
              <option value="">— select a country —</option>
              {COUNTRY_OPTIONS.map(([code, label]) => (
                <option key={code} value={code}>{label}</option>
              ))}
            </select>
          </label>
          <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 12, color: 'var(--aq-text-dim)' }}>
            <span>City <span style={{ color: 'var(--aq-text-faint)' }}>(optional)</span></span>
            <input
              value={city}
              onChange={(e) => setCity(e.target.value)}
              placeholder="e.g. San Francisco"
              style={{
                padding: '8px 10px',
                background: 'var(--aq-surface-2)',
                border: '1px solid var(--aq-line)',
                borderRadius: 6, color: 'var(--aq-text)',
                font: 'inherit', fontSize: 13, outline: 0,
              }}
            />
          </label>
          <label style={{ display: 'flex', flexDirection: 'column', gap: 4, fontSize: 12, color: 'var(--aq-text-dim)' }}>
            <span>Timezone <span style={{ color: 'var(--aq-danger)' }}>*</span></span>
            {/* IANA picker. Native <select> over a datalist so the
                value can only be one of the supported zones — the
                backend stores it verbatim, so a typo would silently
                break time-of-day comparisons. ~400 zones is OK in a
                <select> on every browser we target. The browser's
                detected zone is pre-selected so the common case is
                zero clicks. */}
            <select
              value={timezone}
              onChange={(e) => setTimezone(e.target.value)}
              style={{
                padding: '8px 10px',
                background: 'var(--aq-surface-2)',
                border: '1px solid var(--aq-line)',
                borderRadius: 6, color: 'var(--aq-text)',
                font: 'inherit', fontSize: 13, outline: 0,
              }}
            >
              {timezones.map((tz) => (
                <option key={tz} value={tz}>{tz}</option>
              ))}
            </select>
            <span style={{ fontSize: 10.5, color: 'var(--aq-text-faint)' }}>
              Defaults to your browser timezone — change if the site is in a different region.
            </span>
          </label>
          {err && (
            <div style={{
              padding: '8px 10px',
              background: 'color-mix(in srgb, var(--aq-danger) 12%, transparent)',
              border: '1px solid color-mix(in srgb, var(--aq-danger) 30%, transparent)',
              borderRadius: 6, color: 'var(--aq-danger)', fontSize: 11.5,
            }}>{err}</div>
          )}
        </div>

        <footer style={{
          padding: '12px 18px', borderTop: '1px solid var(--aq-line)',
          background: 'var(--aq-surface-2)',
          display: 'flex', justifyContent: 'flex-end', gap: 8,
        }}>
          <button
            onClick={onClose}
            disabled={busy}
            style={{
              padding: '7px 12px', fontSize: 12,
              background: 'transparent', border: '1px solid var(--aq-line)',
              color: 'var(--aq-text-dim)', borderRadius: 7, cursor: busy ? 'wait' : 'pointer',
            }}
          >Cancel</button>
          <button
            onClick={submit}
            disabled={busy || !name.trim()}
            className="aq-btn-primary"
            style={{ opacity: (busy || !name.trim()) ? 0.5 : 1 }}
          >
            <Icon name="plus" size={13} />
            {busy ? 'Adding…' : 'Add site'}
          </button>
        </footer>
      </div>
    </div>
  );
}

window.SitesScreen = SitesScreen;
