// frontend/src/pages/crm/mail/MailPage.jsx

import { useState, useEffect, useCallback, useMemo, useRef } from 'react'
import { Link } from 'react-router-dom'
import api from '@/lib/api'
import PageHeader from '@/components/ui/PageHeader'
import Button from '@/components/ui/Button'
import Spinner from '@/components/ui/Spinner'
import SearchBar from '@/components/ui/SearchBar'
import SegmentedControl from '@/components/ui/SegmentedControl'
import IconButtonGroup from '@/components/ui/IconButtonGroup'
import { useToast } from '@/components/ui/Toast'
import ComposeEmailModal from '@/modals/crm/ComposeEmailModal'
import MailViewModal from '@/modals/crm/MailViewModal'
import MailSettingsModal from '@/modals/crm/MailSettingsModal'
import { fmtRelative, fmtDateTimeFull } from '@/lib/formatters'

// ─── helpers ────────────────────────────────────────────────────────────────

const DEFAULT_POLL_INTERVAL = 30

function getPollInterval() {
  const v = parseInt(localStorage.getItem('mail_poll_interval'), 10)
  return !isNaN(v) && v >= 15 && v <= 300 ? v : DEFAULT_POLL_INTERVAL
}

function relativeTime(dateStr) { return fmtRelative(dateStr) }
function fullDate(dateStr) { return fmtDateTimeFull(dateStr) }

// ─── SVG icons ───────────────────────────────────────────────────────────────

const IconRefresh = () => (
  <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
    <path d="M23 4v6h-6"/><path d="M1 20v-6h6"/>
    <path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/>
  </svg>
)

const IconSettings = () => (
  <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
    <circle cx="12" cy="12" r="3"/>
    <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/>
  </svg>
)

const IconDownload = () => (
  <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
    <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
    <polyline points="7 10 12 15 17 10"/>
    <line x1="12" y1="15" x2="12" y2="3"/>
  </svg>
)

function BookmarkIcon({ active }) {
  return (
    <svg width="14" height="14" viewBox="0 0 24 24"
      fill={active ? 'var(--color-warning)' : 'none'}
      stroke={active ? 'var(--color-warning)' : 'var(--color-text-muted)'}
      strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z" />
    </svg>
  )
}

// ─── filter option definitions (with color tokens) ───────────────────────────

const DIR_OPTIONS = (unreadCount) => [
  {
    value: 'inbound',
    label: unreadCount > 0 ? `Inbox (${unreadCount})` : 'Inbox',
    activeBg:   'var(--mail-filter-inbox-bg)',
    activeText: 'var(--mail-filter-inbox-text)',
  },
  {
    value: 'outbound',
    label: 'Sent',
    activeBg:   'var(--mail-filter-sent-bg)',
    activeText: 'var(--mail-filter-sent-text)',
  },
]

const CLIENT_OPTIONS = [
  {
    value: 'all',
    label: 'All Messages',
    activeBg:   'var(--mail-filter-all-bg)',
    activeText: 'var(--mail-filter-all-text)',
  },
  {
    value: 'clients',
    label: 'Clients Only',
    activeBg:   'var(--mail-filter-clients-bg)',
    activeText: 'var(--mail-filter-clients-text)',
  },
]

const MAILBOX_OPTIONS = [
  {
    value: 'sales',
    label: 'Sales',
    activeBg:   'var(--mail-filter-sales-bg)',
    activeText: 'var(--mail-filter-sales-text)',
  },
  {
    value: 'support',
    label: 'Support',
    activeBg:   'var(--mail-filter-support-bg)',
    activeText: 'var(--mail-filter-support-text)',
  },
  {
    value: 'both',
    label: 'All',
    activeBg:   'var(--mail-filter-both-bg)',
    activeText: 'var(--mail-filter-both-text)',
  },
]

const READ_OPTIONS = [
  {
    value: 'all',
    label: 'All',
    activeBg:   'var(--mail-filter-all-bg)',
    activeText: 'var(--mail-filter-all-text)',
  },
  {
    value: 'unread',
    label: 'Unread',
    activeBg:   'var(--mail-filter-unread-bg)',
    activeText: 'var(--mail-filter-unread-text)',
  },
  {
    value: 'read',
    label: 'Read',
    activeBg:   'var(--mail-filter-read-bg)',
    activeText: 'var(--mail-filter-read-text)',
  },
  {
    value: 'important',
    label: 'Bookmarked',
    activeBg:   'var(--mail-filter-bookmarked-bg)',
    activeText: 'var(--mail-filter-bookmarked-text)',
  },
]

// ─── MailRow ─────────────────────────────────────────────────────────────────

function MailRow({ entry, customer, selected, onSelect, onClick, onBookmark }) {
  const isUnread   = entry.direction === 'inbound' && !entry.is_read
  const isSelected = selected

  return (
    <div
      onClick={() => onClick(entry)}
      className="mail-row"
      style={{
        display: 'grid',
        gridTemplateColumns: '20px 32px 220px 1fr 8px 140px',
        alignItems: 'center',
        gap: 'var(--space-3)',
        padding: 'var(--space-4) var(--space-5)',
        borderBottom: '1px solid var(--color-border)',
        backgroundColor: isSelected
          ? 'var(--color-primary-subtle)'
          : isUnread
            ? 'color-mix(in srgb, var(--color-bg-elevated) 50%, var(--color-bg-surface))'
            : 'transparent',
        cursor: 'pointer',
        transition: 'background-color 0.12s',
        minHeight: '68px',
      }}
    >
      {/* Checkbox */}
      <div
        onClick={(e) => { e.stopPropagation(); onSelect(entry.id) }}
        style={{ display: 'flex', alignItems: 'center' }}
      >
        <div style={{
          width: 16, height: 16,
          borderRadius: 'var(--radius-sm)',
          border: `1.5px solid ${isSelected ? 'var(--color-primary)' : 'var(--color-border-strong)'}`,
          backgroundColor: isSelected ? 'var(--color-primary)' : 'transparent',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          flexShrink: 0, transition: 'all 0.12s',
        }}>
          {isSelected && (
            <svg width="10" height="10" viewBox="0 0 10 10" fill="none">
              <path d="M1.5 5L4 7.5L8.5 2.5" stroke="var(--color-text-inverse)" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
          )}
        </div>
      </div>

      {/* Bookmark */}
      <div
        className="mail-bookmark-btn"
        onClick={(e) => { e.stopPropagation(); onBookmark(entry) }}
        title={entry.is_important ? 'Remove bookmark' : 'Bookmark'}
        style={{
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          cursor: 'pointer', opacity: entry.is_important ? 1 : 0.3,
          transition: 'opacity 0.15s',
        }}
      >
        <BookmarkIcon active={!!entry.is_important} />
      </div>

      {/* Sender / recipient */}
      <div style={{ minWidth: 0 }}>
        {customer ? (
          <Link
            to={`/crm/customers/${customer.id}`}
            onClick={(e) => e.stopPropagation()}
            style={{
              color: isUnread ? 'var(--color-text-primary)' : 'var(--color-text-secondary)',
              fontWeight: isUnread ? 'var(--font-weight-semibold)' : 'var(--font-weight-medium)',
              fontSize: 'var(--font-size-base)',
              textDecoration: 'none',
              display: 'block', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
            }}
          >
            {customer.name}{customer.surname ? ` ${customer.surname}` : ''}
          </Link>
        ) : (
          <span style={{
            color: isUnread ? 'var(--color-text-primary)' : 'var(--color-text-secondary)',
            fontWeight: isUnread ? 'var(--font-weight-semibold)' : 'var(--font-weight-medium)',
            fontSize: 'var(--font-size-base)',
            display: 'block', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
          }}>
            {entry.direction === 'inbound'
              ? (entry.from_addr || 'Unknown sender')
              : (Array.isArray(entry.to_addrs) ? entry.to_addrs[0] : entry.to_addrs || 'Unknown recipient')}
          </span>
        )}
        {customer?.organization && (
          <span style={{
            color: 'var(--color-text-muted)', fontSize: 'var(--font-size-sm)',
            display: 'block', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
          }}>
            {customer.organization}
          </span>
        )}
      </div>

      {/* Subject + snippet */}
      <div style={{ minWidth: 0 }}>
        <span style={{
          color: isUnread ? 'var(--color-text-primary)' : 'var(--color-text-secondary)',
          fontWeight: isUnread ? 'var(--font-weight-medium)' : 'var(--font-weight-normal)',
          fontSize: 'var(--font-size-base)',
          display: 'block', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
        }}>
          {entry.subject || <em style={{ opacity: 0.45 }}>(no subject)</em>}
        </span>
        {entry.body && (
          <span style={{
            color: 'var(--color-text-muted)', fontSize: 'var(--font-size-sm)',
            display: 'block', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
          }}>
            {entry.body.replace(/<[^>]*>/g, '').slice(0, 120)}
          </span>
        )}
      </div>

      {/* Unread dot */}
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        {isUnread && (
          <div style={{
            width: 7, height: 7, borderRadius: 'var(--radius-full)',
            backgroundColor: 'var(--color-primary)', flexShrink: 0,
          }} />
        )}
      </div>

      {/* Time — verbose */}
      <div style={{ textAlign: 'right', flexShrink: 0 }}>
        <span
          title={fullDate(entry.occurred_at)}
          style={{ color: 'var(--color-text-muted)', fontSize: 'var(--font-size-sm)' }}
        >
          {relativeTime(entry.occurred_at)}
        </span>
      </div>
    </div>
  )
}

// ─── main ────────────────────────────────────────────────────────────────────

export default function MailPage() {
  const { toast } = useToast()

  const [entries, setEntries]               = useState([])
  const [customers, setCustomers]           = useState({})
  const [loading, setLoading]               = useState(true)
  const [error, setError]                   = useState('')
  const [dirFilter, setDirFilter]           = useState('inbound')
  const [clientFilter, setClientFilter]     = useState('all')
  const [mailboxFilter, setMailboxFilter]   = useState('both')
  const [readFilter, setReadFilter]         = useState('all')
  const [search, setSearch]                 = useState('')
  const [syncing, setSyncing]               = useState(false)
  const [newMailCount, setNewMailCount]     = useState(0)
  const [bannerVisible, setBannerVisible]   = useState(false)
  const [selected, setSelected]             = useState(new Set())
  const [deleting, setDeleting]             = useState(false)
  const [bulkLoading, setBulkLoading]       = useState(false)
  const [viewEntry, setViewEntry]           = useState(null)
  const [composeOpen, setComposeOpen]       = useState(false)
  const [composeTo, setComposeTo]           = useState('')
  const [composeFromAccount, setComposeFromAccount] = useState('')
  const [settingsOpen, setSettingsOpen]     = useState(false)

  const pollRef = useRef(null)
  const composeOpenRef = useRef(false)

  // ── data ──
  const loadAll = useCallback(async () => {
    setLoading(true); setError('')
    try {
      const [mailData, custsData] = await Promise.all([
        api.get(`/crm/comms/email/all?limit=500&mailbox=${encodeURIComponent(mailboxFilter)}`),
        api.get('/crm/customers'),
      ])
      setEntries(mailData.entries || [])
      const map = {}
      for (const c of custsData.customers || []) map[c.id] = c
      setCustomers(map)
    } catch (err) { setError(err.message) }
    finally { setLoading(false) }
  }, [mailboxFilter])

  useEffect(() => { loadAll() }, [loadAll])
  useEffect(() => { setSelected(new Set()); setReadFilter('all') }, [dirFilter])

  // Keep ref in sync so the interval closure can read it without a dep
  useEffect(() => { composeOpenRef.current = composeOpen }, [composeOpen])

  // ── polling ──
  const startPolling = useCallback(() => {
    if (pollRef.current) clearInterval(pollRef.current)
    pollRef.current = setInterval(async () => {
      if (composeOpenRef.current) return   // pause while composing
      try {
        const data = await api.get('/crm/comms/email/check')
        if (data.new_count > 0) { setNewMailCount(data.new_count); setBannerVisible(true) }
      } catch { /* silent */ }
    }, getPollInterval() * 1000)
  }, [])

  useEffect(() => {
    startPolling()
    return () => { if (pollRef.current) clearInterval(pollRef.current) }
  }, [startPolling])

  // ── actions ──
  const syncEmails = async () => {
    setSyncing(true); setNewMailCount(0); setBannerVisible(false)
    try {
      const data = await api.post('/crm/comms/email/sync', {})
      toast.success('Mail synced', `${data.new_count} new email${data.new_count !== 1 ? 's' : ''} pulled.`)
      await loadAll()
    } catch (err) { toast.danger('Sync failed', err.message) }
    finally { setSyncing(false) }
  }

  const toggleSelect = (id) => setSelected((prev) => {
    const next = new Set(prev)
    if (next.has(id)) next.delete(id); else next.add(id)
    return next
  })

  const deleteSelected = async () => {
    if (!selected.size) return
    setDeleting(true)
    try {
      await api.post('/crm/comms/bulk-delete', { ids: [...selected] })
      toast.success('Deleted', `${selected.size} message${selected.size !== 1 ? 's' : ''} removed.`)
      setSelected(new Set()); await loadAll()
    } catch (err) { toast.danger('Delete failed', err.message) }
    finally { setDeleting(false) }
  }

  const bulkMarkRead = async (read) => {
    if (!selected.size) return
    setBulkLoading(true)
    try {
      await api.post('/crm/comms/bulk-read', { ids: [...selected], read })
      setEntries((prev) => prev.map((e) => selected.has(e.id) ? { ...e, is_read: read } : e))
      toast.success(read ? 'Marked as read' : 'Marked as unread', `${selected.size} message${selected.size !== 1 ? 's' : ''} updated.`)
      setSelected(new Set())
    } catch (err) { toast.danger('Failed', err.message) }
    finally { setBulkLoading(false) }
  }

  const bulkFlag = async () => {
    if (!selected.size) return
    setBulkLoading(true)
    try {
      await api.post('/crm/comms/bulk-important', { ids: [...selected], important: true })
      setEntries((prev) => prev.map((e) => selected.has(e.id) ? { ...e, is_important: true } : e))
      toast.success('Flagged', `${selected.size} message${selected.size !== 1 ? 's' : ''} flagged as important.`)
      setSelected(new Set())
    } catch (err) { toast.danger('Failed', err.message) }
    finally { setBulkLoading(false) }
  }

  const toggleImportant = async (entry) => {
    const newVal = !entry.is_important
    setEntries((prev) => prev.map((e) => e.id === entry.id ? { ...e, is_important: newVal } : e))
    try { await api.patch(`/crm/comms/${entry.id}/important`, { important: newVal }) }
    catch { setEntries((prev) => prev.map((e) => e.id === entry.id ? { ...e, is_important: !newVal } : e)) }
  }

  const openEntry = async (entry) => {
    setViewEntry(entry)
    if (entry.direction === 'inbound' && !entry.is_read) {
      setEntries((prev) => prev.map((e) => e.id === entry.id ? { ...e, is_read: true } : e))
      try { await api.patch(`/crm/comms/${entry.id}/read`, { read: true }) } catch { /* ok */ }
    }
  }

  const openReply = (toAddr, sourceAccount = '') => {
    setViewEntry(null); setComposeTo(toAddr || ''); setComposeFromAccount(sourceAccount || ''); setComposeOpen(true)
  }

  // ── customer email lookup ──
  const customerEmailMap = useMemo(() => {
    const map = {}
    Object.values(customers).forEach((c) => {
      ;(c.contacts || []).forEach((ct) => {
        if (ct?.type === 'email' && ct?.value) map[String(ct.value).toLowerCase()] = c.id
      })
    })
    return map
  }, [customers])

  const resolveCustomer = useCallback((entry) => {
    if (entry.customer_id && customers[entry.customer_id]) return customers[entry.customer_id]
    const candidates = [
      ...(entry.from_addr ? [String(entry.from_addr).toLowerCase()] : []),
      ...(Array.isArray(entry.to_addrs) ? entry.to_addrs : entry.to_addrs ? [entry.to_addrs] : []).map((a) => String(a).toLowerCase()),
    ]
    for (const addr of candidates) {
      if (customerEmailMap[addr]) return customers[customerEmailMap[addr]]
    }
    return null
  }, [customers, customerEmailMap])

  // ── filtering ──
  const q = search.trim().toLowerCase()
  const unreadCount = entries.filter((e) => e.direction === 'inbound' && !e.is_read).length

  const filtered = useMemo(() => {
    let list = entries.filter((e) => e.direction === dirFilter)
    if (clientFilter === 'clients') list = list.filter((e) => !!resolveCustomer(e))
    if (readFilter === 'unread')    list = list.filter((e) => !e.is_read)
    else if (readFilter === 'read') list = list.filter((e) => !!e.is_read)
    else if (readFilter === 'important') list = list.filter((e) => !!e.is_important)
    if (q) list = list.filter((e) => {
      const cust = resolveCustomer(e)
      return (
        (e.subject || '').toLowerCase().includes(q) ||
        (e.body || '').toLowerCase().includes(q) ||
        (e.from_addr || '').toLowerCase().includes(q) ||
        (cust?.name || '').toLowerCase().includes(q) ||
        (cust?.organization || '').toLowerCase().includes(q)
      )
    })
    return list
  }, [entries, dirFilter, clientFilter, readFilter, q, resolveCustomer])

  const anySelected = selected.size > 0

  return (
    <>
      <style>{`
        .mail-row:hover { background-color: var(--color-bg-elevated) !important; }
        .mail-row:hover .mail-bookmark-btn { opacity: 1 !important; }
        /* PageHeader toolbar — icon group matches filter bar height */
        .mail-toolbar .icon-btn-group__btn {
          padding-top: 7px !important;
          padding-bottom: 7px !important;
          line-height: var(--line-height-base) !important;
        }
        /* Filter toolbar — SegmentedControls and SearchBar all same height */
        .mail-filter-bar .seg-ctrl__btn {
          padding-top: var(--space-2) !important;
          padding-bottom: var(--space-2) !important;
        }
        .mail-filter-bar .searchbar-input {
          padding-top: 9px !important;
          padding-bottom: 10px !important;
        }
        /* Bulk-action bar — trim horizontal padding on sm buttons */
        .mail-bulk-bar .btn-sm {
          padding-left: var(--space-2) !important;
          padding-right: var(--space-2) !important;
        }
      `}</style>

      <div className="page-wrapper">
        <PageHeader title="Mailbox" subtitle="Email communications with your customers">
          <div className="mail-toolbar" style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-2)' }}>
            <IconButtonGroup
              size="md"
              buttons={[
                {
                  label: 'Refresh',
                  icon: <IconRefresh />,
                  onClick: loadAll,
                  loading: loading && !syncing,
                },
                {
                  label: 'Download new mail',
                  icon: <IconDownload />,
                  onClick: syncEmails,
                  loading: syncing,
                },
                {
                  label: 'Mail settings',
                  icon: <IconSettings />,
                  onClick: () => setSettingsOpen(true),
                },
              ]}
            />
            <Button
              variant="primary"
              size="md"
              onClick={() => { setComposeTo(''); setComposeFromAccount(''); setComposeOpen(true) }}
            >
              Compose
            </Button>
          </div>
        </PageHeader>

        {/* New mail banner */}
        {bannerVisible && (
          <div style={{
            display: 'flex', alignItems: 'center', justifyContent: 'space-between',
            padding: 'var(--space-3) var(--space-5)',
            backgroundColor: 'var(--color-primary-subtle)',
            border: '1px solid var(--color-primary)',
            borderRadius: 'var(--radius-lg)',
            gap: 'var(--space-3)',
          }}>
            <span style={{ color: 'var(--color-primary)', fontSize: 'var(--font-size-sm)', fontWeight: 'var(--font-weight-medium)' }}>
              {newMailCount} new email{newMailCount !== 1 ? 's' : ''} available — sync to load them.
            </span>
            <div style={{ display: 'flex', gap: 'var(--space-2)' }}>
              <Button variant="primary" size="sm" onClick={syncEmails} loading={syncing}>Sync now</Button>
              <Button variant="ghost" size="sm" onClick={() => setBannerVisible(false)}>Dismiss</Button>
            </div>
          </div>
        )}

        {/* Main card */}
        <div style={{
          backgroundColor: 'rgba(28,32,38,0.30)',
          backdropFilter: 'var(--blur-modal)',
          WebkitBackdropFilter: 'var(--blur-modal)',
          border: '1px solid var(--color-border)',
          borderRadius: 'var(--radius-xl)',
          overflow: 'hidden',
          boxShadow: 'var(--shadow-card)',
          display: 'flex', flexDirection: 'column',
        }}>

          {/* ── Filter toolbar ─────────────────────────────────────── */}
          <div className="mail-filter-bar" style={{
            display: 'flex', alignItems: 'center', flexWrap: 'wrap',
            gap: 'var(--space-3)',
            padding: 'var(--space-4) var(--space-5)',
            borderBottom: '1px solid var(--color-border)',
            backgroundColor: 'rgba(14,18,24,0.45)',
            backdropFilter: 'var(--blur-modal)',
            WebkitBackdropFilter: 'var(--blur-modal)',
          }}>
            {/* 1. Inbox / Sent */}
            <SegmentedControl
              size="md"
              value={dirFilter}
              onChange={setDirFilter}
              options={DIR_OPTIONS(unreadCount)}
            />

            {/* 2. All Messages / Clients Only */}
            <SegmentedControl
              size="md"
              value={clientFilter}
              onChange={setClientFilter}
              options={CLIENT_OPTIONS}
            />

            {/* 3. Sales / Support / All */}
            <SegmentedControl
              size="md"
              value={mailboxFilter}
              onChange={setMailboxFilter}
              options={MAILBOX_OPTIONS}
            />

            {/* 4. Search — fills remaining space, same height as buttons */}
            <div style={{ flex: 1, minWidth: 160 }}>
              <SearchBar value={search} onChange={setSearch} placeholder="Search mail…" className="mail-searchbar" />
            </div>

            {/* 5. All / Unread / Read / Bookmarked */}
            <SegmentedControl
              size="md"
              value={readFilter}
              onChange={setReadFilter}
              options={READ_OPTIONS}
            />
          </div>

          {/* ── Bulk action / count bar ────────────────────────────── */}
          <div className="mail-bulk-bar" style={{
            display: 'flex', alignItems: 'center', justifyContent: 'space-between',
            padding: 'var(--space-2) var(--space-5)',
            borderBottom: '1px solid var(--color-border)',
            minHeight: 40, gap: 'var(--space-3)',
          }}>
            <span style={{ fontSize: 'var(--font-size-sm)', color: 'var(--color-text-muted)', flexShrink: 0 }}>
              {filtered.length} message{filtered.length !== 1 ? 's' : ''}
              {filtered.length < entries.filter((e) => e.direction === dirFilter).length ? ' (filtered)' : ''}
            </span>

            {anySelected ? (
              <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-2)', flexWrap: 'wrap' }}>
                <span style={{ fontSize: 'var(--font-size-sm)', color: 'var(--color-text-muted)' }}>
                  {selected.size} selected
                </span>
                <Button variant="ghost" size="sm" onClick={() => setSelected(new Set())}>Clear</Button>
                <Button variant="secondary" size="sm" onClick={() => bulkMarkRead(true)} loading={bulkLoading}>
                  Mark Read
                </Button>
                <Button variant="secondary" size="sm" onClick={() => bulkMarkRead(false)} loading={bulkLoading}>
                  Mark Unread
                </Button>
                <Button variant="warning" size="sm" onClick={bulkFlag} loading={bulkLoading}>
                  Flag Important
                </Button>
                <Button variant="danger" size="sm" onClick={deleteSelected} loading={deleting}>
                  Delete
                </Button>
              </div>
            ) : filtered.length > 0 ? (
              <Button variant="ghost" size="sm" onClick={() => setSelected(new Set(filtered.map((e) => e.id)))}>
                Select all
              </Button>
            ) : null}
          </div>

          {/* ── Error ──────────────────────────────────────────────── */}
          {error && (
            <div style={{
              margin: 'var(--space-4)',
              padding: 'var(--space-3) var(--space-4)',
              backgroundColor: 'var(--color-danger-bg)',
              border: '1px solid var(--color-danger)',
              borderRadius: 'var(--radius-lg)',
              color: 'var(--color-danger)',
              fontSize: 'var(--font-size-sm)',
            }}>
              {error}
            </div>
          )}

          {/* ── Loading ────────────────────────────────────────────── */}
          {loading ? (
            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 'var(--space-16)', gap: 'var(--space-3)' }}>
              <Spinner size="md" />
              <span style={{ color: 'var(--color-text-muted)', fontSize: 'var(--font-size-sm)' }}>Loading mail…</span>
            </div>

          ) : filtered.length === 0 ? (
            <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', padding: 'var(--space-16)', gap: 'var(--space-3)' }}>
              <img src="/src/assets/comms/mail.svg" width={40} height={40} alt="" style={{ opacity: 0.25, filter: 'brightness(0) invert(1)' }} />
              <p style={{ color: 'var(--color-text-muted)', fontSize: 'var(--font-size-base)', margin: 0 }}>
                {q || readFilter !== 'all' || clientFilter !== 'all'
                  ? 'No messages match your filters.'
                  : dirFilter === 'inbound' ? 'Your inbox is empty.' : 'No sent mail.'}
              </p>
            </div>

          ) : (
            <div style={{ overflowY: 'auto' }}>
              {filtered.map((entry) => (
                <MailRow
                  key={entry.id}
                  entry={entry}
                  customer={resolveCustomer(entry)}
                  selected={selected.has(entry.id)}
                  onSelect={toggleSelect}
                  onClick={openEntry}
                  onBookmark={toggleImportant}
                />
              ))}
            </div>
          )}
        </div>
      </div>

      <MailViewModal
        entry={viewEntry}
        customers={customers}
        resolveCustomer={resolveCustomer}
        onClose={() => setViewEntry(null)}
        onReply={openReply}
      />
      <ComposeEmailModal
        open={composeOpen}
        defaultTo={composeTo}
        defaultFromAccount={composeFromAccount}
        onClose={() => setComposeOpen(false)}
        onSent={() => { setComposeOpen(false); loadAll() }}
      />
      <MailSettingsModal
        open={settingsOpen}
        onClose={() => setSettingsOpen(false)}
        onSaved={startPolling}
      />
    </>
  )
}
