'use client'

import React, { useEffect, useRef, useState, type FC } from 'react'
import PropTypes from 'prop-types'
import { choices } from '../../../scripts/tokens/choices'
import { createChart, LineStyle, CrosshairMode, type LineWidth } from 'lightweight-charts'
import { ChartComponent } from '../ChartComponentLightWeight'
import {
  Bar,
  Doughnut,
  Pie,
  Line as LineChartJs
} from 'react-chartjs-2'
import {
  LineChart,
  Line,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip,
  ResponsiveContainer,
  Legend,
  RadialBarChart,
  Text as TextChart,
  PolarAngleAxis,
  RadialBar
} from 'recharts'
import { Text } from '../../atoms'
import { areaConfig, newAreaConfig } from '../ChartComponentLightWeight/chartConfig'
import { fi } from 'date-fns/locale'
import { getGlobalStyle } from '../../../helpers'

interface ChartData {
  labels: string[]
  datasets: Array<{
    label: string
    data: number[]
    backgroundColor: string[]
    borderColor: string[]
    borderWidth: number
  }>
}

interface ChartOptions {
  indexAxis: string
  elements: {
    bar: {
      borderWidth: number
    }
  }
  responsive: boolean
  plugins: {
    legend: {
      position: string
    }
    title: {
      display: boolean
    }
  }
  type: string
}

const dataTest: ChartData = {
  labels: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio'],
  datasets: [
    {
      label: 'ejemplo',
      data: [12, 19, 3, 5, 2, 3],
      backgroundColor: [
        'rgba(255, 99, 132, 0.2)',
        'rgba(54, 162, 235, 0.2)',
        'rgba(255, 206, 86, 0.2)',
        'rgba(75, 192, 192, 0.2)',
        'rgba(153, 102, 255, 0.2)',
        'rgba(255, 159, 64, 0.2)'
      ],
      borderColor: [
        'rgba(255, 99, 132, 1)',
        'rgba(54, 162, 235, 1)',
        'rgba(255, 206, 86, 1)',
        'rgba(75, 192, 192, 1)',
        'rgba(153, 102, 255, 1)',
        'rgba(255, 159, 64, 1)'
      ],
      borderWidth: 1
    }
  ]
}

let width: number, height: number, gradient: CanvasGradient

function getGradient (ctx: CanvasRenderingContext2D, chartArea: any) {
  const chartWidth = chartArea.right - chartArea.left
  const chartHeight = chartArea.bottom - chartArea.top

  if (!gradient || width !== chartWidth || height !== chartHeight) {
    // Crea el gradiente si no existe o si cambió el tamaño del gráfico
    width = chartWidth
    height = chartHeight
    gradient = ctx.createLinearGradient(0, chartArea.bottom, 0, chartArea.top)
    gradient.addColorStop(0, 'blue')
    gradient.addColorStop(0.5, 'yellow')
    gradient.addColorStop(1, 'red')
  }

  return gradient
}

const optionsTest: ChartOptions = {
  indexAxis: 'y',
  elements: {
    bar: {
      borderWidth: 2
    }
  },
  responsive: true,
  plugins: {
    legend: {
      position: 'right'
    },
    title: {
      display: true
    }
  },
  type: 'doughnut'
}

interface HorizontalBarChartProps {
  data?: ChartData
  options?: ChartOptions
}

export const HorizontalBarChart: FC<HorizontalBarChartProps> = ({ data, options }) => {
  const chartOptions = {
    ...options,
    plugins: {
      ...options?.plugins
    },
    elements: {
      line: {
        backgroundColor: (context: any) => {
          const { ctx, chartArea } = context.chart
          if (!chartArea) {
            // Si el área del gráfico aún no está lista, usa un color por defecto
            return 'rgba(0, 0, 0, 0.1)'
          }
          return getGradient(ctx, chartArea)
        }
      }
    }
  }
  return (
    <div className='header'>
      <div className='links'></div>
      <LineChartJs data={data ?? dataTest} options={chartOptions} />
    </div>
  )
}

export const HorizontalBarChartJs: FC<HorizontalBarChartProps> = ({ data, options }) => {
  return (
    <div className='header' style={{ width: '100%', height: '400px' }}>
      <ResponsiveContainer width="100%" height="100%">
        <LineChart
          width={500}
          height={300}
          data={data as any}
          margin={{
            top: 5,
            right: 30,
            left: 20,
            bottom: 5
          }}
        >
          <CartesianGrid strokeDasharray="5 5" />
          <XAxis dataKey="name" />
          <YAxis />
          <Tooltip />
          <Legend />
          <Line yAxisId={0} type="monotone" dataKey="pv" stroke={`${choices.color.brand.fuelYellow}`} strokeDasharray="5 5" />
          <Line type="monotone" dataKey="uv" stroke={`${choices.color.brand.kellyGreen}`} strokeDasharray="5 5" />
        </LineChart>
      </ResponsiveContainer>
    </div>
  )
}

interface CircleProps {
  data?: ChartData
  options?: ChartOptions
}

export const Circle: FC<CircleProps> = ({ data, options }) => {
  return (
    <div className='header'>
      <div className='links'></div>
      <Pie data={data ?? dataTest} options={options ?? optionsTest} />
    </div>
  )
}

Circle.propTypes = {
  data: PropTypes.any,
  options: PropTypes.any
}

interface DoughnutCharProps {
  data?: ChartData
  options?: ChartOptions
}

export const DoughnutChar: FC<DoughnutCharProps> = ({ data, options }) => {
  return (
    <div className='header'>
      <div className='links'></div>
      <Doughnut data={data ?? dataTest} options={options ?? optionsTest} />
    </div>
  )
}

DoughnutChar.propTypes = {
  data: PropTypes.any,
  options: PropTypes.any
}

interface BarChatProps {
  data?: ChartData
  options?: ChartOptions
}

export const BarChat: FC<BarChatProps> = ({ data, options }) => {
  return (
    <div className='header'>
      <div className='links'></div>
      <Bar data={data ?? dataTest} options={options ?? optionsTest} />
    </div>
  )
}

BarChat.propTypes = {
  data: PropTypes.any,
  options: PropTypes.any
}

export const LightweightChartComponent = () => {
  const chartRef = useRef(null)

  useEffect(() => {
    // Crear el gráfico y asociarlo con el div
    const chart = createChart(chartRef.current, {
      width: chartRef.current.clientWidth,
      height: chartRef.current.clientHeight
    })

    // Definir los datos y la serie
    const lineSeries = chart.addLineSeries()
    lineSeries.setData([
      { time: 1633072800, value: 70 },
      { time: 1633076400, value: 72 },
      { time: 1633080000, value: 75 },
      { time: 1633083600, value: 80 }
    ])

    // Limpiar el gráfico cuando el componente se desmonte
    return () => {
      chart.remove()
    }
  }, [])

  return <div ref={chartRef} style={{ width: '100%', height: '400px' }} />
}

export const LargeChartComponent = () => {
  const chartRef = useRef(null)

  useEffect(() => {
    // Crear el gráfico y asociarlo con el div
    const chart = createChart(chartRef.current, {
      width: chartRef.current.clientWidth,
      height: chartRef.current.clientHeight,
      layout: {
        backgroundColor: '#1E1E1E', // Fondo oscuro para la sección del gráfico
        textColor: '#D1D4D7' // Color del texto
      },
      grid: {
        vertLines: {
          color: '#333' // Color de las líneas verticales
        },
        horzLines: {
          color: '#333' // Color de las líneas horizontales
        }
      },
      crosshair: {
        mode: 0 // Modo de cruce (0=por defecto)
      },
      priceScale: {
        borderColor: '#555' // Color de borde del eje Y (de precios)
      },
      timeScale: {
        borderColor: '#555' // Color de borde del eje X (de tiempo)
      }
    })

    // Crear la serie de velas
    const candlestickSeries = chart.addCandlestickSeries({
      upColor: '#4fff00', // Color para las velas alcistas
      borderUpColor: '#4fff00', // Color de borde para las velas alcistas
      wickUpColor: '#4fff00', // Color de la mecha de las velas alcistas
      downColor: '#ff4976', // Color para las velas bajistas
      borderDownColor: '#ff4976', // Color de borde para las velas bajistas
      wickDownColor: '#ff4976' // Color de la mecha de las velas bajistas
    })

    // Datos de ejemplo para las velas (formato: [tiempo, apertura, cierre, mínimo, máximo])
    const candlestickData = [
      { time: 1633072800, open: 40000, high: 41000, low: 39000, close: 40500 },
      { time: 1633076400, open: 40500, high: 42000, low: 40000, close: 41500 },
      { time: 1633080000, open: 41500, high: 42500, low: 41000, close: 42000 },
      { time: 1633083600, open: 42000, high: 44000, low: 41500, close: 43000 },
      { time: 1633087200, open: 43000, high: 45000, low: 42000, close: 44000 },
      { time: 1633090800, open: 44000, high: 46000, low: 43000, close: 45000 },
      { time: 1633094400, open: 45000, high: 47000, low: 44000, close: 46000 },
      { time: 1633098000, open: 46000, high: 48000, low: 45500, close: 47000 }
    ]

    // Establecer los datos de la serie
    candlestickSeries.setData(candlestickData)

    // Suscripción para el movimiento del cruce (crosshair)
    chart.subscribeCrosshairMove(function (param) {
      if (!param || !param.time) return
      const price = param.seriesData.get(candlestickSeries)
      console.log(`Price at time ${param.time}: Open: ${price.open}, Close: ${price.close}`)
    })

    // Limpiar el gráfico cuando el componente se desmonte
    return () => {
      chart.remove()
    }
  }, [])

  return (
    <div
      ref={chartRef}
      style={{ width: '100%', height: '500px', position: 'relative' }}
    />
  )
}

export const SalesDashboardChart = () => {
  useEffect(() => {
    // Datos proporcionados
    const data = [
      { day: 'Domingos', totalSales: 20000 },
      { day: 'Lunes', totalSales: 0 },
      { day: 'Martes', totalSales: 35001.8 },
      { day: 'Miércoles', totalSales: 0 },
      { day: 'Jueves', totalSales: 1000 },
      { day: 'Viernes', totalSales: 0 },
      { day: 'Sábados', totalSales: 0 }
    ]

    // Convertir los días en un arreglo de fechas o índices (timestamps para un gráfico de líneas)
    const chartData = data.map((item, index) => ({
      time: index, // Usa un índice como "time"
      value: item.totalSales
    }))

    // Crear el gráfico
    const chart = createChart('chart-container', {
      width: 600,
      height: 400,
      crosshair: {
        mode: CrosshairMode.Normal
      }
    })

    // Crear la línea de ventas
    const lineSeries = chart.addLineSeries({
      color: '#4e73df',
      lineStyle: LineStyle.Solid,
      crosshairMarkerVisible: true,
      crosshairMarkerRadius: 5
    })

    // Establecer los datos en la serie
    lineSeries.setData(chartData.map((item) => ({ time: item.time, value: item.value })))
  }, [])

  return (
    <div id="chart-container" style={{ position: 'relative', width: '600px', height: '400px' }}></div>
  )
}

interface StockMovementsChartProps {
  className?: string
  width?: number
  title?: string
  height?: number
  chartData: Array<{
    date: string
    TotalIn: number
    TotalOut: number
  }>
}

export const StockMovementsChart: FC<StockMovementsChartProps> = ({
  chartData,
  className,
  width = 600,
  height = 400,
  title = ''
}) => {
  const stockOutData = chartData.map((item) => ({
    time: item.date,
    value: item.TotalOut
  }))

  const stockInData = chartData.map((item) => ({
    time: item.date,
    value: item.TotalIn
  }))

  const TotalAdjustment = chartData.map((item) => ({
    time: item.date,
    value: item.TotalAdjustment
  }))

  const dataSets = [
    { name: 'stock_in', data: stockInData, config: areaConfig },
    { name: 'stock_out', data: stockOutData, config: areaConfig },
    { name: 'total_adjustment', data: TotalAdjustment, config: { ...areaConfig, lineColor: 'rgba(187, 160, 6, 0.89)' } }
  ]

  return (
    <div className={className}>
      <Text size='5xl'>
        {title}
      </Text>
      <ChartComponent
        width={width}
        height={height}
        data={dataSets}
        currentPrice={{
          time: Date.now(),
          value: 19.10
        }}
      />
    </div>
  )
}

interface KmhGoalChartProps {
  current: number
  goal: number
  size?: number
  moneyFormat?: boolean
  numberFormat?: (value: number) => string
  bgColor?: string // Color del arco de fondo
  fgColor?: string // Color del arco de progreso
  strokeWidth?: number // Grosor del arco
  fontSize?: string // Tamaño de fuente para texto
  textColor?: string // Color del texto
  textWeight?: 'normal' | 'bold' | 'bolder' // Peso del texto
  rotateText?: boolean // Rotar el texto según el gráfico
  textPosition?: { x: string, y: string } // Personalización de la posición del texto
  showPercentage?: boolean // Mostrar o no el porcentaje
  orientation?: 'horizontal' | 'vertical' | 'full' // Orientación del gráfico
  startAngle?: number // Ángulo desde el que comienza la línea indicadora (0 a 360 grados)
  reverseDirection?: boolean // Invertir la dirección del gráfico
  strokeDasharray?: string // Personalización de la línea (opcional)
  ref?: React.RefObject<HTMLDivElement>
}

export const KmhGoalChart: React.FC<KmhGoalChartProps> = ({
  current,
  goal,
  size = 250,
  moneyFormat = false,
  numberFormat = (value: number) => value.toString(),
  bgColor = '#eee',
  fgColor = getGlobalStyle('--color-primary-red'),
  strokeWidth = 15,
  fontSize = 'calc(10px + 1vw)',
  textColor = '#333',
  textWeight = 'bold',
  rotateText = false,
  textPosition = { x: '50%', y: '58%' },
  showPercentage = true,
  orientation = 'horizontal', // Default to horizontal
  startAngle = 180, // Default starting at 180 degrees (top)
  reverseDirection = false,
  strokeDasharray = '', // Default to no dash pattern
  ref
}) => {
  const radius = 100
  const percentage = Math.min((current / goal) * 100, 100)

  // Calcular el ángulo en base al porcentaje
  const angle = (percentage / 100) * (orientation === 'full' ? 360 : 180)
  const adjustedStartAngle = reverseDirection ? startAngle + 180 : startAngle
  const endAngle = adjustedStartAngle - angle

  const polarToCartesian = (centerX: number, centerY: number, radius: number, angleInDegrees: number) => {
    const angleInRadians = ((angleInDegrees - 90) * Math.PI) / 180.0
    return {
      x: centerX + radius * Math.cos(angleInRadians),
      y: centerY + radius * Math.sin(angleInRadians)
    }
  }

  const describeArc = (x: number, y: number, radius: number, startAngle: number, endAngle: number) => {
    const start = polarToCartesian(x, y, radius, endAngle)
    const end = polarToCartesian(x, y, radius, startAngle)
    const largeArcFlag = startAngle - endAngle <= 180 ? '0' : '1'

    return [
      'M', start.x, start.y,
      'A', radius, radius, 0, largeArcFlag, 1, end.x, end.y
    ].join(' ')
  }

  const transformText = rotateText ? 'rotate(270)' : undefined

  return (
    <div style={{ width: 'fit-content', height: '100%', position: 'relative' }} ref={ref}>
      <svg
        width="100%"
        height="100%"
        viewBox="0 0 240 240"
        preserveAspectRatio="xMidYMid meet"
      >
        {/* Background arc */}
        <path
          d={describeArc(120, 120, radius, adjustedStartAngle, 0)}
          stroke={bgColor}
          strokeWidth={strokeWidth}
          rx="10"
          ry="10"
          fill="none"
          strokeLinecap="round"
          strokeDasharray={strokeDasharray} // Optional: Dash pattern
        />
        {/* Foreground arc */}
        <path
          d={describeArc(120, 120, radius, adjustedStartAngle, endAngle)}
          stroke={fgColor}
          strokeWidth={strokeWidth}
          fill="none"
          strokeLinecap="round"
          strokeDasharray={strokeDasharray} // Optional: Dash pattern
        />
        {/* Percentage text */}
        {showPercentage && (
          <text
            x="50%"
            y="58%"
            textAnchor="middle"
            style={{
              transform: 'translateY(-20px)'
            }}
            fontSize='calc(10px + 1vw)'
            fill={textColor}
            fontWeight={textWeight}
            transform={transformText}
          >
            {!isNaN(percentage) && percentage > 0 ? `${Math.round(percentage)}%` : '0%'}
          </text>
        )}
        {/* Additional text */}
        <text
          x={textPosition.x}
          y={textPosition.y}
          textAnchor="middle"
          fontSize={fontSize}

          fill="#666"
          transform={transformText}
        >
          {moneyFormat ? `${numberFormat(current)} de ${numberFormat(goal)}` : `${current} de ${goal}`}
        </text>
      </svg>
    </div>
  )
}
