import { useState, useEffect, useRef } from 'react';
import { api, S } from '../lib.js';
import { UserIcon, TrashIcon } from '../icons.jsx';
import {
  getOrCreateKeyPair,
  getPublicKeyJwk,
  getFingerprint,
  deriveSharedKey,
  encryptMsg,
  decryptMsg,
} from '../crypto.js';

export default function Nachrichten({ toast, mobile }) {
  const [kp,          setKp]          = useState(null);
  const [initError,   setInitError]   = useState(false);
  const [users,       setUsers]       = useState([]);
  const [activeUser,  setActiveUser]  = useState(null);
  const [messages,    setMessages]    = useState([]);
  const [sharedKey,   setSharedKey]   = useState(null);   // null | CryptoKey | 'error'
  const [decrypted,   setDecrypted]   = useState({});
  const [partnerFp,   setPartnerFp]   = useState('');
  const [text,        setText]        = useState('');
  const [sending,     setSending]     = useState(false);
  const bottomRef = useRef(null);
  const pollRef   = useRef(null);

  // ── Initialisierung ──────────────────────────────────────────────────────────
  useEffect(() => {
    getOrCreateKeyPair()
      .then(async k => {
        setKp(k);
        try {
          const jwk = await getPublicKeyJwk(k);
          await api('/tools/nachrichten/keys', { body: { public_key: JSON.stringify(jwk) } });
        } catch {}
        loadUsers();
      })
      .catch(() => setInitError(true));
  }, []);

  // ── Polling ──────────────────────────────────────────────────────────────────
  useEffect(() => {
    clearInterval(pollRef.current);
    if (!activeUser) return;
    loadMessages(activeUser.id);
    pollRef.current = setInterval(() => loadMessages(activeUser.id), 10_000);
    return () => clearInterval(pollRef.current);
  }, [activeUser?.id]);

  // ── Shared Key + Partner-Fingerprint ─────────────────────────────────────────
  useEffect(() => {
    setSharedKey(null);
    setDecrypted({});
    setPartnerFp('');
    if (!kp || !activeUser?.public_key) return;
    try {
      const pubJwk = JSON.parse(activeUser.public_key);
      deriveSharedKey(kp.privateKey, pubJwk)
        .then(setSharedKey)
        .catch(() => setSharedKey('error'));
      // Fingerprint des Partner-Keys berechnen (aus dem auf dem Server gespeicherten Public Key)
      crypto.subtle.importKey('jwk', pubJwk, { name:'X25519' }, true, [])
        .then(k => getFingerprint({ publicKey: k }))
        .then(setPartnerFp)
        .catch(() => setPartnerFp('?'));
    } catch {
      setSharedKey('error');
    }
  }, [activeUser?.id, kp]);

  // ── Entschlüsseln ────────────────────────────────────────────────────────────
  useEffect(() => {
    if (sharedKey === null || sharedKey === 'error' || !messages.length) {
      setDecrypted({});
      return;
    }
    let cancelled = false;
    (async () => {
      const result = {};
      for (const m of messages) {
        if (cancelled) return;
        try {
          result[m.id] = await decryptMsg(sharedKey, m.encrypted_content, m.iv);
        } catch {
          result[m.id] = null; // null = nicht entschlüsselbar
        }
      }
      if (!cancelled) setDecrypted(result);
    })();
    return () => { cancelled = true; };
  }, [messages, sharedKey]);

  // ── Scroll to bottom ─────────────────────────────────────────────────────────
  useEffect(() => {
    bottomRef.current?.scrollIntoView({ behavior: 'smooth' });
  }, [messages.length]);

  // ── Handlers ─────────────────────────────────────────────────────────────────
  const loadUsers = async () => {
    try { setUsers(await api('/tools/nachrichten/users')); } catch {}
  };

  const loadMessages = async userId => {
    try {
      setMessages(await api(`/tools/nachrichten/messages/${userId}`));
      await loadUsers();
    } catch {}
  };

  const selectUser = u => {
    setActiveUser(u);
    setMessages([]);
    setDecrypted({});
  };

  const send = async () => {
    if (!text.trim() || !kp || !activeUser) return;
    if (!activeUser.public_key) { toast('Empfänger hat noch keinen Schlüssel', 'error'); return; }
    if (sharedKey === 'error')  { toast('Schlüssel inkompatibel – Empfänger muss Schlüssel neu generieren', 'error'); return; }
    if (!sharedKey)             { toast('Schlüssel wird vorbereitet…', 'error'); return; }
    setSending(true);
    try {
      const { encrypted_content, iv } = await encryptMsg(sharedKey, text.trim());
      await api(`/tools/nachrichten/messages/${activeUser.id}`, { body: { encrypted_content, iv } });
      setText('');
      await loadMessages(activeUser.id);
    } catch(e) { toast(e.message, 'error'); }
    setSending(false);
  };

  const deleteMsg = async id => {
    try {
      await api(`/tools/nachrichten/messages/${id}`, { method:'DELETE' });
      setMessages(p => p.filter(m => m.id !== id));
    } catch(e) { toast(e.message, 'error'); }
  };

  const deleteConversation = async () => {
    if (!window.confirm(`Gesamten Verlauf mit ${activeUser.username} löschen?`)) return;
    try {
      await api(`/tools/nachrichten/conversation/${activeUser.id}`, { method:'DELETE' });
      setMessages([]);
      await loadUsers();
    } catch(e) { toast(e.message, 'error'); }
  };

  // ── Layout ───────────────────────────────────────────────────────────────────
  const showList = !mobile || !activeUser;
  const showChat = !mobile || !!activeUser;
  const h = mobile
    ? 'calc(100dvh - 56px - env(safe-area-inset-bottom, 0px))'
    : '100vh';

  if (initError) return (
    <div style={{ padding:32, color:'rgba(255,255,255,0.45)', fontFamily:'monospace', fontSize:12, lineHeight:2 }}>
      ⚠ Verschlüsselung konnte nicht initialisiert werden.<br/>
      Dein Browser unterstützt X25519 möglicherweise nicht (erfordert Chrome 113+/Firefox 130+/Safari 17.4+).
    </div>
  );

  return (
    <div style={{ display:'flex', height:h, overflow:'hidden', background:'#111114' }}>

      {/* ── Konversationsliste ─────────────────────────────────────────── */}
      {showList && (
        <div style={{
          width: mobile ? '100%' : 230,
          borderRight: mobile ? 'none' : '1px solid rgba(255,255,255,0.06)',
          display:'flex', flexDirection:'column', background:'#0d0d0f', flexShrink:0,
        }}>
          <div style={{ padding:'16px 14px 12px', borderBottom:'1px solid rgba(255,255,255,0.06)' }}>
            <div style={{ ...S.head, marginBottom:0 }}>NACHRICHTEN</div>
          </div>
          <div style={{ flex:1, overflowY:'auto' }}>
            {users.length === 0 ? (
              <div style={{ color:'rgba(255,255,255,0.28)', fontSize:11, fontFamily:'monospace',
                padding:18, textAlign:'center', lineHeight:1.8 }}>
                Keine anderen Benutzer vorhanden
              </div>
            ) : users.map(u => (
              <button key={u.id} onClick={() => selectUser(u)} style={{
                width:'100%', padding:'11px 14px', border:'none', textAlign:'left', cursor:'pointer',
                background: activeUser?.id === u.id ? 'rgba(78,205,196,0.07)' : 'transparent',
                borderLeft: `2px solid ${activeUser?.id === u.id ? '#4ecdc4' : 'transparent'}`,
                display:'flex', alignItems:'center', gap:10,
              }}>
                <div style={{ width:32, height:32, borderRadius:'50%', flexShrink:0,
                  background:'linear-gradient(135deg,rgba(255,107,157,0.2),rgba(78,205,196,0.2))',
                  border:'1px solid rgba(255,255,255,0.07)',
                  display:'flex', alignItems:'center', justifyContent:'center' }}>
                  <UserIcon size={14} color="rgba(255,255,255,0.5)"/>
                </div>
                <div style={{ flex:1, minWidth:0 }}>
                  <div style={{
                    color: u.unread > 0 ? '#fff' : 'rgba(255,255,255,0.65)',
                    fontWeight: u.unread > 0 ? 700 : 400,
                    fontSize:12, fontFamily:'monospace',
                    whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis',
                  }}>{u.username}</div>
                  {u.last_message_at && (
                    <div style={{ color:'rgba(255,255,255,0.26)', fontSize:9, fontFamily:'monospace', marginTop:2 }}>
                      {new Date(u.last_message_at).toLocaleDateString('de-DE',
                        { day:'numeric', month:'short', hour:'2-digit', minute:'2-digit' })}
                    </div>
                  )}
                </div>
                {u.unread > 0 && (
                  <span style={{ background:'#4ecdc4', color:'#000', borderRadius:10,
                    fontSize:9, fontFamily:'monospace', padding:'2px 7px', fontWeight:700, flexShrink:0 }}>
                    {u.unread}
                  </span>
                )}
              </button>
            ))}
          </div>
        </div>
      )}

      {/* ── Chat ──────────────────────────────────────────────────────── */}
      {showChat && (
        <div style={{ flex:1, display:'flex', flexDirection:'column', overflow:'hidden', minWidth:0 }}>
          {!activeUser ? (
            <div style={{ flex:1, display:'flex', alignItems:'center', justifyContent:'center',
              flexDirection:'column', gap:10 }}>
              <div style={{ fontSize:38, opacity:0.1 }}>✉</div>
              <div style={{ color:'rgba(255,255,255,0.18)', fontFamily:'monospace', fontSize:11 }}>
                Benutzer auswählen
              </div>
            </div>
          ) : (
            <>
              {/* Header */}
              <div style={{ padding:'10px 14px', borderBottom:'1px solid rgba(255,255,255,0.06)',
                display:'flex', alignItems:'center', gap:10, background:'#0d0d0f', flexShrink:0 }}>
                {mobile && (
                  <button onClick={() => setActiveUser(null)} style={{ background:'transparent', border:'none',
                    cursor:'pointer', color:'#4ecdc4', fontFamily:'monospace', fontSize:20, padding:'0 4px', lineHeight:1 }}>
                    ‹
                  </button>
                )}
                <div style={{ width:28, height:28, borderRadius:'50%', flexShrink:0,
                  background:'linear-gradient(135deg,rgba(255,107,157,0.2),rgba(78,205,196,0.2))',
                  border:'1px solid rgba(255,255,255,0.07)',
                  display:'flex', alignItems:'center', justifyContent:'center' }}>
                  <UserIcon size={12} color="rgba(255,255,255,0.5)"/>
                </div>
                <div style={{ flex:1, minWidth:0 }}>
                  <div style={{ color:'#fff', fontSize:13, fontFamily:'monospace',
                    whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>
                    {activeUser.username}
                  </div>
                  {sharedKey === 'error' ? (
                    <div style={{ color:'#ff6b9d', fontSize:8, fontFamily:'monospace', letterSpacing:1.5, marginTop:1 }}>
                      ⚠ SCHLÜSSEL INKOMPATIBEL
                    </div>
                  ) : partnerFp ? (
                    <div title={`Fingerprint von ${activeUser.username} – vergleiche mit dessen Anzeige unter Einstellungen → Sicherheit`}
                      style={{ color:'rgba(78,205,196,0.55)', fontSize:8, fontFamily:'monospace', letterSpacing:1, marginTop:2,
                        cursor:'help', whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>
                      🔒 {partnerFp}
                    </div>
                  ) : (
                    <div style={{ color:'rgba(78,205,196,0.35)', fontSize:8, fontFamily:'monospace', letterSpacing:1.5, marginTop:1 }}>
                      🔒 E2E VERSCHLÜSSELT · X25519 + AES-256-GCM
                    </div>
                  )}
                </div>
                <button onClick={deleteConversation} style={{ ...S.btn('#ff6b9d', true), fontSize:10, flexShrink:0 }}>
                  Verlauf löschen
                </button>
              </div>

              {/* Nachrichten */}
              <div style={{ flex:1, overflowY:'auto', padding:'14px', display:'flex', flexDirection:'column', gap:10 }}>
                {!activeUser.public_key && (
                  <InfoBox color="#ffe66d">
                    ⚠ Dieser Benutzer hat die Nachrichten noch nicht geöffnet und besitzt noch kein Schlüsselpaar.
                  </InfoBox>
                )}
                {sharedKey === 'error' && (
                  <InfoBox color="#ff6b9d">
                    ⚠ Schlüssel inkompatibel – der Empfänger verwendet ein anderes Schlüsselformat (z. B. altes P-256).
                    Er muss in Einstellungen → Sicherheit einen neuen Schlüssel generieren.
                  </InfoBox>
                )}
                {messages.length === 0 && activeUser.public_key && sharedKey !== 'error' && (
                  <div style={{ flex:1, display:'flex', alignItems:'center', justifyContent:'center',
                    color:'rgba(255,255,255,0.18)', fontFamily:'monospace', fontSize:11 }}>
                    Noch keine Nachrichten
                  </div>
                )}
                {messages.map(m => {
                  const isMine = !!m.is_mine;
                  const txt    = decrypted[m.id];
                  return (
                    <div key={m.id} style={{ display:'flex',
                      justifyContent: isMine ? 'flex-end' : 'flex-start', gap:6, alignItems:'flex-end' }}>
                      {!isMine && (
                        <div style={{ width:22, height:22, borderRadius:'50%', flexShrink:0,
                          background:'rgba(255,255,255,0.04)', border:'1px solid rgba(255,255,255,0.07)',
                          display:'flex', alignItems:'center', justifyContent:'center' }}>
                          <UserIcon size={10} color="rgba(255,255,255,0.4)"/>
                        </div>
                      )}
                      <div style={{ maxWidth:'75%', display:'flex', flexDirection:'column',
                        alignItems: isMine ? 'flex-end' : 'flex-start', gap:4 }}>
                        <div style={{
                          background: isMine ? 'rgba(78,205,196,0.09)' : 'rgba(255,255,255,0.04)',
                          border: `1px solid ${isMine ? 'rgba(78,205,196,0.15)' : 'rgba(255,255,255,0.07)'}`,
                          borderRadius: isMine ? '12px 12px 3px 12px' : '12px 12px 12px 3px',
                          padding:'8px 12px',
                        }}>
                          {txt === undefined ? (
                            <span style={{ color:'rgba(255,255,255,0.18)', fontSize:12 }}>⋯</span>
                          ) : txt === null ? (
                            <span style={{ color:'rgba(255,107,157,0.5)', fontSize:11, fontFamily:'monospace' }}>
                              🔒 Nicht entschlüsselbar
                            </span>
                          ) : (
                            <span style={{ color:'#e6e6e6', fontSize:13, fontFamily:'monospace',
                              lineHeight:1.55, whiteSpace:'pre-wrap', wordBreak:'break-word' }}>{txt}</span>
                          )}
                        </div>
                        <div style={{ display:'flex', alignItems:'center', gap:5 }}>
                          <span style={{ color:'rgba(255,255,255,0.18)', fontSize:9, fontFamily:'monospace', whiteSpace:'nowrap' }}>
                            {formatMsgTime(m.created_at)}
                          </span>
                          {isMine && (
                            <span title={m.read_by_recipient ? 'Gelesen' : 'Gesendet'}
                              style={{ fontSize:10, lineHeight:1, color: m.read_by_recipient ? '#4ecdc4' : 'rgba(255,255,255,0.2)' }}>
                              {m.read_by_recipient ? '✓✓' : '✓'}
                            </span>
                          )}
                          <button onClick={() => deleteMsg(m.id)} style={{ background:'transparent', border:'none',
                            cursor:'pointer', padding:'0 2px', opacity:0.3, lineHeight:1,
                            display:'flex', alignItems:'center' }}>
                            <TrashIcon size={10} color="#ff6b9d"/>
                          </button>
                        </div>
                      </div>
                    </div>
                  );
                })}
                <div ref={bottomRef}/>
              </div>

              {/* Eingabe */}
              <div style={{ padding:'10px 14px', borderTop:'1px solid rgba(255,255,255,0.06)',
                background:'#0d0d0f', flexShrink:0 }}>
                {!activeUser.public_key || sharedKey === 'error' ? (
                  <div style={{ color:'rgba(255,255,255,0.2)', fontSize:11, fontFamily:'monospace',
                    textAlign:'center', padding:'8px 0' }}>
                    Senden nicht möglich
                  </div>
                ) : (
                  <div style={{ display:'flex', gap:8, alignItems:'flex-end' }}>
                    <textarea
                      value={text} onChange={e => setText(e.target.value)}
                      onKeyDown={e => { if (e.key==='Enter' && !e.shiftKey) { e.preventDefault(); send(); }}}
                      placeholder="Nachricht… (Enter senden · Shift+Enter neue Zeile)"
                      rows={2}
                      style={{ ...S.inp, resize:'none', flex:1, fontSize:13, padding:'8px 10px',
                        lineHeight:1.45, minHeight:42 }}
                    />
                    <button onClick={send} disabled={sending || !text.trim()} style={{
                      ...S.btn('#4ecdc4'), padding:'10px 16px', flexShrink:0, alignSelf:'stretch',
                      opacity: sending || !text.trim() ? 0.3 : 1, fontSize:17, lineHeight:1,
                    }}>↑</button>
                  </div>
                )}
              </div>
            </>
          )}
        </div>
      )}
    </div>
  );
}

function InfoBox({ color, children }) {
  return (
    <div style={{ background:`${color}08`, border:`1px solid ${color}25`,
      borderRadius:8, padding:'10px 14px', color, fontSize:11,
      fontFamily:'monospace', textAlign:'center', lineHeight:1.7 }}>
      {children}
    </div>
  );
}

function formatMsgTime(isoStr) {
  if (!isoStr) return '';
  const d   = new Date(isoStr.replace(' ', 'T'));
  if (isNaN(d)) return '';
  const now = new Date();
  const isToday    = d.toDateString() === now.toDateString();
  const isThisYear = d.getFullYear() === now.getFullYear();
  const time = d.toLocaleTimeString('de-DE', { hour:'2-digit', minute:'2-digit' });
  if (isToday) return time;
  if (isThisYear) return `${d.toLocaleDateString('de-DE', { day:'numeric', month:'short' })} ${time}`;
  return `${d.toLocaleDateString('de-DE', { day:'numeric', month:'short', year:'numeric' })} ${time}`;
}
