import Button from '@/components/Button';
import Card from '@/components/Card';
import Dropdown from '@/components/Dropdown';
import Menu from '@/components/menu/Menu';
import MenuItem from '@/components/menu/MenuItem';
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;
};

// Type guard to check if charts is DashboardOverviewCharts
function isOverviewCharts(
  charts: DashboardOverviewCharts | DashboardComparisonCharts
): charts is DashboardOverviewCharts {
  return 'deplesi' in charts;
}

// Type guard to check if charts is DashboardComparisonCharts
function isComparisonCharts(
  charts: DashboardOverviewCharts | DashboardComparisonCharts
): charts is DashboardComparisonCharts {
  return 'location' 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: '#10B981',
  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,
}: 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.location || 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',
      }}
      variant='bordered'
    >
      <div className='flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 mb-6'>
        <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'
            trigger={
              <Button
                variant='outline'
                color='none'
                className='text-neutral-500 hover:text-neutral-700 rounded-lg px-4 py-2 border-neutral-300'
                onClick={() => setOpen(!open)}
              >
                {chartTypeLabels[chartData]}{' '}
                <div className='divider divider-horizontal p-0 m-0 before:bg-neutral-300 after:bg-neutral-300'></div>
                <Icon icon='heroicons:chevron-down' width={20} height={20} />
              </Button>
            }
            className={{
              content: 'w-52 mt-3',
            }}
            controlled={open}
          >
            <Menu>
              <MenuItem
                title='Body weight'
                onClick={() => {
                  setChartData('body_weight');
                  setOpen(!open);
                }}
              />
              <MenuItem
                title='Performance'
                onClick={() => {
                  setChartData('performance');
                  setOpen(!open);
                }}
              />
              <MenuItem
                title='FCR'
                onClick={() => {
                  setChartData('fcr');
                  setOpen(!open);
                }}
              />
              <MenuItem
                title='Quality Control'
                onClick={() => {
                  setChartData('quality_control');
                  setOpen(!open);
                }}
              />
              <MenuItem
                title='Deplesi'
                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.location || 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}
                onClick={() => {
                  const newVisible = new Set(visibleSeries);
                  if (isVisible) {
                    newVisible.delete(series.id);
                  } else {
                    newVisible.add(series.id);
                  }
                  setVisibleSeries(newVisible);
                }}
                className={`flex items-center gap-2 px-3 py-2 rounded-lg border transition-colors ${
                  isVisible
                    ? 'border-neutral-400 bg-neutral-50'
                    : 'border-neutral-300 hover:bg-neutral-50'
                }`}
              >
                <div
                  className={`w-6 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={`text-sm ${isVisible ? 'text-neutral-900 font-medium' : 'text-neutral-700'}`}
                >
                  {series.label}
                </span>
                <Icon
                  icon='heroicons:information-circle'
                  width={16}
                  height={16}
                  className='text-neutral-400'
                />
              </button>
            );
          });
        })()}
      </div>

      {/* 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.location ||
                  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: 11, fill: '#9ca3af' }}
            tickLine={false}
            axisLine={{ stroke: '#e5e7eb' }}
            label={{
              value: 'Weeks',
              position: 'insideBottom',
              offset: -5,
              style: { fontSize: 12, fill: '#9ca3af' },
            }}
          />
          <YAxis
            tick={{ fontSize: 11, fill: '#9ca3af' }}
            tickLine={false}
            axisLine={{ stroke: '#e5e7eb' }}
            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.location ||
                  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 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.location ||
                  data.charts.flock ||
                  data.charts.kandang;
                seriesData = comparisonChart?.series || [];
                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);
              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;

              return [
                domainMin,
                Math.round(domainMin + step),
                Math.round(domainMin + step * 2),
                Math.round(domainMin + step * 3),
                domainMax,
              ];
            })()}
          />
          <Tooltip
            contentStyle={{
              backgroundColor: '#1f2937',
              border: 'none',
              borderRadius: '8px',
              padding: '8px 12px',
              color: 'white',
            }}
            labelStyle={{ color: 'white', marginBottom: '4px' }}
            itemStyle={{ color: 'white', fontSize: '12px' }}
            labelFormatter={(value) => `Week ${value}`}
            formatter={(
              value: number | undefined,
              name: string | undefined
            ) => {
              if (value === undefined || name === undefined) return ['', ''];

              // 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.location ||
                  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 unit = series?.unit || '';

              return [`${value} ${unit}`, name];
            }}
          />
          {/* 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.location ||
                data.charts.flock ||
                data.charts.kandang;
              seriesData = comparisonChart?.series || [];
            }

            return seriesData
              .filter((series) => visibleSeries.has(series.id))
              .map((series, index) => {
                const isStandard = series.id
                  .toString()
                  .toLowerCase()
                  .includes('std');
                // Use series.id directly as dataKey to match dataset fields
                const dataKey = series.id.toString();

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

export default DashboardLineChart;
