/* coach-panel.jsx — chat surface for the AI coach.
   Desktop: floating button bottom-right opens a 420px-wide drawer.
   Mobile: full-screen, hosted by the BottomNav's "Coach" tab. */
/* global React, MEMBERS, Eyebrow, Avatar, Button */
const { useState, useEffect, useRef, useCallback } = React;

const FN_URL = () => window.SUPABASE_URL + '/functions/v1/coach';

// Async helpers that wrap fetch to the coach Edge Function. Centralised so
// the panel doesn't sprawl with auth boilerplate.
async function coachFetchHistory(memberId) {
  const { data: { session } } = await window.sb.auth.getSession();
  if (!session) throw new Error('Not signed in.');
  const resp = await fetch(FN_URL(), {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${session.access_token}`, 'Content-Type': 'application/json', 'apikey': window.SUPABASE_ANON_KEY },
    body: JSON.stringify({ action: 'fetch_history', memberId }),
  });
  if (!resp.ok) throw new Error(`fetch_history failed: ${await resp.text()}`);
  const j = await resp.json();
  return j.messages || [];
}
async function coachSend(memberId, prompt) {
  const { data: { session } } = await window.sb.auth.getSession();
  if (!session) throw new Error('Not signed in.');
  const resp = await fetch(FN_URL(), {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${session.access_token}`, 'Content-Type': 'application/json', 'apikey': window.SUPABASE_ANON_KEY },
    body: JSON.stringify({ action: 'chat', memberId, prompt }),
  });
  if (!resp.ok) throw new Error(`coach call failed (${resp.status}): ${await resp.text()}`);
  return resp.json();
}
async function coachClear(memberId) {
  const { data: { session } } = await window.sb.auth.getSession();
  if (!session) throw new Error('Not signed in.');
  const resp = await fetch(FN_URL(), {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${session.access_token}`, 'Content-Type': 'application/json', 'apikey': window.SUPABASE_ANON_KEY },
    body: JSON.stringify({ action: 'clear', memberId }),
  });
  if (!resp.ok) throw new Error(`clear failed: ${await resp.text()}`);
  return resp.json();
}

// ============================================================================
// CoachThread — message list + composer. Used by both desktop drawer and
// mobile full-screen Coach tab.
// ============================================================================
function CoachThread({ memberId, autoFocus }) {
  const member = MEMBERS.find(m => m.id === memberId);
  const [messages, setMessages] = useState([]);
  const [draft, setDraft] = useState('');
  const [sending, setSending] = useState(false);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const scrollRef = useRef(null);

  const memberDbId = member?.db_id;

  // Load history when the active member changes
  useEffect(() => {
    if (!memberDbId) return;
    setLoading(true);
    setError(null);
    coachFetchHistory(memberDbId)
      .then(msgs => setMessages(msgs))
      .catch(e => setError(e.message))
      .finally(() => setLoading(false));
  }, [memberDbId]);

  // Scroll to bottom on new messages
  useEffect(() => {
    if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
  }, [messages.length, sending]);

  const send = useCallback(async () => {
    const text = draft.trim();
    if (!text || sending || !memberDbId) return;
    setSending(true);
    setError(null);
    // Optimistic append
    setMessages(prev => [...prev, { role: 'user', content: text, _local: true, id: 'tmp-' + Date.now() }]);
    setDraft('');
    try {
      const res = await coachSend(memberDbId, text);
      setMessages(prev => [...prev, { role: 'assistant', content: res.content, id: 'tmp-' + Date.now() + 'r' }]);
    } catch (e) {
      setError(e.message);
      setMessages(prev => prev.filter(m => !m._local));  // roll back optimistic user msg on error
    } finally {
      setSending(false);
    }
  }, [draft, sending, memberDbId]);

  const onKey = (e) => {
    if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) { e.preventDefault(); send(); }
  };

  const onClear = async () => {
    if (!confirm('Rensa hela konversationen för ' + member.name + '?')) return;
    try {
      await coachClear(memberDbId);
      setMessages([]);
    } catch (e) { setError(e.message); }
  };

  if (!member) return <div style={{ padding: 24, color: 'var(--fg-muted)' }}>Välj en familjemedlem först.</div>;

  return (
    <div style={{ display: 'flex', flexDirection: 'column', height: '100%', background: 'var(--bg)' }}>
      {/* Header */}
      <div style={{
        padding: '12px 16px', borderBottom: '1px solid var(--border)',
        display: 'flex', alignItems: 'center', gap: 10,
      }}>
        <Avatar member={member} size={28} />
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontFamily: 'var(--font-sans)', fontSize: 14, fontWeight: 500 }}>Coach · {member.name}</div>
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--fg-subtle)', letterSpacing: '0.04em' }}>
            {member.age ? member.age + ' år' : ''}{member.sport ? ' · ' + member.sport : ''}
          </div>
        </div>
        <button onClick={onClear} title="Rensa konversation"
          style={{ background: 'transparent', border: 'none', cursor: 'pointer', color: 'var(--fg-subtle)', padding: 6, fontFamily: 'var(--font-mono)', fontSize: 10, letterSpacing: '0.06em', textTransform: 'uppercase' }}>
          Rensa
        </button>
      </div>

      {/* Messages */}
      <div ref={scrollRef} style={{ flex: 1, overflowY: 'auto', padding: '14px 14px 8px' }}>
        {loading && <div style={{ color: 'var(--fg-subtle)', fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '0.06em' }}>Laddar konversation…</div>}
        {!loading && messages.length === 0 && (
          <div style={{ color: 'var(--fg-muted)', fontSize: 13, lineHeight: 1.55, padding: '20px 4px' }}>
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, letterSpacing: '0.10em', textTransform: 'uppercase', color: 'var(--fg-subtle)', marginBottom: 8 }}>Ny konversation</div>
            <div>Hej {member.name}! Fråga mig om dagens pass, dina utmaningar, eller bara berätta hur du mår. Jag känner till dina senaste loggar och utmaningar.</div>
            <div style={{ marginTop: 14, display: 'flex', flexDirection: 'column', gap: 6 }}>
              {['Vad ska jag göra idag?', 'Hur går det för mig denna säsong?', 'Förslå pass åt mig imorgon'].map(s => (
                <button key={s} onClick={() => setDraft(s)}
                  style={{ textAlign: 'left', padding: '8px 10px', background: 'var(--ink-25)', border: '1px solid var(--border)', borderRadius: 6, cursor: 'pointer', fontFamily: 'var(--font-sans)', fontSize: 13, color: 'var(--fg)' }}>
                  {s}
                </button>
              ))}
            </div>
          </div>
        )}
        {messages.map((m, i) => (
          <MessageBubble key={m.id || i} role={m.role} content={m.content} />
        ))}
        {sending && <MessageBubble role="assistant" content="…" thinking />}
      </div>

      {/* Error */}
      {error && (
        <div style={{ padding: '8px 14px', background: 'rgba(176,33,26,0.06)', borderTop: '1px solid var(--danger)', color: 'var(--danger)', fontSize: 12, fontFamily: 'var(--font-mono)' }}>
          {error}
        </div>
      )}

      {/* Composer */}
      <div style={{ padding: 10, borderTop: '1px solid var(--border)', background: 'var(--bg-raised)', display: 'flex', gap: 8, alignItems: 'flex-end' }}>
        <textarea
          autoFocus={autoFocus}
          value={draft}
          onChange={e => setDraft(e.target.value)}
          onKeyDown={onKey}
          placeholder={`Skriv till coach…  (⌘+Enter för att skicka)`}
          rows={2}
          style={{
            flex: 1, resize: 'none', minHeight: 44, maxHeight: 140,
            fontFamily: 'var(--font-sans)', fontSize: 14, color: 'var(--fg)',
            background: 'var(--bg)', border: '1px solid var(--border)', borderRadius: 6,
            padding: '8px 10px', outline: 'none',
          }}
        />
        <button
          onClick={send}
          disabled={sending || !draft.trim()}
          style={{
            fontFamily: 'var(--font-sans)', fontSize: 13, fontWeight: 500,
            padding: '10px 14px', borderRadius: 6,
            background: 'var(--signal)', color: '#fff',
            border: 'none', cursor: sending || !draft.trim() ? 'not-allowed' : 'pointer',
            opacity: sending || !draft.trim() ? 0.5 : 1,
            transition: 'opacity 120ms',
            alignSelf: 'stretch', minWidth: 70,
          }}
        >{sending ? '…' : 'Skicka'}</button>
      </div>
    </div>
  );
}

// ============================================================================
// MessageBubble
// ============================================================================
function MessageBubble({ role, content, thinking }) {
  const isUser = role === 'user';
  return (
    <div style={{ marginBottom: 12, display: 'flex', justifyContent: isUser ? 'flex-end' : 'flex-start' }}>
      <div style={{
        maxWidth: '85%',
        padding: '10px 12px',
        borderRadius: 12,
        background: isUser ? 'var(--signal)' : 'var(--bg-raised)',
        color: isUser ? '#fff' : 'var(--fg)',
        border: isUser ? 'none' : '1px solid var(--border)',
        fontSize: 14, lineHeight: 1.5,
        whiteSpace: 'pre-wrap', wordBreak: 'break-word',
        fontFamily: 'var(--font-sans)',
        opacity: thinking ? 0.6 : 1,
      }}>
        {content}
      </div>
    </div>
  );
}

// ============================================================================
// CoachDrawer — desktop floating button + slide-in drawer
// ============================================================================
function CoachDrawer({ memberId }) {
  const [open, setOpen] = useState(false);
  return (
    <>
      <button
        onClick={() => setOpen(o => !o)}
        title="Öppna coach"
        data-mobile-hide-on-mobile
        style={{
          position: 'fixed', right: 20, bottom: 20, zIndex: 100,
          width: 56, height: 56, borderRadius: 999,
          background: 'var(--signal)', color: '#fff',
          border: 'none', cursor: 'pointer',
          boxShadow: '0 6px 20px -4px rgba(14,133,67,0.45)',
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
          transition: 'transform 120ms',
        }}
      >
        {open ? (
          <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round">
            <line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
          </svg>
        ) : (
          <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
            <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>
          </svg>
        )}
      </button>
      {open && (
        <div
          data-mobile-hide-on-mobile
          style={{
            position: 'fixed', right: 0, top: 0, bottom: 0,
            width: 'min(420px, 100vw)', zIndex: 99,
            background: 'var(--bg-raised)',
            borderLeft: '1px solid var(--border)',
            boxShadow: '-12px 0 40px -16px rgba(0,0,0,0.18)',
            display: 'flex', flexDirection: 'column',
          }}
        >
          <CoachThread memberId={memberId} autoFocus />
        </div>
      )}
    </>
  );
}

window.CoachThread = CoachThread;
window.CoachDrawer = CoachDrawer;
