import { useEffect, useRef, useState, type FormEvent } from 'react';
import { ModalPortal } from '../components/modal-portal';
import { useCompose, useInbox, useMailThread } from './hooks';
import type { InboxItem, InboxState, MailAttachment, MailPerson } from './types';

const fmtBytes = (n: number): string => {
  if (!n) return '';
  if (n < 1024) return `${n} B`;
  if (n < 1024 * 1024) return `${Math.round(n / 1024)} KB`;
  return `${(n / (1024 * 1024)).toFixed(1)} MB`;
};

const FILTERS: { value: InboxState; label: string }[] = [
  { value: 'OPEN', label: 'Open' },
  { value: 'SNOOZED', label: 'Snoozed' },
  { value: 'DONE', label: 'Done' },
  { value: 'ARCHIVED', label: 'Archived' },
];

const KIND_LABEL: Record<string, string> = {
  MAIL: 'Mail',
  MENTION: 'Mention',
  NEEDS_REPLY: 'Needs reply',
  SYSTEM_ALERT: 'Alert',
  SUPPORT_UPDATE: 'Support',
};

const timeOf = (iso?: string): string => {
  if (!iso) return '';
  const d = new Date(iso);
  return Number.isNaN(+d) ? '' : d.toLocaleString([], { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' });
};

/** The unified inbox: work items + mail in one list; click a threaded row to read + reply. */
export function Inbox({ focusThreadId }: { focusThreadId?: string | null } = {}) {
  const [filter, setFilter] = useState<InboxState>('OPEN');
  const { items, loading, error, transition, refetch } = useInbox(filter);
  const compose = useCompose();
  const [selectedId, setSelectedId] = useState<string | null>(null);
  const [composing, setComposing] = useState(false);

  // Deep link (e.g. from global search): mail lives in the Open view, so switch there and let the
  // selection effect pick the matching thread once the list loads.
  useEffect(() => {
    if (focusThreadId) setFilter('OPEN');
  }, [focusThreadId]);

  useEffect(() => {
    if (focusThreadId) {
      const hit = items.find((i) => i.threadId === focusThreadId);
      if (hit) {
        setSelectedId(hit.id);
        return;
      }
    }
    if (selectedId && items.some((i) => i.id === selectedId)) return;
    setSelectedId(items[0]?.id ?? null);
  }, [items, selectedId, focusThreadId]);

  const selected = items.find((i) => i.id === selectedId) ?? null;

  return (
    <div className="miu-inbox">
      <div className="miu-inbox-bar">
        <div className="miu-inbox-filters">
          {FILTERS.map((f) => (
            <button key={f.value} type="button" className={`miu-tab${filter === f.value ? ' is-active' : ''}`} onClick={() => setFilter(f.value)}>
              {f.label}
            </button>
          ))}
        </div>
        {compose.supported ? (
          <button type="button" className="miu-send" onClick={() => setComposing(true)}>
            New message
          </button>
        ) : null}
      </div>

      <div className="miu-inbox-body">
        <aside className="miu-inbox-list">
          {loading && items.length === 0 ? <div className="miu-empty">Loading…</div> : null}
          {error ? <div className="miu-empty miu-error">{error}</div> : null}
          {!loading && items.length === 0 ? <div className="miu-empty">Nothing here — you&apos;re all caught up 🎉</div> : null}
          {items.map((it) => (
            <button key={it.id} type="button" className={`miu-inbox-row${it.id === selectedId ? ' is-active' : ''}`} onClick={() => setSelectedId(it.id)}>
              <span className="miu-inbox-glyph" aria-hidden="true">{it.kind === 'MAIL' ? '✉' : it.kind === 'MENTION' ? '@' : '•'}</span>
              <span className="miu-inbox-main">
                <span className="miu-inbox-row-top">
                  <span className="miu-pill">{KIND_LABEL[it.kind] ?? it.kind}</span>
                  <span className="miu-inbox-title">{it.title}</span>
                </span>
                {it.summary ? <span className="miu-inbox-summary">{it.summary}</span> : null}
              </span>
              {it.state !== 'OPEN' ? <span className="miu-pill">{it.state.toLowerCase()}</span> : null}
            </button>
          ))}
        </aside>

        <section className="miu-inbox-detail">
          {selected ? <Detail item={selected} onTransition={(s) => void transition(selected.id, s)} /> : <div className="miu-empty miu-thread-empty">Select an item to read.</div>}
        </section>
      </div>

      {composing ? <ComposeModal onClose={() => setComposing(false)} onSent={() => { setComposing(false); refetch(); }} /> : null}
    </div>
  );
}

function Detail({ item, onTransition }: { item: InboxItem; onTransition: (state: InboxState) => void }) {
  return (
    <div className="miu-detail">
      {item.state === 'OPEN' && item.kind !== 'MAIL' ? (
        <div className="miu-detail-actions">
          <button type="button" className="miu-tab" onClick={() => onTransition('SNOOZED')}>Snooze</button>
          <button type="button" className="miu-tab" onClick={() => onTransition('DONE')}>Done</button>
          <button type="button" className="miu-tab" onClick={() => onTransition('ARCHIVED')}>Archive</button>
        </div>
      ) : null}
      {item.threadId ? (
        <MailReader threadId={item.threadId} subject={item.title} />
      ) : (
        <div className="miu-detail-body">
          <div className="miu-detail-title">{item.title}</div>
          {item.summary ? <div className="miu-detail-summary">{item.summary}</div> : null}
        </div>
      )}
    </div>
  );
}

/** Read a mail thread (HTML in a sandboxed iframe) + reply. */
export function MailReader({ threadId, subject }: { threadId: string; subject: string }) {
  const { messages, loading, error, reply, canAttach, upload, canDownload, download } = useMailThread(threadId);
  const [draft, setDraft] = useState('');
  const [sending, setSending] = useState(false);
  const [pending, setPending] = useState<MailAttachment | null>(null);
  const [attaching, setAttaching] = useState(false);
  const [uploadingName, setUploadingName] = useState<string | null>(null);
  const [attachErr, setAttachErr] = useState<string | null>(null);
  const fileRef = useRef<HTMLInputElement>(null);

  async function openAttachment(att: MailAttachment): Promise<void> {
    try {
      const url = await download(att);
      window.open(url, '_blank', 'noopener,noreferrer');
    } catch (err) {
      setAttachErr(err instanceof Error ? err.message : String(err));
    }
  }

  async function pick(e: React.ChangeEvent<HTMLInputElement>): Promise<void> {
    const file = e.target.files?.[0];
    e.target.value = '';
    if (!file) return;
    setAttaching(true);
    setUploadingName(file.name);
    setAttachErr(null);
    try {
      setPending(await upload(file));
    } catch (err) {
      setAttachErr(err instanceof Error ? err.message : String(err));
    } finally {
      setAttaching(false);
      setUploadingName(null);
    }
  }

  async function submit(e: FormEvent): Promise<void> {
    e.preventDefault();
    const text = draft.trim();
    if ((!text && !pending) || sending) return;
    const att = pending;
    setDraft('');
    setPending(null);
    setSending(true);
    try {
      await reply(text, att ?? undefined);
    } catch {
      setDraft(text);
      setPending(att);
    } finally {
      setSending(false);
    }
  }

  return (
    <div className="miu-mail">
      <header className="miu-mail-head">{subject || '(no subject)'}</header>
      <div className="miu-mail-body">
        {loading && messages.length === 0 ? <div className="miu-empty">Loading…</div> : null}
        {error ? <div className="miu-empty miu-error">{error}</div> : null}
        {messages.map((m) => (
          <article key={m.id} className="miu-mail-msg">
            <div className="miu-mail-meta">
              <span>{m.kind === 'EMAIL' ? 'Email' : 'Reply'}{m.actorId ? ` · ${m.actorId}` : ''}</span>
              <span>{timeOf(m.at)}</span>
            </div>
            {m.html ? (
              <iframe sandbox="" srcDoc={m.html} title="mail body" className="miu-mail-frame" />
            ) : m.text ? (
              <div className="miu-mail-text">{m.text}</div>
            ) : null}
            {m.attachment ? (
              canDownload ? (
                <button type="button" className="miu-attach-chip miu-attach-dl" onClick={() => void openAttachment(m.attachment!)} title="Download">
                  📎 {m.attachment.filename ?? 'attachment'}{m.attachment.sizeBytes ? ` · ${fmtBytes(m.attachment.sizeBytes)}` : ''} ↓
                </button>
              ) : (
                <span className="miu-attach-chip">📎 {m.attachment.filename ?? 'attachment'}{m.attachment.sizeBytes ? ` · ${fmtBytes(m.attachment.sizeBytes)}` : ''}</span>
              )
            ) : null}
          </article>
        ))}
      </div>
      <form className="miu-composer" onSubmit={submit}>
        {attachErr ? <div className="miu-empty miu-error">{attachErr}</div> : null}
        {attaching && uploadingName ? (
          <div className="miu-attach-pending">
            <span className="miu-attach-chip is-uploading"><span className="miu-spinner" aria-hidden="true" /> {uploadingName} · uploading…</span>
          </div>
        ) : pending ? (
          <div className="miu-attach-pending">
            <span className="miu-attach-chip">📎 {pending.filename ?? 'attachment'}{pending.sizeBytes ? ` · ${fmtBytes(pending.sizeBytes)}` : ''}</span>
            <button type="button" className="miu-attach-x" onClick={() => setPending(null)} aria-label="Remove attachment">✕</button>
          </div>
        ) : null}
        <div className="miu-composer-row">
          {canAttach ? (
            <>
              <input ref={fileRef} type="file" hidden onChange={pick} aria-label="Attach file" />
              <button type="button" className="miu-attach-btn" onClick={() => fileRef.current?.click()} disabled={attaching || !!pending} title="Attach a file" aria-label="Attach a file">
                {attaching ? '…' : '📎'}
              </button>
            </>
          ) : null}
          <input className="miu-input" value={draft} onChange={(e) => setDraft(e.target.value)} placeholder="Reply…" aria-label="Reply" />
          <button type="submit" className="miu-send" disabled={(!draft.trim() && !pending) || sending}>Reply</button>
        </div>
      </form>
    </div>
  );
}

function ComposeModal({ onClose, onSent }: { onClose: () => void; onSent: () => void }) {
  const compose = useCompose();
  const [mode, setMode] = useState<'internal' | 'external'>('internal');
  const [recipient, setRecipient] = useState('');
  const [subject, setSubject] = useState('');
  const [body, setBody] = useState('');
  const [q, setQ] = useState('');
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState<string | null>(null);
  const [attachments, setAttachments] = useState<MailAttachment[]>([]);
  const [attaching, setAttaching] = useState(false);
  const [uploadingName, setUploadingName] = useState<string | null>(null);
  const fileRef = useRef<HTMLInputElement>(null);

  const filtered = compose.directory.filter((p) => p.name.toLowerCase().includes(q.trim().toLowerCase()));
  const canSend = !!recipient && !!subject.trim() && (!!body.trim() || attachments.length > 0) && !busy && !attaching;

  async function pick(e: React.ChangeEvent<HTMLInputElement>): Promise<void> {
    const file = e.target.files?.[0];
    e.target.value = '';
    if (!file || attachments.length >= 10) return;
    setAttaching(true);
    setUploadingName(file.name);
    setErr(null);
    try {
      const ref = await compose.upload(file);
      setAttachments((a) => [...a, ref]);
    } catch (e2) {
      setErr(e2 instanceof Error ? e2.message : String(e2));
    } finally {
      setAttaching(false);
      setUploadingName(null);
    }
  }

  async function send(): Promise<void> {
    if (!canSend) return;
    setBusy(true);
    setErr(null);
    const atts = attachments.length > 0 ? attachments : undefined;
    try {
      if (mode === 'internal') await compose.sendInternal(recipient, subject.trim(), body.trim(), atts);
      else await compose.sendExternal(recipient.trim(), subject.trim(), body.trim(), atts);
      onSent();
    } catch (e) {
      setErr(e instanceof Error ? e.message : String(e));
    } finally {
      setBusy(false);
    }
  }

  return (
    <ModalPortal>
      <div className="miu-modal-overlay" onMouseDown={onClose}>
      <div className="miu-modal" role="dialog" aria-modal="true" onMouseDown={(e) => e.stopPropagation()}>
        <div className="miu-modal-head">
          <span>New message</span>
          <button type="button" className="miu-pane-close" onClick={onClose} aria-label="Close">✕</button>
        </div>
        <div className="miu-modal-body">
          <div className="miu-compose-modes">
            <button type="button" className={`miu-tab${mode === 'internal' ? ' is-active' : ''}`} onClick={() => { setMode('internal'); setRecipient(''); }}>In-app</button>
            <button type="button" className={`miu-tab${mode === 'external' ? ' is-active' : ''}`} onClick={() => { setMode('external'); setRecipient(''); }}>Email</button>
          </div>

          {mode === 'internal' ? (
            <div className="miu-field">
              <span className="miu-field-lbl">To (person)</span>
              <input className="miu-input" value={q} onChange={(e) => setQ(e.target.value)} placeholder="Search people…" aria-label="Search people" />
              <div className="miu-people">
                {filtered.length === 0 ? <div className="miu-empty">No people found.</div> : null}
                {filtered.map((p: MailPerson) => (
                  <label key={p.id} className={`miu-person${recipient === p.id ? ' is-active' : ''}`}>
                    <input type="radio" name="miu-recipient" checked={recipient === p.id} onChange={() => setRecipient(p.id)} />
                    <span>{p.name}</span>
                    <span className="miu-pill">{p.kind}</span>
                  </label>
                ))}
              </div>
            </div>
          ) : (
            <div className="miu-field">
              <span className="miu-field-lbl">To (email)</span>
              <input className="miu-input" value={recipient} onChange={(e) => setRecipient(e.target.value)} placeholder="name@company.com" aria-label="To email" />
            </div>
          )}

          <div className="miu-field">
            <span className="miu-field-lbl">Subject</span>
            <input className="miu-input" value={subject} onChange={(e) => setSubject(e.target.value)} placeholder="Subject" aria-label="Subject" />
          </div>
          <div className="miu-field">
            <span className="miu-field-lbl">Message</span>
            <textarea className="miu-input miu-textarea" value={body} onChange={(e) => setBody(e.target.value)} placeholder="Write your message…" rows={5} aria-label="Message body" />
          </div>
          {compose.canAttach ? (
            <div className="miu-field">
              <span className="miu-field-lbl">Attachments</span>
              <div className="miu-attach-list">
                {attachments.map((a, i) => (
                  <span key={`${a.contentRef}-${i}`} className="miu-attach-pending">
                    <span className="miu-attach-chip">📎 {a.filename ?? 'attachment'}{a.sizeBytes ? ` · ${fmtBytes(a.sizeBytes)}` : ''}</span>
                    <button type="button" className="miu-attach-x" onClick={() => setAttachments((prev) => prev.filter((_, j) => j !== i))} aria-label="Remove attachment">✕</button>
                  </span>
                ))}
                {attaching && uploadingName ? (
                  <span className="miu-attach-pending">
                    <span className="miu-attach-chip is-uploading"><span className="miu-spinner" aria-hidden="true" /> {uploadingName} · uploading…</span>
                  </span>
                ) : null}
                <input ref={fileRef} type="file" hidden onChange={pick} aria-label="Attach file" />
                <button type="button" className="miu-tab" onClick={() => fileRef.current?.click()} disabled={attaching || attachments.length >= 10}>
                  📎 Attach
                </button>
              </div>
            </div>
          ) : null}
          {err ? <div className="miu-empty miu-error">{err}</div> : null}
        </div>
        <div className="miu-modal-foot">
          <button type="button" className="miu-tab" onClick={onClose}>Cancel</button>
          <button type="button" className="miu-send" onClick={() => void send()} disabled={!canSend}>{busy ? 'Sending…' : 'Send'}</button>
        </div>
      </div>
      </div>
    </ModalPortal>
  );
}
