{% extends "base.html" %}
{% block title %}{{ chat_name }} — SimpleX Manager{% endblock %}

{% block head %}
<style>
  .chat-wrap {
    display: flex; flex-direction: column;
    height: calc(100vh - 140px); min-height: 400px;
    background: var(--card); border-radius: 10px; box-shadow: var(--shadow);
    overflow: hidden;
  }
  .chat-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 14px 18px; border-bottom: 1px solid var(--border);
  }
  .chat-head .title { font-weight: 700; font-size: 16px; }

  .chat-log {
    flex: 1; overflow-y: auto; padding: 18px;
    display: flex; flex-direction: column; gap: 6px;
  }

  /* ── Bubble row (holds avatar space + bubble + actions) ── */
  .msg-row {
    display: flex; align-items: flex-end; gap: 6px;
    position: relative;
  }
  .msg-row.out { flex-direction: row-reverse; }

  /* ── Bubble ── */
  .bubble {
    max-width: 72%; padding: 8px 12px; border-radius: 14px;
    font-size: 14px; line-height: 1.4; word-wrap: break-word;
    position: relative;
  }
  .bubble .who { font-size: 11px; font-weight: 700; opacity: 0.7; margin-bottom: 2px; }
  .bubble .ts  { font-size: 10px; opacity: 0.55; margin-top: 4px; text-align: right; }
  .bubble.in  { align-self: flex-start; background: var(--bg); border: 1px solid var(--border); }
  .bubble.out { align-self: flex-end; background: var(--accent); color: var(--btn-light-text); }
  .bubble.deleted { font-style: italic; opacity: 0.5; }

  /* ── Quote block (replied-to message) ── */
  .quote-block {
    border-left: 3px solid currentColor;
    padding: 4px 8px; margin-bottom: 6px; border-radius: 4px;
    font-size: 12px; opacity: 0.75;
    background: rgba(0,0,0,0.06);
    max-height: 60px; overflow: hidden;
  }
  .quote-block .q-who { font-weight: 700; margin-bottom: 1px; }
  .quote-block .q-text { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

  /* ── Inline image ── */
  .msg-image {
    max-width: 100%; max-height: 300px; border-radius: 8px;
    display: block; margin-bottom: 4px; cursor: pointer;
  }

  /* ── File attachment ── */
  .file-block {
    display: flex; align-items: center; gap: 8px;
    padding: 6px 8px; margin-bottom: 4px;
    background: rgba(0,0,0,0.08); border-radius: 8px;
    font-size: 12px;
  }
  .file-block .f-ico { font-size: 18px; flex-shrink: 0; }
  .file-block .f-meta { flex: 1; min-width: 0; }
  .file-block .f-name { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .file-block .f-size { opacity: 0.6; font-size: 11px; }
  .file-block .f-action button, .file-block .f-action a {
    font-size: 11px; padding: 3px 8px; border-radius: 6px;
    border: 1px solid currentColor; background: transparent; cursor: pointer;
    color: inherit; text-decoration: none; display: inline-block;
  }
  .file-block .f-action button:hover, .file-block .f-action a:hover { background: rgba(255,255,255,0.15); }

  /* ── Reactions ── */
  .reactions {
    display: flex; flex-wrap: wrap; gap: 4px; margin-top: 5px;
  }
  .rxn {
    display: inline-flex; align-items: center; gap: 3px;
    font-size: 13px; padding: 1px 6px;
    border-radius: 10px; border: 1px solid var(--border);
    background: var(--bg); cursor: pointer;
    transition: background 0.1s;
  }
  .rxn.me { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 15%, transparent); }
  .rxn:hover { background: var(--border); }
  .rxn .rxn-count { font-size: 11px; opacity: 0.8; }

  /* ── Hover action buttons ── */
  .msg-actions {
    display: none; flex-direction: column; gap: 3px;
    align-self: center;
  }
  .msg-row:hover .msg-actions { display: flex; }
  .msg-act-btn {
    background: var(--card); border: 1px solid var(--border);
    border-radius: 6px; padding: 3px 7px; cursor: pointer;
    font-size: 12px; color: var(--text); white-space: nowrap;
  }
  .msg-act-btn:hover { border-color: var(--accent); color: var(--accent); }

  /* ── Emoji picker strip ── */
  .emoji-strip {
    display: none; position: absolute; z-index: 10;
    background: var(--card); border: 1px solid var(--border);
    border-radius: 10px; padding: 5px 8px; gap: 4px;
    box-shadow: var(--shadow);
  }
  .msg-row:hover .emoji-strip { display: flex; }
  .msg-row.out .emoji-strip { right: 100%; margin-right: 6px; }
  .msg-row:not(.out) .emoji-strip { left: 100%; margin-left: 6px; }
  .e-btn { font-size: 18px; cursor: pointer; border: none; background: transparent;
           padding: 2px; border-radius: 4px; }
  .e-btn:hover { background: var(--bg); }

  /* ── Reply preview above compose ── */
  .reply-preview {
    display: flex; align-items: center; justify-content: space-between;
    padding: 6px 12px; background: var(--bg); border-top: 1px solid var(--border);
    font-size: 12px; gap: 8px;
  }
  .reply-preview .rp-bar {
    width: 3px; align-self: stretch; border-radius: 2px;
    background: var(--accent); flex-shrink: 0;
  }
  .reply-preview .rp-body { flex: 1; min-width: 0; }
  .reply-preview .rp-who { font-weight: 700; color: var(--accent); }
  .reply-preview .rp-text { opacity: 0.7; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .reply-preview .rp-cancel { cursor: pointer; opacity: 0.5; font-size: 16px; flex-shrink: 0; }
  .reply-preview .rp-cancel:hover { opacity: 1; }

  .chat-compose {
    display: flex; gap: 8px; padding: 12px; border-top: 1px solid var(--border);
  }
  .chat-compose textarea { resize: none; height: 42px; }
  .chat-empty { text-align: center; color: var(--muted); margin: auto; font-size: 14px; }
  .chat-banner { padding: 8px 18px; font-size: 12px; color: var(--muted);
                 background: var(--bg); border-bottom: 1px solid var(--border); }
</style>
{% endblock %}

{% block content %}
<div class="flex gap-8" style="margin-bottom:16px;">
  <a href="/profile/{{ profile.id }}" class="muted" style="text-decoration:none;">← {{ profile.name }}</a>
  <span class="muted">/</span>
  <strong>{{ chat_name }}</strong>
  <span class="tag">{{ 'channel' if is_channel else chat_type }}</span>
</div>

<div class="chat-wrap">
  <div class="chat-head">
    <span class="title">{{ chat_name }}</span>
    <button class="btn btn-ghost" style="padding:4px 12px;font-size:12px;"
            onclick="loadMessages(true)"><i class="fa-solid fa-rotate-right"></i> Refresh</button>
  </div>

  {% if is_channel %}
  <div class="chat-banner"><i class="fa-solid fa-bullhorn"></i> Channel — messages you send here broadcast to all subscribers.</div>
  {% endif %}

  <div class="chat-log" id="chat-log">
    {% if not running %}
    <div class="chat-empty">Profile is stopped. Start it to load messages.</div>
    {% else %}
    <div class="chat-empty" id="chat-loading">Loading messages…</div>
    {% endif %}
  </div>

  <div id="reply-preview" class="reply-preview" style="display:none;">
    <div class="rp-bar"></div>
    <div class="rp-body">
      <div class="rp-who" id="rp-who"></div>
      <div class="rp-text" id="rp-text"></div>
    </div>
    <span class="rp-cancel" onclick="cancelReply()">&#x2715;</span>
  </div>

  <div class="chat-compose">
    <textarea id="msg-input" placeholder="{{ 'Broadcast a message…' if is_channel else 'Type a message…' }}"
              {% if not running %}disabled{% endif %}
              onkeydown="if(event.key==='Enter'&&!event.shiftKey){event.preventDefault();sendMsg();}"></textarea>
    <button class="btn btn-primary" onclick="sendMsg()" {% if not running %}disabled{% endif %}>Send</button>
  </div>
</div>

<script>
const PROFILE_ID = {{ profile.id }};
const CHAT_TYPE  = '{{ chat_type }}';
const CHAT_ID    = {{ chat_id }};
const RUNNING    = {{ 'true' if running else 'false' }};
const _token = () => document.cookie.match(/(?:^|;\s*)token=([^;]+)/)?.[1] || '';

let lastIds = '';
let replyTo = null;   // {id, sender, text}

const QUICK_EMOJIS = ['👍','❤️','😂','😮','😢','🙏'];

function fmtSize(bytes) {
  if (bytes < 1024) return bytes + ' B';
  if (bytes < 1048576) return (bytes/1024).toFixed(1) + ' KB';
  return (bytes/1048576).toFixed(1) + ' MB';
}

function fmtTs(iso) {
  if (!iso) return '';
  const d = new Date(iso);
  if (isNaN(d)) return '';
  return d.toLocaleString([], {month:'short', day:'numeric', hour:'2-digit', minute:'2-digit'});
}

function escapeHtml(s) {
  return String(s).replace(/[&<>"']/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
}

function renderQuote(q) {
  if (!q) return '';
  const who = q.sender ? `<div class="q-who">${escapeHtml(q.sender)}</div>` : '';
  const txt = q.text ? `<div class="q-text">${escapeHtml(q.text)}</div>` : '<div class="q-text"><em>attachment</em></div>';
  return `<div class="quote-block">${who}${txt}</div>`;
}

function renderImage(m) {
  if (!m.image_preview) return '';
  // image_preview is a base64 data URI from the message content
  const escaped = escapeHtml(m.image_preview);
  // If file is downloaded, clicking opens the full-res version
  const fullUrl = m.file && m.file.status === 'rcvComplete'
    ? `/api/profiles/${PROFILE_ID}/file/${m.file.id}/download`
    : null;
  const img = `<img class="msg-image" src="${escaped}" alt="image"
    ${fullUrl ? `onclick="window.open('${fullUrl}','_blank')" title="Click to open full size"` : ''}>`;
  return img;
}

function renderFile(f) {
  if (!f) return '';
  const isComplete = f.status === 'rcvComplete' || f.status === 'sndComplete' || f.status === 'sndStored';
  const ico = '<i class="fa-solid fa-paperclip"></i>';
  const name = escapeHtml(f.name || 'file');
  const size = fmtSize(f.size || 0);
  let action = '';
  if (f.status === 'rcvInvitation') {
    action = `<div class="f-action"><button onclick="acceptFile(${f.id},this)"><i class="fa-solid fa-download"></i> Accept</button></div>`;
  } else if (isComplete) {
    const dlUrl = `/api/profiles/${PROFILE_ID}/file/${f.id}/download`;
    action = `<div class="f-action"><a href="${dlUrl}" target="_blank"><i class="fa-solid fa-arrow-down"></i> Download</a></div>`;
  } else if (f.status && f.status.startsWith('rcvTransfer')) {
    action = `<div class="f-action"><span style="opacity:0.6;font-size:11px;"><i class="fa-solid fa-spinner fa-spin"></i> Downloading…</span></div>`;
  }
  return `<div class="file-block">
    <div class="f-ico">${ico}</div>
    <div class="f-meta">
      <div class="f-name" title="${name}">${name}</div>
      <div class="f-size">${size}</div>
    </div>
    ${action}
  </div>`;
}

function renderReactions(reactions, itemId) {
  if (!reactions || !reactions.length) return '';
  const pills = reactions.map(r => {
    const me = r.me ? ' me' : '';
    return `<span class="rxn${me}" title="${r.me?'You reacted':''}" onclick="toggleReaction(${itemId},'${escapeHtml(r.emoji)}',${r.me})">${escapeHtml(r.emoji)}<span class="rxn-count">${r.count}</span></span>`;
  }).join('');
  return `<div class="reactions">${pills}</div>`;
}

function renderEmojiStrip(itemId) {
  const btns = QUICK_EMOJIS.map(e =>
    `<button class="e-btn" title="React ${e}" onclick="sendReaction(${itemId},'${e}',true,event)">${e}</button>`
  ).join('');
  return `<div class="emoji-strip">${btns}</div>`;
}

function render(messages) {
  const log = document.getElementById('chat-log');
  const sig = messages.map(m => m.id + ':' + (m.reactions||[]).map(r=>r.emoji+r.count).join('')).join(',');
  if (sig === lastIds) return;
  const atBottom = log.scrollHeight - log.scrollTop - log.clientHeight < 60;
  lastIds = sig;

  if (!messages.length) {
    log.innerHTML = '<div class="chat-empty">No messages yet.</div>';
    return;
  }

  log.innerHTML = messages.map(m => {
    const out = m.outgoing;
    const dir = out ? 'out' : 'in';
    const bubbleCls = `bubble ${dir}${m.deleted ? ' deleted' : ''}`;
    const who = (!out && m.sender) ? `<div class="who">${escapeHtml(m.sender)}</div>` : '';
    const txt = m.deleted ? '(deleted)' : (m.text ? escapeHtml(m.text) : '');

    const quoteHtml = renderQuote(m.quote);
    const imageHtml = renderImage(m);
    const fileHtml = (!imageHtml || m.file) ? renderFile(m.file) : '';
    const reactHtml = renderReactions(m.reactions, m.id);
    const emojiStrip = m.deleted ? '' : renderEmojiStrip(m.id);
    const replyBtn = m.deleted ? '' :
      `<button class="msg-act-btn" onclick="setReply(${m.id},${JSON.stringify(escapeHtml(m.sender||'You'))},${JSON.stringify(escapeHtml((m.text||'').slice(0,80)))})" title="Reply"><i class="fa-solid fa-reply"></i></button>`;

    const actionsHtml = `<div class="msg-actions">${replyBtn}</div>`;

    const inner = `${quoteHtml}${imageHtml}${fileHtml}${who}${txt}${reactHtml}<div class="ts">${fmtTs(m.ts)}</div>`;

    return `<div class="msg-row ${dir}" data-id="${m.id}">
      ${emojiStrip}
      ${out ? actionsHtml : ''}
      <div class="${bubbleCls}">${inner}</div>
      ${!out ? actionsHtml : ''}
    </div>`;
  }).join('');

  if (atBottom) log.scrollTop = log.scrollHeight;
}

async function loadMessages(force) {
  if (!RUNNING) return;
  try {
    const resp = await fetch(`/api/profiles/${PROFILE_ID}/chat/${CHAT_TYPE}/${CHAT_ID}/messages?count=80`, {
      headers: {'X-Token': _token()},
    });
    if (!resp.ok) return;
    const data = await resp.json();
    if (force) lastIds = '';
    render(data.messages || []);
  } catch(e) {}
}

function setReply(id, sender, text) {
  replyTo = {id, sender, text};
  document.getElementById('rp-who').textContent = sender || 'Unknown';
  document.getElementById('rp-text').textContent = text || '(attachment)';
  document.getElementById('reply-preview').style.display = 'flex';
  document.getElementById('msg-input').focus();
}

function cancelReply() {
  replyTo = null;
  document.getElementById('reply-preview').style.display = 'none';
}

async function sendMsg() {
  const input = document.getElementById('msg-input');
  const text = input.value.trim();
  if (!text) return;
  input.value = '';
  const body = {text};
  if (replyTo) body.reply_to_id = replyTo.id;
  const resp = await fetch(`/api/profiles/${PROFILE_ID}/chat/${CHAT_TYPE}/${CHAT_ID}/send`, {
    method: 'POST',
    headers: {'Content-Type': 'application/json', 'X-Token': _token()},
    body: JSON.stringify(body),
  });
  cancelReply();
  const data = await resp.json();
  if (!data.ok) {
    input.value = text;
    alert('Failed to send: ' + (data.error || data.detail || 'unknown error'));
    return;
  }
  setTimeout(() => loadMessages(true), 250);
}

async function sendReaction(itemId, emoji, add, ev) {
  if (ev) ev.stopPropagation();
  await fetch(`/api/profiles/${PROFILE_ID}/chat/${CHAT_TYPE}/${CHAT_ID}/react`, {
    method: 'POST',
    headers: {'Content-Type': 'application/json', 'X-Token': _token()},
    body: JSON.stringify({item_id: itemId, emoji, add}),
  });
  setTimeout(() => loadMessages(true), 300);
}

async function toggleReaction(itemId, emoji, currently_reacted) {
  await sendReaction(itemId, emoji, !currently_reacted, null);
}

async function acceptFile(fileId, btn) {
  btn.disabled = true;
  btn.textContent = '…';
  const resp = await fetch(`/api/profiles/${PROFILE_ID}/file/${fileId}/receive`, {
    method: 'POST', headers: {'X-Token': _token()},
  });
  const data = await resp.json();
  if (!data.ok) { btn.disabled = false; btn.textContent = 'Retry'; return; }
  setTimeout(() => loadMessages(true), 500);
}

if (RUNNING) {
  loadMessages(true);
  setInterval(loadMessages, 3000);
}
</script>
{% endblock %}
