<template>
  <div class="graph-view">
    <div class="graph-header">
      <h1>Knowledge Graph</h1>
      <p>Explore relationships between auditees, findings, recommendations, and legal frameworks.</p>
    </div>

    <!-- Query Panel -->
    <div class="query-panel">
      <n-card title="Graph Queries" :bordered="false">
        <div class="query-grid">
          <n-button
            v-for="query in presetQueries"
            :key="query.id"
            quaternary
            class="query-btn"
            @click="runQuery(query.cypher)"
          >
            <template #icon>
              <n-icon><search-outline /></n-icon>
            </template>
            {{ query.label }}
          </n-button>
        </div>
        <n-divider />
        <n-input
          v-model:value="customQuery"
          type="textarea"
          placeholder="Enter Cypher query..."
          :autosize="{ minRows: 3, maxRows: 6 }"
          class="cypher-input"
        />
        <div class="query-actions">
          <n-button type="primary" @click="runQuery(customQuery)" :loading="isLoading">
            <template #icon><n-icon><play-outline /></n-icon></template>
            Run Query
          </n-button>
          <n-button quaternary @click="customQuery = ''">
            Clear
          </n-button>
        </div>
      </n-card>
    </div>

    <!-- Graph Visualization -->
    <div class="graph-visualization">
      <n-card :bordered="false" class="graph-card">
        <div v-if="isLoading" class="graph-loading">
          <n-spin size="large" />
          <p>Loading graph data...</p>
        </div>
        <div v-else-if="graphData.nodes.length === 0" class="graph-empty">
          <n-empty description="Run a query to visualize the knowledge graph">
            <template #icon>
              <n-icon size="48"><share-social-outline /></n-icon>
            </template>
          </n-empty>
        </div>
        <div v-else ref="graphContainer" class="graph-container">
          <v-chart class="chart" :option="chartOption" autoresize />
        </div>
      </n-card>
    </div>

    <!-- Results Panel -->
    <div v-if="queryResults.length > 0" class="results-panel">
      <n-card title="Query Results" :bordered="false">
        <n-data-table
          :columns="resultColumns"
          :data="queryResults"
          :pagination="{ pageSize: 10 }"
          size="small"
        />
      </n-card>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { GraphChart } from 'echarts/charts'
import { TooltipComponent, LegendComponent } from 'echarts/components'
import VChart from 'vue-echarts'
import { api } from '@/api/client'
import type { GraphData, GraphNode, GraphEdge } from '@/types'
import { SearchOutline, PlayOutline, ShareSocialOutline } from '@vicons/ionicons5'

use([CanvasRenderer, GraphChart, TooltipComponent, LegendComponent])

const isLoading = ref(false)
const customQuery = ref('')
const graphData = ref<GraphData>({ nodes: [], edges: [] })
const queryResults = ref<any[]>([])

const presetQueries = [
  {
    id: 'pending-recs',
    label: 'Pending Recommendations by Ministry',
    cypher: 'MATCH (a:Auditee)<-[:AUDITS]-(r:AuditReport)-[:CONTAINS]->(f:Finding)-[:RECOMMENDS]->(rec:Recommendation) WHERE rec.status = "Pending" RETURN a.name, rec.description, rec.deadline ORDER BY rec.deadline',
  },
  {
    id: 'county-findings',
    label: 'Findings by County (2023/24)',
    cypher: 'MATCH (a:Auditee)-[:AUDITS]-(r:AuditReport)-[:CONTAINS]->(f:Finding) WHERE r.fiscal_year = "2023/24" AND a.type = "county" RETURN a.name, count(f) as findings ORDER BY findings DESC',
  },
  {
    id: 'legal-refs',
    label: 'Most Cited Legal Provisions',
    cypher: 'MATCH (f:Finding)-[:CITES_LAW]->(l:LegalProvision) RETURN l.section, count(f) as citations ORDER BY citations DESC LIMIT 10',
  },
  {
    id: 'adverse-opinions',
    label: 'Adverse/Disclaimer Opinions',
    cypher: 'MATCH (r:AuditReport) WHERE r.audit_opinion IN ["adverse", "disclaimer"] RETURN r.title, r.auditee, r.fiscal_year, r.audit_opinion',
  },
  {
    id: 'amount-entities',
    label: 'Largest Financial Irregularities',
    cypher: 'MATCH (f:Finding)-[:INVOLVES_AMOUNT]->(a:FinancialAmount) RETURN f.description, a.value, a.currency ORDER BY a.value DESC LIMIT 20',
  },
]

const chartOption = computed(() => ({
  tooltip: {
    trigger: 'item',
    formatter: (params: any) => {
      if (params.dataType === 'node') {
        return `<strong>${params.data.label}</strong><br/>Type: ${params.data.type}`
      }
      return `${params.data.source} -> ${params.data.target}`
    },
  },
  legend: {
    data: ['Auditee', 'Report', 'Finding', 'Legal', 'Amount'],
    bottom: 0,
  },
  series: [
    {
      type: 'graph',
      layout: 'force',
      data: graphData.value.nodes.map((n: GraphNode) => ({
        id: n.id,
        name: n.label,
        label: n.label,
        type: n.type,
        symbolSize: n.type === 'auditee' ? 40 : n.type === 'report' ? 30 : 20,
        itemStyle: {
          color: getNodeColor(n.type),
        },
        category: n.type,
      })),
      links: graphData.value.edges.map((e: GraphEdge) => ({
        source: e.source,
        target: e.target,
        label: {
          show: true,
          formatter: e.type,
        },
      })),
      categories: [
        { name: 'Auditee' },
        { name: 'Report' },
        { name: 'Finding' },
        { name: 'Legal' },
        { name: 'Amount' },
      ],
      roam: true,
      label: {
        show: true,
        position: 'right',
        fontSize: 12,
      },
      force: {
        repulsion: 300,
        edgeLength: 100,
      },
      emphasis: {
        focus: 'adjacency',
        lineStyle: {
          width: 4,
        },
      },
    },
  ],
}))

const resultColumns = [
  { title: 'Property', key: 'property' },
  { title: 'Value', key: 'value' },
]

const getNodeColor = (type: string) => {
  const colors: Record<string, string> = {
    auditee: '#1a5fb4',
    report: '#26a269',
    finding: '#e5a50a',
    legal: '#c01c28',
    amount: '#9b59b6',
  }
  return colors[type] || '#7f8c8d'
}

const runQuery = async (cypher: string) => {
  if (!cypher.trim()) return

  isLoading.value = true
  try {
    const response = await api.graphQuery(cypher)
    graphData.value = response
    queryResults.value = response.nodes.map((n: GraphNode) => ({
      property: n.label,
      value: JSON.stringify(n.properties),
    }))
  } catch (error) {
    console.error('Graph query failed:', error)
  } finally {
    isLoading.value = false
  }
}
</script>

<style scoped lang="scss">
.graph-view {
  padding-bottom: 48px;
}

.graph-header {
  margin-bottom: 32px;

  h1 {
    font-size: 28px;
    font-weight: 700;
    margin-bottom: 8px;
  }

  p {
    color: var(--text-secondary);
    font-size: 15px;
  }
}

.query-panel {
  margin-bottom: 24px;
}

.query-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 8px;
  margin-bottom: 16px;
}

.query-btn {
  justify-content: flex-start;
  text-align: left;
  height: auto;
  padding: 8px 12px;
  font-size: 13px;
}

.cypher-input {
  font-family: 'SF Mono', Monaco, monospace;
  font-size: 13px;
}

.query-actions {
  display: flex;
  gap: 12px;
  margin-top: 12px;
}

.graph-visualization {
  margin-bottom: 24px;
}

.graph-card {
  min-height: 500px;
}

.graph-loading,
.graph-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 500px;
  gap: 16px;
}

.graph-container {
  height: 500px;
}

.chart {
  width: 100%;
  height: 100%;
}

.results-panel {
  margin-top: 24px;
}

@media (max-width: 768px) {
  .query-grid {
    grid-template-columns: 1fr;
  }
}
</style>
