<script setup lang="ts">
import { ref, watch, computed } from 'vue'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import { Separator } from '@/components/ui/separator'
import { useApi } from '@/composables/useApi'

type SemanticLink = {
  id: string
  source_entity_type: string
  source_entity_id: string
  target_entity_type: string
  target_entity_id: string
  source_entity_label?: string
  target_entity_label?: string
  source_entity_name?: string
  target_entity_name?: string
  link_type: string
  status: string
  origin: string
  confidence?: number
  reason?: string
  evidence?: any
  updated_at?: string
}

interface Props {
  objectApiName: string
  recordId: string
}

const props = defineProps<Props>()
const { api } = useApi()

const links = ref<SemanticLink[]>([])
const loading = ref(false)
const error = ref<string | null>(null)
const activeTab = ref<'all' | 'suggested' | 'approved' | 'rejected' | 'dismissed'>('suggested')

const formatDate = (value?: string) => {
  if (!value) return ''
  const date = new Date(value)
  if (Number.isNaN(date.getTime())) return value
  return date.toLocaleString()
}

const formatConfidence = (value?: number) => {
  if (value === undefined || value === null) return '—'
  return `${Math.round(value * 100)}%`
}

const getOtherSide = (link: SemanticLink) => {
  const isSource =
    link.source_entity_type === props.objectApiName &&
    link.source_entity_id === props.recordId
  return {
    entityType: isSource ? link.target_entity_type : link.source_entity_type,
    entityId: isSource ? link.target_entity_id : link.source_entity_id,
    entityLabel: isSource ? link.target_entity_label : link.source_entity_label,
    entityName: isSource ? link.target_entity_name : link.source_entity_name,
  }
}

const formatLinkType = (value?: string) => {
  if (!value) return 'Related'
  return value
    .replace(/_/g, ' ')
    .replace(/\b\w/g, (c) => c.toUpperCase())
}

const parseEvidence = (raw: any) => {
  if (!raw) return null
  if (typeof raw === 'object') return raw
  try {
    return JSON.parse(raw)
  } catch {
    return null
  }
}

const fetchLinks = async () => {
  if (!props.objectApiName || !props.recordId) return
  loading.value = true
  error.value = null
  try {
    const params =
      activeTab.value === 'all'
        ? undefined
        : { status: activeTab.value }
    const data = await api.get(`/knowledge/semantic/links/${props.objectApiName}/${props.recordId}`, {
      params,
    })
    links.value = Array.isArray(data) ? data : []
  } catch (e: any) {
    error.value = e.message || 'Failed to load semantic links'
  } finally {
    loading.value = false
  }
}

const reviewLink = async (id: string, status: 'approved' | 'rejected' | 'dismissed') => {
  try {
    await api.patch(`/knowledge/semantic/links/${id}/review`, { status })
    await fetchLinks()
  } catch (e: any) {
    error.value = e.message || 'Failed to update link'
  }
}

const canApprove = (status: string) => status !== 'approved'
const canReject = (status: string) => status !== 'rejected'
const canDismiss = (status: string) => status !== 'dismissed'

watch(
  () => [props.objectApiName, props.recordId, activeTab.value],
  () => {
    fetchLinks()
  },
  { immediate: true },
)
</script>

<template>
  <Card>
    <CardHeader class="flex flex-row items-center justify-between">
      <CardTitle>Semantic Links</CardTitle>
      <Button variant="ghost" size="sm" @click="fetchLinks">Refresh</Button>
    </CardHeader>
    <CardContent class="space-y-4">
      <Tabs v-model="activeTab" class="space-y-4">
        <TabsList>
          <TabsTrigger value="suggested">Suggested</TabsTrigger>
          <TabsTrigger value="approved">Approved</TabsTrigger>
          <TabsTrigger value="rejected">Rejected</TabsTrigger>
          <TabsTrigger value="dismissed">Dismissed</TabsTrigger>
          <TabsTrigger value="all">All</TabsTrigger>
        </TabsList>

        <TabsContent :value="activeTab" class="space-y-4">
          <div v-if="loading" class="text-sm text-muted-foreground">
            Loading links...
          </div>
          <div v-else-if="error" class="text-sm text-destructive">
            {{ error }}
          </div>
          <div v-else-if="links.length === 0" class="text-sm text-muted-foreground">
            No links found.
          </div>
          <div v-else class="space-y-4">
            <div
              v-for="link in links"
              :key="link.id"
              class="rounded-lg border p-4 space-y-3"
            >
              <div class="flex flex-wrap items-center justify-between gap-2">
                <div class="text-sm font-medium">
                  {{ getOtherSide(link).entityLabel || getOtherSide(link).entityType }} ·
                  {{ getOtherSide(link).entityName || getOtherSide(link).entityId }}
                </div>
                <div class="text-xs text-muted-foreground">
                  {{ formatLinkType(link.link_type) }} • {{ link.origin }} • {{ formatConfidence(link.confidence) }}
                </div>
              </div>

              <div class="text-xs text-muted-foreground">
                Status: <span class="font-medium text-foreground">{{ link.status }}</span>
                <span v-if="link.updated_at" class="ml-2">Updated: {{ formatDate(link.updated_at) }}</span>
              </div>

              <p v-if="link.reason" class="text-sm">{{ link.reason }}</p>

              <div v-if="parseEvidence(link.evidence)" class="text-xs text-muted-foreground space-y-2">
                <Separator />
                <div>
                  <div class="font-medium text-foreground">Evidence</div>
                  <p v-if="parseEvidence(link.evidence)?.explanation" class="mt-1 text-foreground">
                    {{ parseEvidence(link.evidence).explanation }}
                  </p>
                  <div v-if="parseEvidence(link.evidence)?.matchedSignals?.length" class="mt-2">
                    <div>Matched context:</div>
                    <ul class="list-disc pl-4">
                      <li
                        v-for="(signal, idx) in parseEvidence(link.evidence).matchedSignals"
                        :key="idx"
                      >
                        {{ signal }}
                      </li>
                    </ul>
                  </div>
                  <div v-if="parseEvidence(link.evidence)?.matchedChunks?.length" class="mt-2">
                    <div>Matched excerpts:</div>
                    <ul class="list-disc pl-4">
                      <li
                        v-for="(match, idx) in parseEvidence(link.evidence).matchedChunks"
                        :key="idx"
                      >
                        {{ match.sourceKind }}: {{ match.text }}
                      </li>
                    </ul>
                  </div>
                </div>
              </div>

              <div class="flex items-center gap-2">
                <Button
                  size="sm"
                  variant="outline"
                  @click="reviewLink(link.id, 'approved')"
                  :disabled="!canApprove(link.status)"
                >
                  Approve
                </Button>
                <Button
                  size="sm"
                  variant="outline"
                  @click="reviewLink(link.id, 'rejected')"
                  :disabled="!canReject(link.status)"
                >
                  Reject
                </Button>
                <Button
                  size="sm"
                  variant="outline"
                  @click="reviewLink(link.id, 'dismissed')"
                  :disabled="!canDismiss(link.status)"
                >
                  Dismiss
                </Button>
              </div>
            </div>
          </div>
        </TabsContent>
      </Tabs>
    </CardContent>
  </Card>
</template>
