<chat-room>
  <div class="chat-room">
    <!-- Header -->
    <header class="room-header">
      <div class="room-header-info">
        <h3>{props.room?.name}</h3>
        <button class="members-toggle" onclick={toggleMembers}>
          <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/>
            <circle cx="9" cy="7" r="4"/>
            <path d="M23 21v-2a4 4 0 0 0-3-3.87"/>
            <path d="M16 3.13a4 4 0 0 1 0 7.75"/>
          </svg>
          {(props.room?.members?.length || 0) + 1} members
          <svg class={'members-chevron ' + (state.showMembers ? 'open' : '')} width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <polyline points="6 9 12 15 18 9"/>
          </svg>
        </button>
      </div>
      <div class="room-actions">
        <button class="btn btn-ghost btn-icon" onclick={props.cbInvite} title="Invite">
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <path d="M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/>
            <circle cx="8.5" cy="7" r="4"/>
            <line x1="20" y1="8" x2="20" y2="14"/><line x1="23" y1="11" x2="17" y2="11"/>
          </svg>
        </button>
        <button
          if={props.user?.id === props.room?.created_by}
          class="btn btn-ghost btn-icon btn-danger-icon"
          onclick={props.cbDeleteRoom}
          title="Delete Room"
        >
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <polyline points="3 6 5 6 21 6"/>
            <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
          </svg>
        </button>
      </div>

      <!-- Member list dropdown -->
      <div if={state.showMembers} class="members-dropdown">
        <div class="member-item ai-member">
          <div class="member-avatar ai-avatar">
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <rect x="4" y="8" width="16" height="12" rx="2"/>
              <line x1="12" y1="2" x2="12" y2="8"/>
              <circle cx="12" cy="2" r="1" fill="currentColor"/>
              <circle cx="9" cy="14" r="1.5" fill="currentColor"/>
              <circle cx="15" cy="14" r="1.5" fill="currentColor"/>
            </svg>
          </div>
          <span class="member-name">{props.room?.ai_name || 'AI Assistant'}</span>
          <span class="member-role ai-role">AI</span>
        </div>
        <div each={member in props.room?.members} key={member.id} class="member-item">
          <div class="member-avatar">
            <img src={avatarFromEmail(member.email, 28)}
                 alt={member.display_name}
                 width="28"
                 height="28"
                 class="avatar-img"
                 loading="lazy"
            />
          </div>
          <span class="member-name">{member.display_name}</span>
          <span if={member.id === props.room?.created_by} class="member-role">Owner</span>
        </div>
      </div>
    </header>

    <!-- Messages -->
    <div class="messages-list" ref="messagesList">
      <div class="messages-spacer"></div>
      <div each={msg in props.messages} key={msg.id} data-hash={msg.hash || ''} id={msg.hash ? 'msg-' + msg.hash : ''}>
        <message-bubble
          message={msg}
          is-own={msg.sender_id === props.user?.id}
        />
      </div>

      <!-- Streaming AI message (live content) -->
      <div if={props.streamingMessage} key="streaming">
        <message-bubble
          message={props.streamingMessage}
          is-own={false}
          is-streaming={true}
        />
      </div>

      <!-- AI typing indicator (only when NOT streaming content) -->
      <div if={props.aiTyping && !props.streamingMessage} class="typing-indicator ai-typing">
        <div class="typing-avatar ai-avatar">
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <rect x="4" y="8" width="16" height="12" rx="2"/>
            <line x1="12" y1="2" x2="12" y2="8"/>
            <circle cx="12" cy="2" r="1" fill="currentColor"/>
            <circle cx="9" cy="14" r="1.5" fill="currentColor"/>
            <circle cx="15" cy="14" r="1.5" fill="currentColor"/>
          </svg>
        </div>
        <template if={props.aiToolStatus}>
          <span class="tool-status-text">
            {isSearchTool(props.aiToolStatus.tool) ? '🔍 Searching...' : props.aiToolStatus.tool === 'web_fetch' ? '🌐 Reading page...' : '⚙️ Using tool...'}
          </span>
        </template>
        <template if={!props.aiToolStatus}>
          <div class="typing-dots">
            <span></span><span></span><span></span>
          </div>
        </template>
      </div>

      <div if={state.typingDisplay} class="typing-indicator">
        <span class="typing-text">{state.typingDisplay}</span>
      </div>
    </div>

    <!-- Input -->
    <div class="message-input-area">
      <!-- Image preview -->
      <div if={state.pendingImage} class="image-preview-bar">
        <img src={state.pendingImagePreview} alt="Preview" class="image-preview-thumb" />
        <span class="image-preview-name">{state.pendingImage?.name || 'Pasted image'}</span>
        <button class="image-preview-remove" onclick={removeImage} title="Remove image">
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
          </svg>
        </button>
      </div>
      <div class="input-wrapper">
        <button class="btn btn-ghost attach-btn" onclick={triggerFileInput} title="Attach image">
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <rect x="3" y="3" width="18" height="18" rx="2" ry="2"/>
            <circle cx="8.5" cy="8.5" r="1.5"/>
            <polyline points="21 15 16 10 5 21"/>
          </svg>
        </button>
        <input type="file" ref="fileInput" accept="image/png,image/jpeg,image/gif,image/webp" style="display:none" onchange={handleFileSelect} />
        <textarea
          ref="input"
          class="message-input"
          placeholder={'Type a message... (use @ai or @' + (props.room?.ai_name || 'AI') + ')'}
          rows="1"
          oninput={handleInput}
          onkeydown={handleKeydown}
          onpaste={handlePaste}
        ></textarea>
        <button
          class="btn btn-primary send-btn"
          onclick={handleSend}
          disabled={!state.inputValue?.trim() && !state.pendingImage}
        >
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/>
          </svg>
        </button>
      </div>
    </div>
  </div>

  <style>
    .chat-room {
      height: 100%;
      display: flex;
      flex-direction: column;
      background: var(--bg-secondary);
    }

    .room-header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 0 var(--space-lg);
      height: var(--header-height);
      border-bottom: 1px solid var(--border);
      background: var(--bg-secondary);
      position: relative;
    }

    .room-header-info h3 {
      font-size: var(--text-base);
      font-weight: 600;
    }

    .members-toggle {
      background: none;
      border: none;
      color: var(--text-muted);
      font-size: var(--text-xs);
      cursor: pointer;
      display: inline-flex;
      align-items: center;
      gap: 4px;
      padding: 2px 6px;
      border-radius: var(--radius-sm);
      transition: all var(--transition-fast);
    }

    .members-toggle:hover {
      color: var(--text-secondary);
      background: var(--bg-hover);
    }

    .members-chevron {
      transition: transform 0.15s;
    }

    .members-chevron.open {
      transform: rotate(180deg);
    }

    .members-dropdown {
      position: absolute;
      top: 100%;
      left: var(--space-lg);
      background: var(--bg-tertiary);
      border: 1px solid var(--border);
      border-radius: var(--radius-md);
      padding: var(--space-xs) 0;
      min-width: 200px;
      max-width: 280px;
      box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
      z-index: 20;
      animation: fadeIn 0.15s ease;
    }

    @keyframes fadeIn {
      from { opacity: 0; }
      to { opacity: 1; }
    }

    .member-item {
      display: flex;
      align-items: center;
      gap: var(--space-sm);
      padding: var(--space-xs) var(--space-md);
    }

    .member-avatar {
      width: 28px;
      height: 28px;
      border-radius: var(--radius-full);
      background: var(--bg-elevated);
      display: flex;
      align-items: center;
      justify-content: center;
      font-weight: 600;
      font-size: var(--text-xs);
      color: var(--text-secondary);
      flex-shrink: 0;
      overflow: hidden;
    }

    .avatar-img {
      width: 100%;
      height: 100%;
      border-radius: var(--radius-full);
      object-fit: cover;
    }

    .member-item .ai-avatar {
      background: var(--accent);
      color: white;
    }

    .member-name {
      font-size: var(--text-sm);
      color: var(--text-primary);
      flex: 1;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    .member-role {
      font-size: 11px;
      color: var(--text-muted);
      background: var(--bg-elevated);
      padding: 1px 6px;
      border-radius: var(--radius-sm);
    }

    .ai-role {
      color: var(--accent);
      background: rgba(108, 92, 231, 0.15);
    }

    .room-actions {
      display: flex;
      gap: var(--space-xs);
    }

    .btn-icon {
      width: 36px;
      height: 36px;
      padding: 0;
      display: flex;
      align-items: center;
      justify-content: center;
      border-radius: var(--radius-md);
    }

    .btn-danger-icon:hover {
      color: var(--error, #e53e3e) !important;
      background: rgba(229, 62, 62, 0.1);
    }

    .messages-list {
      flex: 1;
      overflow-y: auto;
      padding: var(--space-md) var(--space-lg);
      display: flex;
      flex-direction: column;
      gap: var(--space-xs);
      min-height: 0;
    }

    .messages-spacer {
      flex: 1;
    }

    .typing-indicator {
      display: flex;
      align-items: center;
      gap: var(--space-sm);
      padding: var(--space-xs) var(--space-sm);
      font-size: var(--text-sm);
      color: var(--text-muted);
    }

    .ai-typing {
      align-items: center;
    }

    .typing-avatar {
      width: 28px;
      height: 28px;
      border-radius: var(--radius-full);
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: var(--text-xs);
      font-weight: 600;
      flex-shrink: 0;
    }

    .ai-avatar {
      background: var(--accent);
      color: white;
    }

    .typing-dots {
      display: flex;
      gap: 4px;
    }

    .typing-dots span {
      width: 6px;
      height: 6px;
      background: var(--text-muted);
      border-radius: var(--radius-full);
      animation: typing-bounce 1.4s infinite ease-in-out;
    }

    .typing-dots span:nth-child(2) {
      animation-delay: 0.2s;
    }

    .typing-dots span:nth-child(3) {
      animation-delay: 0.4s;
    }

    @keyframes typing-bounce {
      0%, 80%, 100% { transform: scale(0.6); opacity: 0.4; }
      40% { transform: scale(1); opacity: 1; }
    }

    .typing-text {
      font-style: italic;
    }

    .tool-status-text {
      font-size: var(--text-sm);
      color: var(--accent);
      font-weight: 500;
      animation: tool-pulse 1.5s ease-in-out infinite;
    }

    @keyframes tool-pulse {
      0%, 100% { opacity: 1; }
      50% { opacity: 0.5; }
    }

    .message-input-area {
      padding: var(--space-sm) var(--space-lg) var(--space-md);
      border-top: 1px solid var(--border);
    }

    .image-preview-bar {
      display: flex;
      align-items: center;
      gap: var(--space-sm);
      padding: var(--space-sm) var(--space-sm);
      margin-bottom: var(--space-xs);
      background: var(--bg-tertiary);
      border: 1px solid var(--border);
      border-radius: var(--radius-md);
      animation: fadeIn 0.15s ease;
    }

    .image-preview-thumb {
      width: 48px;
      height: 48px;
      object-fit: cover;
      border-radius: var(--radius-sm);
      border: 1px solid var(--border);
    }

    .image-preview-name {
      flex: 1;
      font-size: var(--text-xs);
      color: var(--text-secondary);
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    .image-preview-remove {
      background: none;
      border: none;
      color: var(--text-muted);
      cursor: pointer;
      padding: 4px;
      border-radius: var(--radius-sm);
      display: flex;
      align-items: center;
      justify-content: center;
      transition: all var(--transition-fast);
    }

    .image-preview-remove:hover {
      color: var(--error, #e53e3e);
      background: rgba(229, 62, 62, 0.1);
    }

    .input-wrapper {
      display: flex;
      align-items: flex-end;
      gap: var(--space-sm);
      background: var(--bg-tertiary);
      border: 1px solid var(--border);
      border-radius: var(--radius-lg);
      padding: var(--space-sm);
      transition: border-color var(--transition-fast);
    }

    .input-wrapper:focus-within {
      border-color: var(--accent);
    }

    .attach-btn {
      width: 36px;
      height: 36px;
      padding: 0;
      flex-shrink: 0;
      display: flex;
      align-items: center;
      justify-content: center;
      border-radius: var(--radius-md);
      color: var(--text-muted);
    }

    .attach-btn:hover {
      color: var(--accent);
    }

    .message-input {
      flex: 1;
      border: none;
      background: transparent;
      color: var(--text-primary);
      padding: var(--space-xs) var(--space-sm);
      resize: none;
      max-height: 120px;
      line-height: 1.5;
      font-size: var(--text-sm);
      outline: none;
    }

    .message-input::placeholder {
      color: var(--text-muted);
    }

    .send-btn {
      width: 36px;
      height: 36px;
      padding: 0;
      border-radius: var(--radius-md);
      flex-shrink: 0;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    .send-btn:disabled {
      opacity: 0.4;
      cursor: not-allowed;
    }
  </style>

  <script>
    import { ws } from '../services/websocket.js'
    import { api } from '../services/api.js'
    import { avatarFromEmail as _avatarFromEmail } from '../services/avatar.js'

    export default {
      avatarFromEmail: _avatarFromEmail,

      state: {
        inputValue: '',
        typingDisplay: '',
        showMembers: false,
        pendingImage: null,
        pendingImagePreview: null,
        uploading: false,
      },

      onMounted() {
        // Close the members popover when clicking anywhere outside the header controls.
        this._closeMembers = (e) => {
          if (this.state.showMembers && !this.$('.members-toggle')?.contains(e.target) && !this.$('.members-dropdown')?.contains(e.target)) {
            this.update({ showMembers: false })
          }
        }
        document.addEventListener('click', this._closeMembers)
      },

      onUnmounted() {
        document.removeEventListener('click', this._closeMembers)
        if (this.state.pendingImagePreview) {
          URL.revokeObjectURL(this.state.pendingImagePreview)
        }
      },

      toggleMembers(e) {
        e.stopPropagation()
        this.update({ showMembers: !this.state.showMembers })
      },

      onUpdated() {
        // Auto-resize textarea
        const textarea = this.$('textarea')
        if (textarea) {
          textarea.style.height = 'auto'
          textarea.style.height = Math.min(textarea.scrollHeight, 120) + 'px'
        }

        // Convert the raw typing user list into the small sentence shown under messages.
        const users = this.props.typingUsers || []
        let typingDisplay = ''
        if (users.length === 1) {
          typingDisplay = `${users[0].display_name} is typing...`
        } else if (users.length > 1) {
          typingDisplay = `${users.length} people are typing...`
        }
        if (typingDisplay !== this.state.typingDisplay) {
          this.state.typingDisplay = typingDisplay
        }
      },

      handleInput(e) {
        this.update({ inputValue: e.target.value })
        if (this.props.room) {
          ws.sendTyping(this.props.room.id)
        }
      },

      handleKeydown(e) {
        if (e.key === 'Enter' && !e.shiftKey) {
          e.preventDefault()
          this.handleSend()
        }
      },

      handlePaste(e) {
        const items = e.clipboardData?.items
        if (!items) return

        // Pasted screenshots feel like file attachments to the user,
        // so they go through the same preview/upload path as picked files.
        for (const item of items) {
          if (item.type.startsWith('image/')) {
            e.preventDefault()
            const file = item.getAsFile()
            if (file) this.attachImage(file)
            return
          }
        }
      },

      triggerFileInput() {
        this.$('[ref="fileInput"]')?.click()
      },

      handleFileSelect(e) {
        const file = e.target.files?.[0]
        if (file && file.type.startsWith('image/')) {
          this.attachImage(file)
        }
        e.target.value = '' // reset so same file can be re-selected
      },

      attachImage(file) {
        // Revoke old preview URL
        if (this.state.pendingImagePreview) {
          URL.revokeObjectURL(this.state.pendingImagePreview)
        }
        const preview = URL.createObjectURL(file)
        this.update({
          pendingImage: file,
          pendingImagePreview: preview,
        })
      },

      removeImage() {
        if (this.state.pendingImagePreview) {
          URL.revokeObjectURL(this.state.pendingImagePreview)
        }
        this.update({
          pendingImage: null,
          pendingImagePreview: null,
        })
      },

      async handleSend() {
        const content = this.state.inputValue?.trim() || ''
        const hasImage = !!this.state.pendingImage

        if (!content && !hasImage) return

        // Intercept /clear command — room creator only
        if (content === '/clear') {
          if (this.props.user?.id === this.props.room?.created_by) {
            this.update({ inputValue: '' })
            const textarea = this.$('textarea')
            if (textarea) {
              textarea.value = ''
              textarea.style.height = 'auto'
            }
            this.props.cbClearRoom()
          }
          return
        }

        // Extract mentions (@ai or @{aiName} detection)
        // The server only needs to know whether the AI was mentioned, not the exact text match.
        const mentions = []
        const lc = content.toLowerCase()
        const aiName = this.props.room?.ai_name?.toLowerCase() || ''
        if (lc.includes('@ai') || (aiName && lc.includes(`@${aiName}`))) {
          mentions.push('ai-assistant')
        }

        let imageUrl = null

        // Upload image first if attached
        if (hasImage) {
          try {
            this.update({ uploading: true })
            const result = await api.uploadChatImage(this.state.pendingImage)
            imageUrl = result.url
          } catch (err) {
            // Keep the draft visible so the user can retry instead of losing the message.
            console.error('Failed to upload image:', err)
            this.update({ uploading: false })
            return
          }
        }

        // Clean up image preview
        if (this.state.pendingImagePreview) {
          URL.revokeObjectURL(this.state.pendingImagePreview)
        }

        this.props.cbSend({ content, mentions, imageUrl })
        this.update({
          inputValue: '',
          pendingImage: null,
          pendingImagePreview: null,
          uploading: false,
        })

        const textarea = this.$('textarea')
        if (textarea) {
          textarea.value = ''
          textarea.style.height = 'auto'
        }
      },

      isSearchTool(toolName) {
        return toolName === 'web_search' || toolName === 'brave_search'
      },
    }
  </script>
</chat-room>
