import Button from '@/components/Button';
import Card from '@/components/Card';
import Dropdown from '@/components/Dropdown';
import DataStateSkeleton from '@/components/helper/skeleton/DataStateSkeleton';
import { OptionType } from '@/components/input/SelectInput';
import Menu from '@/components/menu/Menu';
import MenuItem from '@/components/menu/MenuItem';
import { formatNumber } from '@/lib/helper';
import {
  Dashboard,
  DashboardOverviewCharts,
  DashboardComparisonCharts,
  DashboardChartsSeries,
  DashboardChartsDataset,
} from '@/types/api/dashboard/dashboard';
import { Icon } from '@iconify/react';
import { useState, useEffect } from 'react';
import {
  CartesianGrid,
  Line,
  LineChart,
  ResponsiveContainer,
  Tooltip,
  XAxis,
  YAxis,
} from 'recharts';

type DashboardLineChartProps = {
  analysisMode: 'OVERVIEW' | 'COMPARISON';
  data: Dashboard;
  selectedKandang?: OptionType;
};

// Type guard to check if charts is DashboardOverviewCharts
function isOverviewCharts(
  charts: DashboardOverviewCharts | DashboardComparisonCharts | undefined
): charts is DashboardOverviewCharts {
  if (!charts) return false;
  return (
    'deplesi' in charts ||
    'body_weight' in charts ||
    'fcr' in charts ||
    'performance' in charts ||
    'quality_control' in charts
  );
}

// Type guard to check if charts is DashboardComparisonCharts
function isComparisonCharts(
  charts: DashboardOverviewCharts | DashboardComparisonCharts | undefined
): charts is DashboardComparisonCharts {
  if (!charts) return false;
  return 'farm' in charts || 'flock' in charts || 'kandang' in charts;
}

const lineColors: Record<string, string> = {
  body_weight: '#10B981',
  std_body_weight: '#10B981',
  act_laying: '#1062B9',
  std_laying: '#1062B9',
  act_egg_weight: '#10B981',
  std_egg_weight: '#10B981',
  act_feed_intake: '#F52419',
  std_feed_intake: '#F52419',
  act_uniformity: '#F59E0B',
  std_uniformity: '#F59E0B',
  act_fcr: '#10B981',
  std_fcr: '#10B981',
  act_fcr_cum: '#F52419',
  std_fcr_cum: '#F52419',
  normal: '#10B981',
  abnormal: '#F52419',
  act_deplesi: '#10B981',
  std_deplesi: '#10B981',
};

const defaultLineColors: string[] = [
  '#10B981',
  '#1062B9',
  '#F52419',
  '#F59E0B',
  '#7F56D9',
];

// Helper function to get line color
const getLineColor = (
  seriesId: string | number,
  index: number,
  mode: 'OVERVIEW' | 'COMPARISON'
): string => {
  // For COMPARISON mode, use default colors with cycling
  if (mode === 'COMPARISON') {
    return defaultLineColors[index % defaultLineColors.length];
  }

  // For OVERVIEW mode, use predefined colors or fallback to default
  const predefinedColor = lineColors[seriesId];
  if (predefinedColor) {
    return predefinedColor;
  }

  // Fallback to default colors with cycling
  return defaultLineColors[index % defaultLineColors.length];
};

const DashboardLineChart = ({
  analysisMode,
  data,
  selectedKandang,
}: DashboardLineChartProps) => {
  const [chartData, setChartData] =
    useState<keyof DashboardOverviewCharts>('body_weight');
  const [open, setOpen] = useState(false);
  // Track which series are visible (by series id)
  const [visibleSeries, setVisibleSeries] = useState<Set<string | number>>(
    new Set()
  );

  // Mapping for chart type labels
  const chartTypeLabels: Record<keyof DashboardOverviewCharts, string> = {
    body_weight: 'Body Weight',
    performance: 'Performance',
    fcr: 'FCR',
    quality_control: 'Quality Control',
    deplesi: 'Deplesi',
  };

  // Initialize all series as visible when chartData changes
  useEffect(() => {
    let seriesData: DashboardChartsSeries[] = [];

    if (analysisMode === 'OVERVIEW' && isOverviewCharts(data.charts)) {
      seriesData = data.charts[chartData]?.series || [];
    } else if (
      analysisMode === 'COMPARISON' &&
      isComparisonCharts(data.charts)
    ) {
      const comparisonChart =
        data.charts.farm || data.charts.flock || data.charts.kandang;
      seriesData = comparisonChart?.series || [];
    }

    // Set all series as visible by default
    const allSeriesIds = new Set(seriesData.map((s) => s.id));
    setVisibleSeries(allSeriesIds);
  }, [chartData, analysisMode, data.charts]);

  return (
    <Card
      className={{
        wrapper: 'w-full rounded-lg p-0',
        body: 'p-4',
      }}
      variant='bordered'
    >
      <div className='flex flex-col sm:flex-row justify-between items-start gap-4 mb-3'>
        <div className='text-lg font-semibold'>
          Performance{' '}
          <Icon
            icon='heroicons:information-circle'
            width={20}
            height={20}
            className='inline text-neutral-500'
          />
        </div>
        {analysisMode == 'OVERVIEW' && (
          <Dropdown
            align='end'
            direction='bottom'
            className={{
              content: 'mt-1 min-w-full',
            }}
            trigger={
              <Button
                variant='outline'
                color='none'
                className='py-2.5 pl-3 pr-2 text-base-content/50 rounded-lg text-sm border-base-content/10 shadow-button-soft'
                onClick={() => setOpen(!open)}
              >
                {chartTypeLabels[chartData]}{' '}
                <div className='w-6 h-5 flex items-center justify-center border-l border-base-content/10'>
                  <Icon icon='heroicons:chevron-down' width={14} height={14} />
                </div>
              </Button>
            }
            controlled={open}
          >
            <Menu className='p-0 w-full shadow-button-soft border border-base-content/10 rounded-lg'>
              <MenuItem
                title='Body weight'
                className='text-sm padding-3 whitespace-nowrap'
                onClick={() => {
                  setChartData('body_weight');
                  setOpen(!open);
                }}
              />
              <MenuItem
                title='Performance'
                className='text-sm padding-3 whitespace-nowrap'
                onClick={() => {
                  setChartData('performance');
                  setOpen(!open);
                }}
              />
              <MenuItem
                title='FCR'
                className='text-sm padding-3 whitespace-nowrap'
                onClick={() => {
                  setChartData('fcr');
                  setOpen(!open);
                }}
              />
              <MenuItem
                title='Quality Control'
                className='text-sm padding-3 whitespace-nowrap'
                onClick={() => {
                  setChartData('quality_control');
                  setOpen(!open);
                }}
              />
              <MenuItem
                title='Deplesi'
                className='text-sm padding-3 whitespace-nowrap'
                onClick={() => {
                  setChartData('deplesi');
                  setOpen(!open);
                }}
              />
            </Menu>
          </Dropdown>
        )}
      </div>

      {/* Legend - Dynamic based on series data */}
      <div className='flex flex-wrap gap-3 mb-6'>
        {(() => {
          // Get series data based on current mode and chartData
          let seriesData: DashboardChartsSeries[] = [];

          if (analysisMode === 'OVERVIEW' && isOverviewCharts(data.charts)) {
            seriesData = data.charts[chartData]?.series || [];
          } else if (
            analysisMode === 'COMPARISON' &&
            isComparisonCharts(data.charts)
          ) {
            const comparisonChart =
              data.charts.farm || data.charts.flock || data.charts.kandang;
            seriesData = comparisonChart?.series || [];
          }

          return seriesData.map((series, index) => {
            const isVisible = visibleSeries.has(series.id);
            const isStandard = series.id
              .toString()
              .toLowerCase()
              .includes('std');

            return (
              <Button
                key={`${series.id}-${index}`}
                onClick={() => {
                  const newVisible = new Set(visibleSeries);
                  if (isVisible) {
                    newVisible.delete(series.id);
                  } else {
                    newVisible.add(series.id);
                  }
                  setVisibleSeries(newVisible);
                }}
                variant='outline'
                color='none'
                className={`flex items-center gap-2 p-3 rounded-lg border transition-colors ${
                  isVisible
                    ? 'border-base-content/10 hover:bg-base-content/4'
                    : 'border-base-content/10 bg-base-content/4'
                }`}
              >
                <div
                  className={`w-5 h-0.5 ${
                    isStandard ? 'border-t-2 border-dashed' : ''
                  } ${!isVisible ? 'opacity-30' : ''}`}
                  style={{
                    backgroundColor: isStandard
                      ? 'transparent'
                      : getLineColor(series.id, index, analysisMode),
                    borderColor: isStandard
                      ? getLineColor(series.id, index, analysisMode)
                      : 'transparent',
                  }}
                ></div>
                <span
                  className={`font-semibold text-sm ${isVisible ? 'text-base-content/50' : 'text-base-content/50'}`}
                >
                  {series.label}
                </span>
                <Icon
                  icon='heroicons:eye'
                  width={16}
                  height={16}
                  className='text-base-content/40'
                />
              </Button>
            );
          });
        })()}
      </div>

      {/* Chart Container with Empty State Overlay */}
      <div className='relative'>
        {/* Chart */}
        <ResponsiveContainer width='100%' height={350}>
          <LineChart
            data={(() => {
              // Transform data based on analysisMode
              if (analysisMode === 'OVERVIEW') {
                // For OVERVIEW mode, use the selected chart data
                if (isOverviewCharts(data.charts)) {
                  const selectedChartData = data.charts[chartData];
                  if (!selectedChartData || !selectedChartData.dataset)
                    return [];
                  return selectedChartData.dataset;
                }
                return [];
              } else {
                // For COMPARISON mode, use the first available comparison chart
                if (isComparisonCharts(data.charts)) {
                  const chartData =
                    data.charts.farm ||
                    data.charts.flock ||
                    data.charts.kandang;

                  if (!chartData || !chartData.dataset) return [];
                  return chartData.dataset;
                }
                return [];
              }
            })()}
            margin={{
              top: 5,
              right: 10,
              left: 0,
              bottom: 5,
            }}
          >
            <CartesianGrid strokeDasharray='3 3' stroke='#e5e7eb' />
            <XAxis
              dataKey='week'
              tick={{
                fontSize: 12,
                fill: '#18181B',
                opacity: 0.5,
                fontWeight: 600,
              }}
              tickLine={false}
              axisLine={{ stroke: '#C1C1C180', opacity: 0.5 }}
              label={{
                value: 'Weeks',
                position: 'insideBottom',
                offset: -5,
                style: {
                  fontSize: 12,
                  fill: '#18181B',
                  opacity: 0.2,
                  fontWeight: 600,
                },
              }}
            />
            <YAxis
              tick={{
                fontSize: 12,
                fill: '#18181B',
                opacity: 0.5,
                fontWeight: 600,
              }}
              label={
                (chartData === 'body_weight' || chartData === 'performance') &&
                analysisMode === 'OVERVIEW'
                  ? {
                      value:
                        chartData === 'body_weight'
                          ? 'Body Weight'
                          : 'Percentage',
                      position: 'insideLeft',
                      angle: -90,
                      offset: 5,
                      style: {
                        fontSize: 12,
                        fill: '#18181B',
                        opacity: 0.2,
                        fontWeight: 600,
                      },
                    }
                  : analysisMode === 'COMPARISON'
                    ? {
                        value: 'Percentage',
                        position: 'insideLeft',
                        angle: -90,
                        offset: 5,
                        style: {
                          fontSize: 12,
                          fill: '#18181B',
                          opacity: 0.2,
                          fontWeight: 600,
                        },
                      }
                    : undefined
              }
              tickLine={false}
              axisLine={{ stroke: '#C1C1C180', opacity: 0.5 }}
              domain={(() => {
                // Calculate dynamic domain based on visible data
                // let seriesData: DashboardChartsSeries[] = [];
                let dataset: DashboardChartsDataset[] = [];

                if (
                  analysisMode === 'OVERVIEW' &&
                  isOverviewCharts(data.charts)
                ) {
                  // seriesData = data.charts[chartData]?.series || [];
                  dataset = data.charts[chartData]?.dataset || [];
                } else if (
                  analysisMode === 'COMPARISON' &&
                  isComparisonCharts(data.charts)
                ) {
                  const comparisonChart =
                    data.charts.farm ||
                    data.charts.flock ||
                    data.charts.kandang;
                  // seriesData = comparisonChart?.series || [];
                  dataset = comparisonChart?.dataset || [];
                }

                // Get all values from visible series
                const visibleSeriesIds = Array.from(visibleSeries);
                const allValues: number[] = [];

                dataset.forEach((item: DashboardChartsDataset) => {
                  visibleSeriesIds.forEach((seriesId) => {
                    const value = item[seriesId];
                    if (typeof value === 'number') {
                      allValues.push(value);
                    }
                  });
                });

                if (allValues.length === 0) return [0, 100];

                const minValue = Math.min(...allValues);
                const maxValue = Math.max(...allValues);

                // Add padding (10% on each side)
                const padding = (maxValue - minValue) * 0.1;
                const domainMin = Math.floor(Math.max(0, minValue - padding));
                const domainMax = Math.ceil(maxValue + padding);

                return [domainMin, domainMax];
              })()}
              ticks={(() => {
                // Calculate dynamic ticks based on domain
                let dataset: DashboardChartsDataset[] = [];

                if (
                  analysisMode === 'OVERVIEW' &&
                  isOverviewCharts(data.charts)
                ) {
                  dataset = data.charts[chartData]?.dataset || [];
                } else if (
                  analysisMode === 'COMPARISON' &&
                  isComparisonCharts(data.charts)
                ) {
                  const comparisonChart =
                    data.charts.farm ||
                    data.charts.flock ||
                    data.charts.kandang;
                  dataset = comparisonChart?.dataset || [];
                }

                const visibleSeriesIds = Array.from(visibleSeries);
                const allValues: number[] = [];

                dataset.forEach((item: DashboardChartsDataset) => {
                  visibleSeriesIds.forEach((seriesId) => {
                    const value = item[seriesId];
                    if (typeof value === 'number') {
                      allValues.push(value);
                    }
                  });
                });

                if (allValues.length === 0) return [0, 25, 50, 75, 100];

                const minValue = Math.min(...allValues);
                const maxValue = Math.max(...allValues);

                // Handle edge case where min equals max
                if (minValue === maxValue) {
                  const value = Math.round(minValue);
                  const padding = Math.max(10, Math.abs(value) * 0.2);
                  return [
                    Math.floor(value - padding),
                    Math.floor(value - padding / 2),
                    value,
                    Math.ceil(value + padding / 2),
                    Math.ceil(value + padding),
                  ];
                }

                const padding = (maxValue - minValue) * 0.1;
                const domainMin = Math.floor(Math.max(0, minValue - padding));
                const domainMax = Math.ceil(maxValue + padding);

                // Generate 5 evenly spaced ticks
                const range = domainMax - domainMin;
                const step = range / 4;

                // Use Set to ensure unique values
                const tickSet = new Set([
                  domainMin,
                  Math.round(domainMin + step),
                  Math.round(domainMin + step * 2),
                  Math.round(domainMin + step * 3),
                  domainMax,
                ]);

                return Array.from(tickSet).sort((a, b) => a - b);
              })()}
              tickFormatter={(value) => formatNumber(Number(value))}
            />
            <Tooltip
              contentStyle={{
                backgroundColor: '#1f2937',
                border: 'none',
                borderRadius: '8px',
                padding: '12px 12px',
                color: 'white',
              }}
              labelStyle={{ color: 'white', marginBottom: '4px' }}
              itemStyle={{ color: 'white', fontSize: '12px' }}
              labelFormatter={(value) => `Week ${value}`}
              content={(props) => {
                return (
                  <div className='flex flex-col gap-1.5 rounded-lg bg-neutral-950 p-4  text-white'>
                    <p className='text-white/50 text-xs font-semibold text-start'>
                      {analysisMode === 'OVERVIEW'
                        ? selectedKandang
                          ? selectedKandang.label || 'Overview Performance'
                          : 'Overview Performance'
                        : 'Comparison Performance'}
                    </p>
                    <ul className='flex flex-col gap-1'>
                      {props.payload.map((item, index) => {
                        if (item.name.startsWith('STD. ')) return null;
                        // Get series data to find the unit
                        let seriesData: DashboardChartsSeries[] = [];
                        if (
                          analysisMode === 'OVERVIEW' &&
                          isOverviewCharts(data.charts)
                        ) {
                          seriesData = data.charts[chartData]?.series || [];
                        } else if (
                          analysisMode === 'COMPARISON' &&
                          isComparisonCharts(data.charts)
                        ) {
                          const comparisonChart =
                            data.charts.farm ||
                            data.charts.flock ||
                            data.charts.kandang;
                          seriesData = comparisonChart?.series || [];
                        }

                        // Find the series that matches this line's name
                        const series = seriesData.find(
                          (s) => s.label === item.name
                        );
                        const color = series?.id
                          ? getLineColor(series.id, index, analysisMode)
                          : '#9ca3af';
                        const unit = series?.unit;

                        return (
                          <li
                            key={`${item.name}-${index}`}
                            className='flex w-full justify-between items-center flex-row gap-y-1.5 gap-x-3 p-0'
                          >
                            <span className='flex flex-row gap-1.5 items-center'>
                              <div
                                className='h-5 w-5 m-0 rounded'
                                style={{
                                  backgroundColor: color,
                                }}
                              ></div>
                              <div className='m-0'>
                                {formatNumber(item.value)}
                                {unit}
                              </div>
                            </span>
                            <span className='m-0'>{item.name}</span>
                          </li>
                        );
                      })}
                    </ul>
                    <p className='text-white/50 text-xs text-start'>
                      Week {props.label}
                    </p>
                  </div>
                );
              }}
              formatter={(
                value: number | undefined,
                name: string | undefined
              ) => {
                if (
                  value === undefined ||
                  name === undefined ||
                  name.startsWith('STD. ')
                )
                  return [undefined, undefined];

                // Get series data to find the unit
                let seriesData: DashboardChartsSeries[] = [];
                if (
                  analysisMode === 'OVERVIEW' &&
                  isOverviewCharts(data.charts)
                ) {
                  seriesData = data.charts[chartData]?.series || [];
                } else if (
                  analysisMode === 'COMPARISON' &&
                  isComparisonCharts(data.charts)
                ) {
                  const comparisonChart =
                    data.charts.farm ||
                    data.charts.flock ||
                    data.charts.kandang;
                  seriesData = comparisonChart?.series || [];
                }

                // Find the series that matches this line's name
                const series = seriesData.find((s) => s.label === name);
                const id = series?.id || '';

                return [value, id];
              }}
            />
            {/* Dynamic Line rendering based on visible series */}
            {(() => {
              let seriesData: DashboardChartsSeries[] = [];

              if (
                analysisMode === 'OVERVIEW' &&
                isOverviewCharts(data.charts)
              ) {
                seriesData = data.charts[chartData]?.series || [];
              } else if (
                analysisMode === 'COMPARISON' &&
                isComparisonCharts(data.charts)
              ) {
                const comparisonChart =
                  data.charts.farm || data.charts.flock || data.charts.kandang;
                seriesData = comparisonChart?.series || [];
              }

              return seriesData.map((series, originalIndex) => {
                // Skip rendering if series is not visible
                if (!visibleSeries.has(series.id)) {
                  return null;
                }

                const isStandard = series.id
                  .toString()
                  .toLowerCase()
                  .includes('std');
                const dataKey = series.id.toString();

                return (
                  <Line
                    key={`${series.id}--${originalIndex}`}
                    type='monotone'
                    dataKey={dataKey}
                    name={series.label}
                    stroke={getLineColor(
                      series.id,
                      originalIndex,
                      analysisMode
                    )}
                    opacity={isStandard ? 0.5 : 1}
                    strokeWidth={2}
                    strokeDasharray={isStandard ? '5 5' : undefined}
                    dot={
                      isStandard
                        ? false
                        : {
                            r: 3,
                            fill: '#fff',
                            stroke: getLineColor(
                              series.id,
                              originalIndex,
                              analysisMode
                            ),
                            strokeWidth: 2,
                          }
                    }
                    activeDot={isStandard ? undefined : { r: 5 }}
                  />
                );
              });
            })()}
          </LineChart>
        </ResponsiveContainer>

        {/* Empty State Overlay */}
        {(() => {
          // Get current dataset
          let dataset: DashboardChartsDataset[] = [];

          if (analysisMode === 'OVERVIEW' && isOverviewCharts(data.charts)) {
            dataset = data.charts[chartData]?.dataset || [];
          } else if (
            analysisMode === 'COMPARISON' &&
            isComparisonCharts(data.charts)
          ) {
            const comparisonChart =
              data.charts.farm || data.charts.flock || data.charts.kandang;
            dataset = comparisonChart?.dataset || [];
          }

          // Show empty state if dataset is empty
          if (dataset.length === 0) {
            return (
              <div className='absolute inset-x-0 inset-y-15 z-10 flex flex-col items-center justify-center rounded-lg'>
                {/* Chart icon */}
                <DataStateSkeleton
                  icon={
                    <Icon
                      icon='heroicons:chart-bar'
                      className='text-white'
                      width={20}
                      height={20}
                    />
                  }
                  title='Data Not Yet Available'
                  description='Please change your filters to get the data.'
                />
              </div>
            );
          }
          return null;
        })()}
      </div>
    </Card>
  );
};

export default DashboardLineChart;
