// Tidvattnaren — chat-vy. Hanterar både global- och plant-scope.
// Sessions byts via pills överst; meddelanden visas i bubblor; nya
// meddelanden POST:as till /api/chat/sessions/:id/messages som ger
// både ekot av användarens meddelande och AI-svaret tillbaka.

// ─────── Markdown → React (ingen dangerouslySetInnerHTML) ───────
// Tillräckligt för LLM-output: rubriker, listor, fetstil, kursiv, kod,
// länkar, kodblock. Allt renderas som React-noder så XSS är omöjligt.
function renderInline(text, keyBase = '') {
  const out = [];
  let key = 0;
  // Alternation: **bold**, __bold__, *em*, _em_, `code`, [link](url)
  const re = /(\*\*([^*\n]+)\*\*)|(__([^_\n]+)__)|(\*([^*\n]+)\*)|(_([^_\n]+)_)|(`([^`\n]+)`)|(\[([^\]]+)\]\(([^)\s]+)\))/g;
  let last = 0; let m;
  while ((m = re.exec(text)) !== null) {
    if (m.index > last) out.push(text.slice(last, m.index));
    if (m[1])      out.push(<strong key={keyBase + (key++)}>{m[2]}</strong>);
    else if (m[3]) out.push(<strong key={keyBase + (key++)}>{m[4]}</strong>);
    else if (m[5]) out.push(<em     key={keyBase + (key++)}>{m[6]}</em>);
    else if (m[7]) out.push(<em     key={keyBase + (key++)}>{m[8]}</em>);
    else if (m[9]) out.push(<code   key={keyBase + (key++)}>{m[10]}</code>);
    else if (m[11]) out.push(<a key={keyBase + (key++)} href={m[13]}
                                target="_blank" rel="noopener noreferrer">{m[12]}</a>);
    last = m.index + m[0].length;
  }
  if (last < text.length) out.push(text.slice(last));
  return out;
}

function renderLines(text, keyBase = '') {
  // Behåll \n inom ett block som <br/>
  const parts = text.split('\n');
  const out = [];
  parts.forEach((line, i) => {
    if (i > 0) out.push(<br key={keyBase + 'br' + i}/>);
    out.push(...renderInline(line, keyBase + 'i' + i + '-'));
  });
  return out;
}

function renderMarkdown(text) {
  // Plocka ut ``` kodblock som platshållare så de inte stör line-by-line-loopen
  const codeBlocks = [];
  const placeholderText = text.replace(/```(\w+)?\n([\s\S]*?)```/g, (m, lang, code) => {
    const idx = codeBlocks.length;
    codeBlocks.push(code.replace(/\n$/, ''));
    return ` CODE${idx} `;
  });

  const lines = placeholderText.split('\n');
  const out = [];
  let i = 0; let key = 0;
  const HEADING_RE = /^(#{1,4})\s+(.+)$/;
  const LIST_RE = /^\s*(-|\*|\+|\d+\.)\s+/;
  const ORDERED_RE = /^\s*\d+\./;
  const CODE_PLACEHOLDER_RE = /^ CODE(\d+) $/;

  while (i < lines.length) {
    const line = lines[i];

    // Tom rad — separator, hoppa
    if (!line.trim()) { i++; continue; }

    // Kodblock-platshållare
    const codeMatch = line.match(CODE_PLACEHOLDER_RE);
    if (codeMatch) {
      out.push(<pre key={`pre${key++}`}><code>{codeBlocks[+codeMatch[1]]}</code></pre>);
      i++; continue;
    }

    // Rubrik (en rad)
    const h = line.match(HEADING_RE);
    if (h) {
      const level = Math.min(h[1].length + 2, 6); // # → h3, ## → h4, ### → h5
      const Tag = 'h' + level;
      out.push(<Tag key={`h${key++}`}>{renderInline(h[2], `h${key}-`)}</Tag>);
      i++; continue;
    }

    // Lista — samla på sig så länge raderna är list-rader
    if (LIST_RE.test(line)) {
      const ordered = ORDERED_RE.test(line);
      const items = [];
      while (i < lines.length && LIST_RE.test(lines[i])) {
        items.push(lines[i].replace(LIST_RE, ''));
        i++;
      }
      const ListTag = ordered ? 'ol' : 'ul';
      out.push(
        <ListTag key={`list${key++}`}>
          {items.map((it, j) => <li key={j}>{renderInline(it, `li${key}-${j}-`)}</li>)}
        </ListTag>
      );
      continue;
    }

    // Stycke — samla rader tills vi möter tom rad, rubrik, lista eller kodblock
    const paraLines = [];
    while (
      i < lines.length
      && lines[i].trim()
      && !HEADING_RE.test(lines[i])
      && !LIST_RE.test(lines[i])
      && !CODE_PLACEHOLDER_RE.test(lines[i])
    ) {
      paraLines.push(lines[i]);
      i++;
    }
    if (paraLines.length) {
      out.push(<p key={`p${key++}`}>{renderLines(paraLines.join('\n'), `p${key}-`)}</p>);
    }
  }

  return out;
}

const SUGGESTIONS_GLOBAL = [
  'Vilka plantor borde jag prioritera idag?',
  'Vad kan jag plantera nu i mitten av maj?',
  'Vilka av mina plantor passar ihop?',
];
const SUGGESTIONS_PLANT = (name) => [
  `Hur sköter jag ${name} bäst?`,
  `Vanliga problem med ${name}?`,
  `När bör jag skörda?`,
];

function ChatScreen({ scopeType, scopePlant, onClearScope }) {
  const [sessions, setSessions] = React.useState([]);
  const [activeId, setActiveId] = React.useState(null);
  const [messages, setMessages] = React.useState([]);
  const [input, setInput] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const [error, setError] = React.useState(null);
  const messagesEnd = React.useRef(null);

  const scopeQuery = scopeType === 'plant' && scopePlant
    ? `?scope=plant&plantId=${encodeURIComponent(scopePlant.id)}`
    : '?scope=global';

  // Ladda sessioner
  React.useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const ses = await TV.apiGet(`/api/chat/sessions${scopeQuery}`);
        if (cancelled) return;
        setSessions(ses);
        if (ses.length > 0 && !activeId) setActiveId(ses[0].id);
      } catch (e) {
        setError(e.message);
      }
    })();
    return () => { cancelled = true; };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [scopeType, scopePlant?.id]);

  // Ladda meddelanden för aktiv session
  React.useEffect(() => {
    if (!activeId) { setMessages([]); return; }
    let cancelled = false;
    (async () => {
      try {
        const data = await TV.apiGet(`/api/chat/sessions/${activeId}`);
        if (!cancelled) setMessages(data.messages || []);
      } catch (e) {
        setError(e.message);
      }
    })();
    return () => { cancelled = true; };
  }, [activeId]);

  // Auto-scroll till botten
  React.useEffect(() => {
    if (messagesEnd.current) {
      messagesEnd.current.scrollIntoView({ behavior: 'smooth' });
    }
  }, [messages.length, busy]);

  const newSession = async () => {
    try {
      const body = scopeType === 'plant'
        ? { scopeType: 'plant', plantId: scopePlant.id }
        : { scopeType: 'global' };
      const session = await TV.apiPost('/api/chat/sessions', body);
      setSessions(prev => [session, ...prev]);
      setActiveId(session.id);
      setMessages([]);
    } catch (e) {
      setError(e.message);
    }
  };

  const deleteSession = async (id, e) => {
    e.stopPropagation();
    if (!confirm('Radera den här chatten?')) return;
    try {
      await TV.apiPost(`/api/chat/sessions/${id}`, null, 'DELETE');
      setSessions(prev => prev.filter(s => s.id !== id));
      if (activeId === id) {
        const remaining = sessions.filter(s => s.id !== id);
        setActiveId(remaining[0]?.id || null);
      }
    } catch (e) {
      setError(e.message);
    }
  };

  const sendMessage = async (text) => {
    const content = (text ?? input).trim();
    if (!content || busy) return;
    setInput('');
    setError(null);

    let sessionId = activeId;
    // Om ingen session finns, skapa en innan vi skickar
    if (!sessionId) {
      try {
        const body = scopeType === 'plant'
          ? { scopeType: 'plant', plantId: scopePlant.id }
          : { scopeType: 'global' };
        const session = await TV.apiPost('/api/chat/sessions', body);
        setSessions(prev => [session, ...prev]);
        setActiveId(session.id);
        sessionId = session.id;
      } catch (e) {
        setError(e.message);
        return;
      }
    }

    // Optimistiskt: lägg in användarens meddelande direkt
    const tempUserMsg = { id: `tmp-${Date.now()}`, role: 'user', content, createdAt: new Date().toISOString() };
    setMessages(prev => [...prev, tempUserMsg]);
    setBusy(true);

    try {
      const result = await TV.apiPost(`/api/chat/sessions/${sessionId}/messages`, { content });
      setMessages(prev => {
        const withoutTemp = prev.filter(m => m.id !== tempUserMsg.id);
        return [...withoutTemp, result.userMessage, result.assistantMessage];
      });
      // Uppdatera sessionens titel om servern auto-genererat ny
      if (result.session) {
        setSessions(prev => prev.map(s => s.id === sessionId ? result.session : s));
      }
    } catch (e) {
      setError(e.message);
      // Lämna kvar tempUserMsg så användaren ser vad de skickade
    } finally {
      setBusy(false);
    }
  };

  const onKeyDown = (e) => {
    if (e.key === 'Enter' && !e.shiftKey) {
      e.preventDefault();
      sendMessage();
    }
  };

  const suggestions = scopeType === 'plant'
    ? SUGGESTIONS_PLANT(scopePlant?.name || 'denna planta')
    : SUGGESTIONS_GLOBAL;

  return (
    <div className="chat-screen">
      {/* Sessions-pills */}
      <div className="chat-sessions">
        <button className="chat-new" onClick={newSession} title="Ny chatt">
          <Icon.Plus size={12}/> Ny
        </button>
        {sessions.map(s => (
          <button key={s.id}
                  className={`chat-session-pill ${s.id === activeId ? 'active' : ''} ${s.scopeType === 'plant' ? 'scope-plant' : ''}`}
                  onClick={() => setActiveId(s.id)}
                  onDoubleClick={(e) => deleteSession(s.id, e)}
                  title="Dubbelklicka för att radera">
            <span style={{ maxWidth: 200, overflow: 'hidden', textOverflow: 'ellipsis' }}>
              {s.title}
            </span>
          </button>
        ))}
      </div>

      {scopeType === 'plant' && scopePlant && (
        <div className="chat-scope-banner">
          <Icon.Sparkle size={14}/>
          <span style={{ flex: 1 }}>Pratar specifikt om <strong>{scopePlant.name}</strong> — AI:n vet alla plantor men fokuserar på den här.</span>
          {onClearScope && (
            <button onClick={onClearScope} style={{
              appearance: 'none', border: '1px solid color-mix(in srgb, var(--accent) 40%, transparent)',
              background: 'transparent', color: '#8B4516', cursor: 'pointer',
              padding: '4px 8px', borderRadius: 8, fontSize: 11.5, fontWeight: 600,
              flexShrink: 0,
            }}>Hela trädgården</button>
          )}
        </div>
      )}

      {/* Meddelanden eller tomtillstånd */}
      <div className="chat-messages">
        {messages.length === 0 && !busy && (
          <div className="chat-empty">
            <div className="serif">
              {scopeType === 'plant' ? `Fråga om ${scopePlant?.name}` : 'Chatta om din trädgård'}
            </div>
            <div style={{ fontSize: 13.5, lineHeight: 1.5, maxWidth: 320 }}>
              AI:n vet om alla dina plantor och kan hjälpa med skötsel, problem, och tips.
            </div>
            <div className="chat-suggestions">
              {suggestions.map(s => (
                <button key={s} className="chat-suggestion" onClick={() => sendMessage(s)}>{s}</button>
              ))}
            </div>
          </div>
        )}

        {messages.map(m => (
          <div key={m.id} className={`chat-msg ${m.role}`}>
            {m.role === 'assistant' ? renderMarkdown(m.content) : m.content}
          </div>
        ))}

        {busy && (
          <div className="chat-typing">
            <span/><span/><span/>
          </div>
        )}

        {error && (
          <div className="chat-msg assistant" style={{ background: '#F7E0CF', color: 'var(--warn)', fontSize: 13 }}>
            ⚠️ {error}
          </div>
        )}

        <div ref={messagesEnd}/>
      </div>

      {/* Input */}
      <div className="chat-input-wrap">
        <div className="chat-input">
          <textarea
            value={input}
            onChange={(e) => setInput(e.target.value)}
            onKeyDown={onKeyDown}
            placeholder={scopeType === 'plant' ? `Fråga om ${scopePlant?.name}…` : 'Fråga om din trädgård…'}
            rows={1}
          />
          <button onClick={() => sendMessage()} disabled={busy || !input.trim()} aria-label="Skicka">
            <Icon.Send size={18}/>
          </button>
        </div>
      </div>
    </div>
  );
}

window.ChatScreen = ChatScreen;
