<template>
  <div class="w-full h-full">
    <canvas 
      ref="chartCanvas" 
      class="w-full h-full"
      :width="width" 
      :height="height"
    ></canvas>
  </div>
</template>

<script setup lang="ts">
interface ChartData {
  month: number
  monthName: string
  revenue: number
  expenses: number
  netCashFlow: number
  runningBalance: number
  oneOffEvents?: Array<{ type: string, amount: number, name: string }>
}

interface Props {
  data: ChartData[]
  viewMode: 'combined' | 'runway' | 'cashflow'
  width?: number
  height?: number
}

const props = withDefaults(defineProps<Props>(), {
  width: 800,
  height: 320
})

const chartCanvas = ref<HTMLCanvasElement | null>(null)

const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
                   'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']

function drawChart() {
  if (!chartCanvas.value || !props.data.length) return
  
  const canvas = chartCanvas.value
  const ctx = canvas.getContext('2d')
  if (!ctx) return
  
  // Clear canvas
  ctx.clearRect(0, 0, canvas.width, canvas.height)
  
  const padding = 60
  const chartWidth = canvas.width - padding * 2
  const chartHeight = canvas.height - padding * 2
  
  const dataLength = props.data.length
  const scaleX = chartWidth / (dataLength - 1)
  
  // Calculate data ranges based on view mode
  let maxValue = 0
  let minValue = 0
  
  if (props.viewMode === 'runway' || props.viewMode === 'combined') {
    const balances = props.data.map(d => d.runningBalance)
    maxValue = Math.max(maxValue, ...balances)
    minValue = Math.min(minValue, ...balances)
  }
  
  if (props.viewMode === 'cashflow' || props.viewMode === 'combined') {
    const revenues = props.data.map(d => d.revenue)
    const expenses = props.data.map(d => d.expenses)
    maxValue = Math.max(maxValue, ...revenues, ...expenses)
  }
  
  // Add some padding to the range
  const range = maxValue - minValue
  maxValue += range * 0.1
  minValue -= range * 0.1
  
  // Ensure we show zero line
  if (minValue > 0) minValue = Math.min(0, minValue)
  if (maxValue < 0) maxValue = Math.max(0, maxValue)
  
  const valueRange = maxValue - minValue
  const scaleY = valueRange > 0 ? chartHeight / valueRange : 1
  
  // Helper functions
  const getX = (index: number) => padding + (index * scaleX)
  const getY = (value: number) => padding + chartHeight - ((value - minValue) * scaleY)
  
  // Draw background for negative values
  if (minValue < 0) {
    const zeroY = getY(0)
    ctx.fillStyle = 'rgba(239, 68, 68, 0.1)'
    ctx.fillRect(padding, zeroY, chartWidth, canvas.height - zeroY - padding)
  }
  
  // Draw grid
  drawGrid(ctx, padding, chartWidth, chartHeight, minValue, maxValue, valueRange, scaleY)
  
  // Draw data based on view mode
  if (props.viewMode === 'cashflow' || props.viewMode === 'combined') {
    drawCashFlowData(ctx, getX, getY)
  }
  
  if (props.viewMode === 'runway' || props.viewMode === 'combined') {
    drawRunwayData(ctx, getX, getY)
  }
  
  // Draw one-off events
  drawOneOffEvents(ctx, getX, getY)
  
  // Draw axis labels
  drawAxisLabels(ctx, padding, chartWidth, chartHeight, minValue, maxValue, valueRange)
}

function drawGrid(ctx: CanvasRenderingContext2D, padding: number, chartWidth: number, chartHeight: number, minValue: number, maxValue: number, valueRange: number, scaleY: number) {
  ctx.strokeStyle = '#e5e7eb'
  ctx.lineWidth = 1
  
  // Horizontal grid lines
  const gridLines = 5
  for (let i = 0; i <= gridLines; i++) {
    const y = padding + (chartHeight / gridLines) * i
    ctx.beginPath()
    ctx.moveTo(padding, y)
    ctx.lineTo(padding + chartWidth, y)
    ctx.stroke()
  }
  
  // Vertical grid lines (every 3 months)
  for (let i = 0; i < props.data.length; i += 3) {
    const x = padding + (i * chartWidth) / (props.data.length - 1)
    ctx.beginPath()
    ctx.moveTo(x, padding)
    ctx.lineTo(x, padding + chartHeight)
    ctx.stroke()
  }
  
  // Zero line if applicable
  if (minValue < 0 && maxValue > 0) {
    const zeroY = padding + chartHeight - ((0 - minValue) * scaleY)
    ctx.strokeStyle = '#6b7280'
    ctx.lineWidth = 2
    ctx.beginPath()
    ctx.moveTo(padding, zeroY)
    ctx.lineTo(padding + chartWidth, zeroY)
    ctx.stroke()
  }
}

function drawCashFlowData(ctx: CanvasRenderingContext2D, getX: (i: number) => number, getY: (v: number) => number) {
  // Draw revenue line
  ctx.strokeStyle = '#3b82f6'
  ctx.lineWidth = 2
  ctx.beginPath()
  props.data.forEach((dataPoint, index) => {
    const x = getX(index)
    const y = getY(dataPoint.revenue)
    if (index === 0) {
      ctx.moveTo(x, y)
    } else {
      ctx.lineTo(x, y)
    }
  })
  ctx.stroke()
  
  // Draw expenses line
  ctx.strokeStyle = '#ef4444'
  ctx.lineWidth = 2
  ctx.beginPath()
  props.data.forEach((dataPoint, index) => {
    const x = getX(index)
    const y = getY(dataPoint.expenses)
    if (index === 0) {
      ctx.moveTo(x, y)
    } else {
      ctx.lineTo(x, y)
    }
  })
  ctx.stroke()
}

function drawRunwayData(ctx: CanvasRenderingContext2D, getX: (i: number) => number, getY: (v: number) => number) {
  // Draw balance line
  ctx.strokeStyle = '#10b981'
  ctx.lineWidth = 3
  ctx.beginPath()
  props.data.forEach((dataPoint, index) => {
    const x = getX(index)
    const y = getY(dataPoint.runningBalance)
    if (index === 0) {
      ctx.moveTo(x, y)
    } else {
      ctx.lineTo(x, y)
    }
  })
  ctx.stroke()
  
  // Mark zero crossing points
  ctx.fillStyle = '#ef4444'
  for (let i = 1; i < props.data.length; i++) {
    const prev = props.data[i - 1].runningBalance
    const current = props.data[i].runningBalance
    
    if (prev >= 0 && current < 0) {
      // Crossed from positive to negative
      const x = getX(i)
      const y = getY(0)
      ctx.beginPath()
      ctx.arc(x, y, 4, 0, 2 * Math.PI)
      ctx.fill()
      
      // Add warning label
      ctx.fillStyle = '#ef4444'
      ctx.font = '12px sans-serif'
      ctx.textAlign = 'center'
      ctx.fillText('Out of Money', x, y - 10)
      ctx.fillStyle = '#ef4444' // Reset for next point
    }
  }
}

function drawOneOffEvents(ctx: CanvasRenderingContext2D, getX: (i: number) => number, getY: (v: number) => number) {
  props.data.forEach((dataPoint, index) => {
    if (dataPoint.oneOffEvents && dataPoint.oneOffEvents.length > 0) {
      const x = getX(index)
      let yOffset = 0
      
      dataPoint.oneOffEvents.forEach(event => {
        const isIncome = event.type === 'income'
        const baseY = getY(isIncome ? dataPoint.revenue : dataPoint.expenses)
        const y = baseY + yOffset
        
        // Draw event marker
        ctx.fillStyle = isIncome ? '#8b5cf6' : '#f59e0b'
        ctx.beginPath()
        ctx.arc(x, y, 3, 0, 2 * Math.PI)
        ctx.fill()
        
        // Add tooltip-style label
        if (event.amount > 0) {
          ctx.fillStyle = isIncome ? '#8b5cf6' : '#f59e0b'
          ctx.font = '10px sans-serif'
          ctx.textAlign = 'center'
          const shortName = event.name.length > 15 ? event.name.substring(0, 12) + '...' : event.name
          ctx.fillText(shortName, x, y - 8)
        }
        
        yOffset += 15
      })
    }
  })
}

function drawAxisLabels(ctx: CanvasRenderingContext2D, padding: number, chartWidth: number, chartHeight: number, minValue: number, maxValue: number, valueRange: number) {
  ctx.fillStyle = '#6b7280'
  ctx.font = '12px sans-serif'
  
  // X-axis labels (months)
  ctx.textAlign = 'center'
  props.data.forEach((dataPoint, index) => {
    if (index % 2 === 0) { // Show every other month to avoid crowding
      const x = padding + (index * chartWidth) / (props.data.length - 1)
      ctx.fillText(monthNames[dataPoint.month], x, padding + chartHeight + 20)
    }
  })
  
  // Y-axis labels (values)
  ctx.textAlign = 'right'
  const gridLines = 5
  for (let i = 0; i <= gridLines; i++) {
    const value = minValue + (valueRange / gridLines) * (gridLines - i)
    const y = padding + (chartHeight / gridLines) * i + 4
    ctx.fillText(formatShort(value), padding - 10, y)
  }
}

function formatShort(value: number): string {
  if (Math.abs(value) >= 1000000) {
    return `${(value / 1000000).toFixed(1)}M`
  }
  if (Math.abs(value) >= 1000) {
    return `${(value / 1000).toFixed(0)}k`
  }
  return Math.round(value).toString()
}

// Watch for changes and redraw
watch(() => [props.data, props.viewMode], () => {
  nextTick(() => drawChart())
}, { deep: true })

onMounted(() => {
  nextTick(() => drawChart())
})
</script>