<script setup lang="ts">
import {
  InputGroup,
  InputGroupTextarea,
  InputGroupAddon,
  InputGroupButton,
  InputGroupText,
} from '@/components/ui/input-group'
import { Separator } from '@/components/ui/separator'
import { ArrowUp, Loader2 } from 'lucide-vue-next'
import { useRoute } from 'vue-router'
import { useApi } from '@/composables/useApi'

interface ChatMessage {
  role: 'user' | 'assistant' | 'system';
  text: string;
  isStreaming?: boolean;
}

interface StreamEvent {
  type: string;
  data?: any;
  processId?: string;
  nodeId?: string;
  toolName?: string;
}

const chatInput = ref('')
const messages = ref<ChatMessage[]>([])
const sending = ref(false)
const route = useRoute()
const { api } = useApi()
const sessionId = ref<string | null>(null)
const eventSource = ref<EventSource | null>(null)

const getTenantId = () => {
  if (!import.meta.client) return 'tenant1'
  return localStorage.getItem('tenantId') || 'tenant1'
}

const buildContext = () => {
  const recordId = route.params.recordId ? String(route.params.recordId) : undefined
  const viewParam = route.params.view ? String(route.params.view) : undefined
  const view = viewParam || (recordId ? (recordId === 'new' ? 'edit' : 'detail') : 'list')
  const objectApiName = route.params.objectName
    ? String(route.params.objectName)
    : undefined

  return {
    objectApiName,
    view,
    recordId,
    route: route.fullPath,
  }
}

const connectToStream = (sessionIdValue: string) => {
  if (eventSource.value) {
    eventSource.value.close()
  }

  const baseUrl = window.location.hostname === 'localhost' 
    ? 'http://localhost:3000'
    : `https://${window.location.hostname}`
  
  eventSource.value = new EventSource(
    `${baseUrl}/tenants/${getTenantId()}/ai-chat/stream?sessionId=${sessionIdValue}`
  )

  eventSource.value.onmessage = (event) => {
    try {
      const payload: StreamEvent = JSON.parse(event.data)
      handleStreamEvent(payload)
    } catch (error) {
      console.error('Failed to parse stream event:', error)
    }
  }

  eventSource.value.onerror = () => {
    eventSource.value?.close()
    eventSource.value = null
  }
}

const handleStreamEvent = (event: StreamEvent) => {
  switch (event.type) {
    case 'agent_started':
      // Agent is thinking
      break
    case 'processes_listed':
      // Processes discovered
      break
    case 'process_selected':
      messages.value.push({
        role: 'system',
        text: `🔄 Selected process: ${event.data?.processName || 'Process'}`,
      })
      break
    case 'agent_message':
      messages.value.push({
        role: 'assistant',
        text: event.data?.message || '',
      })
      break
    case 'node_started':
      const lastMsg = messages.value[messages.value.length - 1]
      if (lastMsg?.isStreaming) {
        lastMsg.text += `\n⚙️ Executing step...`
      }
      break
    case 'tool_called':
      const lastToolMsg = messages.value[messages.value.length - 1]
      if (lastToolMsg?.isStreaming) {
        lastToolMsg.text += `\n🔧 Using tool: ${event.toolName}`
      }
      break
    case 'need_input':
      messages.value.push({
        role: 'assistant',
        text: event.data?.prompt || 'I need some additional information from you.',
      })
      sending.value = false
      break
    case 'final':
      if (event.data?.output) {
        messages.value.push({
          role: 'assistant',
          text: event.data.message || '✅ Process completed successfully!',
        })
      } else if (event.data?.reply) {
        messages.value.push({
          role: 'assistant',
          text: event.data.reply,
        })
      }
      sending.value = false
      break
    case 'error':
      messages.value.push({
        role: 'assistant',
        text: `❌ Error: ${event.data?.error || 'An error occurred'}`,
      })
      sending.value = false
      break
  }
}

const handleSend = async () => {
  if (!chatInput.value.trim()) return

  const message = chatInput.value.trim()
  messages.value.push({ role: 'user', text: message })
  chatInput.value = ''
  sending.value = true

  // Add a streaming message placeholder
  messages.value.push({ 
    role: 'assistant', 
    text: '🤔 Thinking...', 
    isStreaming: true 
  })

  try {
    const history = messages.value
      .filter(m => m.role !== 'system' && !m.isStreaming)
      .slice(0, -1)
      .slice(-6)
      .map(m => ({ role: m.role, text: m.text }))

    const response = await api.post(`/tenants/${getTenantId()}/ai-chat/messages`, {
      message,
      history,
      context: buildContext(),
      sessionId: sessionId.value || undefined,
    })

    if (response.sessionId && !sessionId.value) {
      sessionId.value = response.sessionId
      connectToStream(response.sessionId)
    }

    // Remove streaming placeholder and add response
    messages.value = messages.value.filter(m => !m.isStreaming)
    
    if (response.reply) {
      messages.value.push({
        role: 'assistant',
        text: response.reply,
      })
    }

    // If process is running, stream will handle updates
    if (response.runId) {
      messages.value.push({
        role: 'assistant',
        text: '⏳ Processing workflow...',
        isStreaming: true,
      })
    }
  } catch (error: any) {
    console.error('Failed to send AI chat message:', error)
    messages.value = messages.value.filter(m => !m.isStreaming)
    messages.value.push({
      role: 'assistant',
      text: error.message || 'Sorry, I ran into an error. Please try again.',
    })
  } finally {
    sending.value = false
  }
}

onUnmounted(() => {
  if (eventSource.value) {
    eventSource.value.close()
  }
})
</script>

<template>
  <div class="ai-chat-area w-full border-t border-border p-4 bg-neutral-50">
    <div class="ai-chat-messages mb-4 space-y-3 max-h-[400px] overflow-y-auto">
      <div
        v-for="(message, index) in messages"
        :key="`${message.role}-${index}`"
        class="flex"
        :class="message.role === 'user' ? 'justify-end' : 'justify-start'"
      >
        <div
          class="max-w-[80%] rounded-lg px-3 py-2 text-sm whitespace-pre-line"
          :class="{
            'bg-primary text-primary-foreground': message.role === 'user',
            'bg-white border border-border text-foreground': message.role === 'assistant',
            'bg-blue-50 border border-blue-200 text-blue-900 text-xs': message.role === 'system',
          }"
        >
          <Loader2 v-if="message.isStreaming" class="inline-block size-3 animate-spin mr-1" />
          {{ message.text }}
        </div>
      </div>
      <p v-if="messages.length === 0" class="text-sm text-muted-foreground">
        Ask the assistant to execute business processes, add records, or answer questions.
      </p>
    </div>
    <InputGroup>
      <InputGroupTextarea 
        v-model="chatInput"
        placeholder="Ask, Search or Chat..." 
        class="min-h-[60px] rounded-lg"
        @keydown.enter.exact.prevent="handleSend"
        :disabled="sending"
      />
      <InputGroupAddon>
        <InputGroupText class="ml-auto">
          52% used
        </InputGroupText>
        <Separator orientation="vertical" class="!h-4" />
        <InputGroupButton
          variant="default"
          class="rounded-full"
          :disabled="!chatInput.trim() || sending"
          @click="handleSend"
        >
          <ArrowUp class="size-4" />
          <span class="sr-only">Send</span>
        </InputGroupButton>
      </InputGroupAddon>
    </InputGroup>
  </div>
</template>

<style scoped>
.ai-chat-area {
  min-height: 190px;
}
</style>
