import { ref, computed } from 'vue'
import { useAuthStore } from 'src/stores/auth'

import { HUB_URL } from 'src/config/hub'

function agentHeaders (extra = {}) {
  try {
    const email = useAuthStore().user
    if (email && email !== 'authenticated') return { 'Content-Type': 'application/json', 'X-Authentik-Email': email, ...extra }
  } catch {}
  return { 'Content-Type': 'application/json', ...extra }
}

const conversations = ref([])
const discussions = ref([])
const activeToken = ref(null)
const activeDiscussion = ref(null)
const activeConv = ref(null)
const showAll = ref(true)
const loading = ref(false)
const panelOpen = ref(false)
const selectedIds = ref(new Set())
let sseSource = null

export function useConversations () {
  async function fetchList () {
    loading.value = true
    try {
      const url = showAll.value ? `${HUB_URL}/conversations?all=1` : `${HUB_URL}/conversations`
      const res = await fetch(url)
      if (res.ok) {
        const data = await res.json()
        conversations.value = data.conversations || []
        discussions.value = data.discussions || []
      }
    } catch {}
    loading.value = false
  }

  function openDiscussion (disc) {
    activeDiscussion.value = disc; activeToken.value = null; activeConv.value = null
    const active = disc.conversations.find(c => c.status === 'active')
    if (active) activeToken.value = active.token
    connectDiscussionSSE(disc.conversations.map(c => c.token))
  }

  async function openConversation (token) {
    activeToken.value = token
    try { const res = await fetch(`${HUB_URL}/conversations/${token}`); if (res.ok) activeConv.value = await res.json() } catch {}
    connectSSE(token)
  }

  function connectDiscussionSSE (tokens) {
    if (sseSource) sseSource.close()
    sseSource = new EventSource(`${HUB_URL}/sse?topics=${tokens.map(t => 'conv:' + t).concat(['conversations']).join(',')}`)
    sseSource.addEventListener('conv-message', e => {
      try {
        const data = JSON.parse(e.data)
        if (activeDiscussion.value && data.message) {
          const msg = { ...data.message, convToken: data.token }
          if (!activeDiscussion.value.messages.find(m => m.id === msg.id)) activeDiscussion.value.messages.push(msg)
        }
        updateListFromMessage(data)
      } catch {}
    })
    sseSource.addEventListener('conv-closed', handleConvClosed)
    sseSource.addEventListener('conv-deleted', () => fetchList())
  }

  function updateListFromMessage (data) {
    const idx = conversations.value.findIndex(c => c.token === data.token)
    if (idx >= 0) {
      conversations.value[idx].lastMessage = data.message
      conversations.value[idx].lastActivity = data.message.ts
      conversations.value[idx].messageCount++
    } else fetchList()
  }

  function handleConvClosed (e) {
    try {
      const data = JSON.parse(e.data)
      const idx = conversations.value.findIndex(c => c.token === data.token)
      if (idx >= 0) conversations.value[idx].status = 'closed'
      if (activeConv.value && data.token === activeToken.value) activeConv.value.status = 'closed'
    } catch {}
  }

  function connectSSE (token) {
    if (sseSource) sseSource.close()
    sseSource = new EventSource(`${HUB_URL}/sse?topics=conv:${token},conversations`)
    sseSource.addEventListener('conv-message', e => {
      try {
        const data = JSON.parse(e.data)
        if (activeConv.value && data.token === activeToken.value && data.message) {
          if (!activeConv.value.messages.find(m => m.id === data.message.id)) activeConv.value.messages.push(data.message)
        }
        updateListFromMessage(data)
      } catch {}
    })
    sseSource.addEventListener('conv-closed', handleConvClosed)
    sseSource.addEventListener('conv-deleted', () => fetchList())
  }

  function connectGlobalSSE () {
    if (sseSource) sseSource.close()
    sseSource = new EventSource(`${HUB_URL}/sse?topics=conversations`)
    sseSource.addEventListener('conv-message', e => { try { updateListFromMessage(JSON.parse(e.data)) } catch {} })
    sseSource.addEventListener('conv-deleted', () => fetchList())
  }

  async function sendMessage (token, text) {
    const res = await fetch(`${HUB_URL}/conversations/${token}/messages`, { method: 'POST', headers: agentHeaders(), body: JSON.stringify({ text }) })
    if (!res.ok) throw new Error('Failed to send')
    return res.json()
  }

  async function startConversation ({ phone, customer, customerName, subject }) {
    const res = await fetch(`${HUB_URL}/conversations`, { method: 'POST', headers: agentHeaders(), body: JSON.stringify({ phone, customer, customerName, subject }) })
    if (!res.ok) throw new Error('Failed to create conversation')
    const data = await res.json(); await fetchList(); return data
  }

  async function closeConversation (token) {
    await fetch(`${HUB_URL}/conversations/${token}/close`, { method: 'POST', headers: agentHeaders() })
    if (activeConv.value && activeToken.value === token) activeConv.value.status = 'closed'
    const idx = conversations.value.findIndex(c => c.token === token)
    if (idx >= 0) conversations.value[idx].status = 'closed'
  }

  async function deleteDiscussion (disc) {
    const res = await fetch(`${HUB_URL}/conversations/discussion`, {
      method: 'DELETE', headers: agentHeaders(),
      body: JSON.stringify({ phone: disc.phone, date: disc.id.includes(':active') ? 'active' : disc.date }),
    })
    if (!res.ok) throw new Error('Failed to delete')
    clearActiveIfMatch(disc); await fetchList()
  }

  async function bulkDelete (discs) {
    const res = await fetch(`${HUB_URL}/conversations/bulk`, {
      method: 'DELETE', headers: agentHeaders(),
      body: JSON.stringify({ discussions: discs.map(d => ({ tokens: d.conversations.map(c => c.token) })) }),
    })
    if (!res.ok) throw new Error('Failed to bulk delete')
    const data = await res.json()
    for (const d of discs) clearActiveIfMatch(d)
    selectedIds.value.clear(); await fetchList(); return data
  }

  async function archiveDiscussion (disc) {
    const res = await fetch(`${HUB_URL}/conversations/archive`, {
      method: 'POST', headers: agentHeaders(),
      body: JSON.stringify({ tokens: disc.conversations.map(c => c.token) }),
    })
    if (!res.ok) { const err = await res.json().catch(() => ({})); throw new Error(err.error || 'Archive failed') }
    const data = await res.json(); clearActiveIfMatch(disc); await fetchList(); return data
  }

  async function bulkArchive (discs) {
    const results = []
    for (const d of discs) {
      const res = await fetch(`${HUB_URL}/conversations/archive`, {
        method: 'POST', headers: agentHeaders(),
        body: JSON.stringify({ tokens: d.conversations.map(c => c.token) }),
      })
      if (res.ok) results.push(await res.json())
    }
    selectedIds.value.clear(); await fetchList(); return results
  }

  function clearActiveIfMatch (disc) {
    if (activeDiscussion.value?.id === disc.id) { activeDiscussion.value = null; activeToken.value = null; activeConv.value = null }
  }

  function toggleSelect (discId) {
    const s = new Set(selectedIds.value)
    s.has(discId) ? s.delete(discId) : s.add(discId)
    selectedIds.value = s
  }

  function selectAll () { selectedIds.value = new Set(discussions.value.map(d => d.id)) }
  function clearSelection () { selectedIds.value = new Set() }

  const selectedDiscussions = computed(() => discussions.value.filter(d => selectedIds.value.has(d.id)))

  function disconnectSSE () { if (sseSource) { sseSource.close(); sseSource = null } }

  function goBack () {
    activeToken.value = null; activeConv.value = null; activeDiscussion.value = null
    if (sseSource) sseSource.close()
    connectGlobalSSE()
  }

  const activeCount = computed(() => discussions.value.filter(d => d.status === 'active').length)

  return {
    conversations, discussions, activeToken, activeDiscussion, activeConv,
    loading, panelOpen, showAll, selectedIds, selectedDiscussions,
    fetchList, openDiscussion, openConversation, sendMessage, startConversation,
    closeConversation, deleteDiscussion, bulkDelete, archiveDiscussion, bulkArchive,
    toggleSelect, selectAll, clearSelection,
    goBack, disconnectSSE, connectGlobalSSE, activeCount, HUB_URL,
  }
}
