import type { MutableRefObject } from 'react'
import type { Chart, Plugin } from 'chart.js'

import type { SlotData } from '../../types/dashboard'

export type NegWeekendRange = { start: number; end: number }

const SELL_NEG = 'rgba(226,75,74,0.07)'
const BUY_NEG = 'rgba(29,158,117,0.07)'
const WEEKEND_NEG = 'rgba(239,159,39,0.07)'

function isWeekendPrague(iso: string): boolean {
  const w = new Date(iso).toLocaleDateString('en-US', { timeZone: 'Europe/Prague', weekday: 'short' })
  return w === 'Sat' || w === 'Sun'
}

export function computeNegWeekendRanges(slots: SlotData[], nowIndex: number): NegWeekendRange[] {
  const ranges: NegWeekendRange[] = []
  let i = 0
  const n = slots.length
  while (i < n) {
    if (i <= nowIndex) {
      i += 1
      continue
    }
    const s = slots[i]!
    const buy = s.buy_price
    if (!(buy != null && buy < 0 && isWeekendPrague(s.interval_start))) {
      i += 1
      continue
    }
    const start = i
    while (
      i < n &&
      slots[i]!.buy_price != null &&
      slots[i]!.buy_price! < 0 &&
      isWeekendPrague(slots[i]!.interval_start)
    ) {
      i += 1
    }
    ranges.push({ start, end: i })
  }
  return ranges
}

export function createSlotBackgroundPlugin(
  slots: SlotData[],
  _nowIndex: number,
  negWeekendRanges: NegWeekendRange[],
): Plugin {
  return {
    id: 'emsSlotBg',
    beforeDatasetsDraw(chart: Chart) {
      const { ctx, chartArea } = chart
      if (!chartArea || !slots.length) return
      const n = slots.length
      const w = chartArea.width / n

      for (let i = 0; i < n; i++) {
        const s = slots[i]!
        const x0 = chartArea.left + i * w
        let fill: string | null = null
        if (s.sell_price != null && s.sell_price < 0) fill = SELL_NEG
        else if (s.buy_price != null && s.buy_price < 0) fill = BUY_NEG
        if (fill) {
          ctx.save()
          ctx.fillStyle = fill
          ctx.fillRect(x0, chartArea.top, w, chartArea.bottom - chartArea.top)
          ctx.restore()
        }
      }

      for (const r of negWeekendRanges) {
        if (r.start >= n || r.end <= r.start) continue
        const x0 = chartArea.left + r.start * w
        const x1 = chartArea.left + r.end * w
        ctx.save()
        ctx.fillStyle = WEEKEND_NEG
        ctx.fillRect(x0, chartArea.top, x1 - x0, chartArea.bottom - chartArea.top)
        ctx.strokeStyle = 'rgba(239,159,39,0.45)'
        ctx.setLineDash([4, 3])
        ctx.lineWidth = 1
        ctx.strokeRect(x0 + 0.5, chartArea.top + 0.5, x1 - x0 - 1, chartArea.bottom - chartArea.top - 1)
        ctx.restore()
      }
    },
  }
}

/** Pozadí slotů – čte aktuální slots z ref (bez přepínání instance grafu). */
export function createSlotBackgroundPluginRefs(
  slotsRef: MutableRefObject<SlotData[]>,
  negRangesRef: MutableRefObject<NegWeekendRange[]>,
): Plugin {
  return {
    id: 'emsSlotBgRef',
    beforeDatasetsDraw(chart: Chart) {
      const { ctx, chartArea } = chart
      const slots = slotsRef.current
      const negWeekendRanges = negRangesRef.current
      if (!chartArea || !slots.length) return
      const n = slots.length
      const w = chartArea.width / n

      for (let i = 0; i < n; i++) {
        const s = slots[i]!
        const x0 = chartArea.left + i * w
        let fill: string | null = null
        if (s.sell_price != null && s.sell_price < 0) fill = SELL_NEG
        else if (s.buy_price != null && s.buy_price < 0) fill = BUY_NEG
        if (fill) {
          ctx.save()
          ctx.fillStyle = fill
          ctx.fillRect(x0, chartArea.top, w, chartArea.bottom - chartArea.top)
          ctx.restore()
        }
      }

      for (const r of negWeekendRanges) {
        if (r.start >= n || r.end <= r.start) continue
        const x0 = chartArea.left + r.start * w
        const x1 = chartArea.left + r.end * w
        ctx.save()
        ctx.fillStyle = WEEKEND_NEG
        ctx.fillRect(x0, chartArea.top, x1 - x0, chartArea.bottom - chartArea.top)
        ctx.strokeStyle = 'rgba(239,159,39,0.45)'
        ctx.setLineDash([4, 3])
        ctx.lineWidth = 1
        ctx.strokeRect(x0 + 0.5, chartArea.top + 0.5, x1 - x0 - 1, chartArea.bottom - chartArea.top - 1)
        ctx.restore()
      }
    },
  }
}

/** Čára „teď“ – index z ref. */
export function createNowLinePluginRef(nowIndexRef: MutableRefObject<number>, label: string): Plugin {
  return {
    id: 'emsNowLineRef',
    afterDatasetsDraw(chart: Chart) {
      const nowIndex = nowIndexRef.current
      const { ctx, chartArea } = chart
      const labels = chart.data.labels
      if (!chartArea || !labels?.length) return
      const n = labels.length
      if (nowIndex < 0 || nowIndex >= n) return
      const w = chartArea.width / n
      const x = chartArea.left + nowIndex * w

      ctx.save()
      ctx.beginPath()
      ctx.strokeStyle = '#378ADD'
      ctx.setLineDash([5, 4])
      ctx.lineWidth = 1.5
      ctx.moveTo(x, chartArea.top)
      ctx.lineTo(x, chartArea.bottom)
      ctx.stroke()

      ctx.setLineDash([])
      ctx.fillStyle = '#378ADD'
      ctx.font = '600 10px system-ui, sans-serif'
      ctx.textAlign = 'left'
      ctx.textBaseline = 'top'
      ctx.fillText(label, Math.min(x + 3, chartArea.right - 28), chartArea.top + 2)
      ctx.restore()
    },
  }
}

export function createNowLinePlugin(nowIndex: number, label: string): Plugin {
  return {
    id: 'emsNowLine',
    afterDatasetsDraw(chart: Chart) {
      const { ctx, chartArea } = chart
      const labels = chart.data.labels
      if (!chartArea || !labels?.length) return
      const n = labels.length
      if (nowIndex < 0 || nowIndex >= n) return
      const w = chartArea.width / n
      const x = chartArea.left + nowIndex * w

      ctx.save()
      ctx.beginPath()
      ctx.strokeStyle = '#378ADD'
      ctx.setLineDash([5, 4])
      ctx.lineWidth = 1.5
      ctx.moveTo(x, chartArea.top)
      ctx.lineTo(x, chartArea.bottom)
      ctx.stroke()

      ctx.setLineDash([])
      ctx.fillStyle = '#378ADD'
      ctx.font = '600 10px system-ui, sans-serif'
      ctx.textAlign = 'left'
      ctx.textBaseline = 'top'
      ctx.fillText(label, Math.min(x + 3, chartArea.right - 28), chartArea.top + 2)
      ctx.restore()
    },
  }
}
