import { useEffect, useCallback, useRef, useState } from 'react';
import { AnalyticsApi, SearchApi, EmailApi } from '../api/client.js';
import BulkToolbar from '../components/BulkToolbar.jsx';
import useSelection from '../hooks/useSelection.js';
import useListKeyboardNav from '../hooks/useListKeyboardNav.js';

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

const fmtDate = (iso) => {
  const d = new Date(iso);
  const now = new Date();
  const diffDays = (now - d) / 86400000;
  if (diffDays < 1) return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
  if (diffDays < 7) return d.toLocaleDateString([], { weekday: 'short' });
  return d.toLocaleDateString([], { month: 'short', day: 'numeric' });
};

const fmtSize = (b) => {
  if (!b) return '';
  if (b < 1024) return `${b} B`;
  if (b < 1048576) return `${(b / 1024).toFixed(0)} KB`;
  return `${(b / 1048576).toFixed(1)} MB`;
};

const PAGE_SIZE = 50;

// ── SenderList (left panel) ───────────────────────────────────────────────────

function SenderList({ senders, selectedId, onSelect, search, onSearch }) {
  const filtered = senders.filter((s) => {
    const q = search.toLowerCase();
    return !q || (s.address + ' ' + (s.displayName ?? '')).toLowerCase().includes(q);
  });

  return (
    <div className="sl-panel">
      <div className="sl-search-wrap">
        <input
          className="sl-search"
          type="search"
          placeholder="Filter senders…"
          value={search}
          onChange={(e) => onSearch(e.target.value)}
          aria-label="Filter senders"
        />
      </div>
      <div className="sl-count">{filtered.length.toLocaleString()} sender{filtered.length !== 1 ? 's' : ''}</div>
      <ul className="sl-list">
        {filtered.map((s) => (
          <li key={s.senderId}>
            <button
              className={`sl-item${selectedId === s.senderId ? ' sl-item--active' : ''}`}
              onClick={() => onSelect(s)}
            >
              <div className="sl-name">{s.displayName || s.address}</div>
              <div className="sl-addr">{s.displayName ? s.address : s.domain}</div>
              <div className="sl-meta">
                <span className="sl-email-count">{s.emailCount.toLocaleString()}</span>
                {s.unreadCount > 0 && <span className="sl-unread">{s.unreadCount} unread</span>}
              </div>
            </button>
          </li>
        ))}
      </ul>
    </div>
  );
}

// ── EmailDetail (full single-email view) ──────────────────────────────────────

function EmailDetail({ email: summary, onBack }) {
  const [detail, setDetail] = useState(null);
  const [loading, setLoading] = useState(true);
  const [aiSummary, setAiSummary] = useState(null);
  const [aiLoading, setAiLoading] = useState(false);

  useEffect(() => {
    setDetail(null);
    setLoading(true);
    setAiSummary(null);
    EmailApi.get(summary.id)
      .then(setDetail)
      .catch(() => setDetail(null))
      .finally(() => setLoading(false));
  }, [summary.id]);

  const email = detail ?? summary;

  const fetchAiSummary = () => {
    setAiLoading(true);
    EmailApi.summary(summary.id)
      .then((r) => setAiSummary(r.summary))
      .catch(() => setAiSummary(null))
      .finally(() => setAiLoading(false));
  };

  return (
    <div className="sd-detail">
      <button className="sd-back" onClick={onBack}>← Back to list</button>
      <div className="sd-detail-header">
        <div className="sd-detail-subject">{email.subject || '(no subject)'}</div>
        <div className="sd-detail-meta">
          <span>{email.senderDisplayName || email.senderAddress}</span>
          <span className="sd-detail-sep">·</span>
          <span>{new Date(email.sentAtUtc).toLocaleString()}</span>
          {email.sizeEstimateBytes > 0 && (
            <>
              <span className="sd-detail-sep">·</span>
              <span>{fmtSize(email.sizeEstimateBytes)}</span>
            </>
          )}
        </div>
      </div>

      {!loading && (
        <div className="sd-ai-summary">
          {aiSummary != null ? (
            <div className="sd-ai-summary-text">✨ {aiSummary}</div>
          ) : (
            <button className="btn-sm" onClick={fetchAiSummary} disabled={aiLoading}>
              {aiLoading ? 'Summarising…' : '✨ AI summary'}
            </button>
          )}
        </div>
      )}

      {loading && <div className="sd-body-loading muted">Loading message…</div>}

      {!loading && detail?.bodyText && (
        <div className="sd-body">{detail.bodyText}</div>
      )}

      {!loading && !detail?.bodyText && email.snippet && (
        <div className="sd-snippet">{email.snippet}</div>
      )}

      <div className="sd-detail-actions">
        <button
          className="btn-sm"
          onClick={() => window.open(
            `https://mail.google.com/mail/u/0/#all/${email.gmailMessageId}`,
            '_blank', 'noopener,noreferrer'
          )}
        >Open in Gmail ↗</button>
      </div>
    </div>
  );
}

// ── EmailListRow (row inside sender email list) ───────────────────────────────

function EmailListRow({ email: initial, onRemove, onOpen, selected, onToggleSelect, focused }) {
  const [email, setEmail] = useState(initial);
  const [acting, setActing] = useState(false);

  const act = (fn, patch) => async (e) => {
    e.stopPropagation();
    if (acting) return;
    setActing(true);
    try { await fn(email.id); setEmail((p) => ({ ...p, ...patch })); }
    finally { setActing(false); }
  };

  const handleTrash = async (e) => {
    e.stopPropagation();
    if (acting) return;
    setActing(true);
    try { await EmailApi.trash(email.id); onRemove?.(email.id); }
    finally { setActing(false); }
  };

  return (
    <tr
      className={`email-row${email.isUnread ? ' email-row--unread' : ''}${acting ? ' email-row--acting' : ''}${focused ? ' email-row--focused' : ''}`}
      onClick={() => onOpen(email)}
      title="View email"
      style={{ cursor: 'pointer' }}
    >
      <td className="el-select" onClick={(e) => e.stopPropagation()}>
        <input type="checkbox" checked={!!selected} onChange={() => onToggleSelect(email.id)} />
      </td>
      <td className="el-unread">{email.isUnread && <span className="unread-dot" />}</td>
      <td className="el-subject">
        <span className="el-subj-text">{email.subject || '(no subject)'}</span>
        {email.snippet && <span className="el-snippet"> — {email.snippet}</span>}
      </td>
      <td className="el-meta">
        {email.hasAttachments && <span className="el-attach" title="Has attachment">📎</span>}
        {email.sizeEstimateBytes > 1048576 && <span className="el-size">{fmtSize(email.sizeEstimateBytes)}</span>}
      </td>
      <td className="el-date">{fmtDate(email.sentAtUtc)}</td>
      <td className="el-actions" onClick={(e) => e.stopPropagation()}>
        <button
          className="action-btn"
          title={email.isUnread ? 'Mark as read' : 'Mark as unread'}
          onClick={email.isUnread
            ? act(EmailApi.markRead,   { isUnread: false })
            : act(EmailApi.markUnread, { isUnread: true  })}
        >{email.isUnread ? '✓' : '●'}</button>
        <button
          className={`action-btn${email.isStarred ? ' action-btn--active' : ''}`}
          title={email.isStarred ? 'Unstar' : 'Star'}
          onClick={email.isStarred
            ? act(EmailApi.unstar, { isStarred: false })
            : act(EmailApi.star,   { isStarred: true  })}
        >⭐</button>
        <button
          className="action-btn action-btn--danger"
          title="Move to trash"
          onClick={handleTrash}
        >🗑️</button>
      </td>
    </tr>
  );
}

// ── SenderEmails (right panel) ────────────────────────────────────────────────

function SenderEmails({ sender }) {
  const [emails, setEmails] = useState([]);
  const [totalCount, setTotalCount] = useState(null);
  const [page, setPage] = useState(1);
  const [hasMore, setHasMore] = useState(true);
  const [loading, setLoading] = useState(false);
  const [openEmail, setOpenEmail] = useState(null);
  const sentinelRef = useRef(null);
  const { selected, toggle, clear, removeIds, selectedIds } = useSelection();
  const focusedId = useListKeyboardNav(emails, (id) => setEmails((prev) => prev.filter((x) => x.id !== id)));

  // Reset when sender changes
  useEffect(() => {
    setEmails([]);
    setTotalCount(null);
    setPage(1);
    setHasMore(true);
    setOpenEmail(null);
    clear();
  }, [sender.senderId, clear]);

  const fetchPage = useCallback((p) => {
    setLoading(true);
    SearchApi.query(`from:${sender.address}`, p, PAGE_SIZE)
      .then((r) => {
        setEmails((prev) => p === 1 ? r.items : [...prev, ...r.items]);
        setTotalCount(r.totalCount);
        setHasMore(p < r.totalPages);
        setPage(p);
      })
      .finally(() => setLoading(false));
  }, [sender]);

  useEffect(() => { fetchPage(1); }, [fetchPage]);

  // Infinite scroll sentinel
  useEffect(() => {
    const el = sentinelRef.current;
    if (!el) return;
    const obs = new IntersectionObserver(
      (entries) => { if (entries[0].isIntersecting && hasMore && !loading) fetchPage(page + 1); },
      { rootMargin: '200px' }
    );
    obs.observe(el);
    return () => obs.disconnect();
  }, [hasMore, loading, page, fetchPage]);

  if (openEmail) {
    return <EmailDetail email={openEmail} onBack={() => setOpenEmail(null)} />;
  }

  return (
    <div className="sd-panel">
      <div className="sd-panel-header">
        <div className="sd-panel-name">{sender.displayName || sender.address}</div>
        <div className="sd-panel-addr">{sender.displayName ? sender.address : ''}</div>
        {totalCount !== null && (
          <div className="sd-panel-count">{totalCount.toLocaleString()} email{totalCount !== 1 ? 's' : ''}</div>
        )}
      </div>

      <BulkToolbar
        selectedIds={selectedIds}
        onClear={clear}
        onDone={(action, ids) => {
          if (action === 'trash' || action === 'archive') {
            setEmails((prev) => prev.filter((x) => !ids.includes(x.id)));
            removeIds(ids);
          }
        }}
      />

      {emails.length > 0 && (
        <table className="email-list">
          <tbody>
            {emails.map((e) => (
              <EmailListRow
                key={e.id}
                email={e}
                selected={selected.has(e.id)}
                onToggleSelect={toggle}
                focused={focusedId === e.id}
                onOpen={setOpenEmail}
                onRemove={(id) => setEmails((prev) => prev.filter((x) => x.id !== id))}
              />
            ))}
          </tbody>
        </table>
      )}

      <div ref={sentinelRef} />
      {loading && <div className="fv-loading-more">Loading…</div>}
      {!loading && !hasMore && emails.length > 0 && (
        <div className="fv-end">— {emails.length.toLocaleString()} emails —</div>
      )}
      {!loading && emails.length === 0 && (
        <div className="fv-empty">No emails found from this sender.</div>
      )}
    </div>
  );
}

// ── Page ──────────────────────────────────────────────────────────────────────

export default function Senders() {
  const [senders, setSenders] = useState(null);
  const [selected, setSelected] = useState(null);
  const [search, setSearch] = useState('');

  useEffect(() => {
    AnalyticsApi.allSenders().then((list) => {
      setSenders(list);
      if (list.length > 0) setSelected(list[0]);
    }).catch(() => setSenders([]));
  }, []);

  if (!senders) return <div className="page"><h2>Senders</h2><p className="muted">Loading…</p></div>;

  if (senders.length === 0) return (
    <div className="page">
      <h2>Senders</h2>
      <p className="muted">No senders yet — run a sync first.</p>
    </div>
  );

  return (
    <div className="senders-master-detail">
      <SenderList
        senders={senders}
        selectedId={selected?.senderId}
        onSelect={setSelected}
        search={search}
        onSearch={setSearch}
      />
      {selected && <SenderEmails key={selected.senderId} sender={selected} />}
    </div>
  );
}
