import { useSuspenseQuery } from '@suspensive/react-query';
import { truncate } from 'lodash-es';
import { Suspense } from 'react';
import { colors, preset } from 'tailwind-preset';
import { Card, CircleSpinner } from 'ui-components';

import { ErrorStandardLineIcon } from '@/components/icons/common/ErrorStandardLine';
import { ContainerIcon } from '@/components/icons/container';
import { HostIcon } from '@/components/icons/host';
import { ImageIcon } from '@/components/icons/image';
import { ReactECharts, ReactEChartsProps } from '@/components/ReactEcharts';
import { getSeverityColorMap } from '@/constants/charts';
import { CardHeader } from '@/features/malwares/pages/landing/CardHeader';
import { queries } from '@/queries';
import { Mode, useTheme } from '@/theme/ThemeContext';
import { getSeverityPrettyName, SeverityEnum } from '@/utils/enum';
import { abbreviateNumber } from '@/utils/number';
import { usePageNavigation } from '@/utils/usePageNavigation';

export interface TopNMalwareChartData {
  name: string;
  low: number;
  high: number;
  medium: number;
  critical: number;
  unknown: number;
}

function getChartOptions({ data, theme }: { data: TopNMalwareChartData[]; theme: Mode }) {
  const color = colors[theme === 'light' ? 'variables' : 'darkVariables'].DEFAULT;
  return {
    backgroundColor: 'transparent',
    title: {
      show: false,
    },
    textStyle: {
      fontFamily: preset.theme.extend.fontFamily.body.join(','),
    },
    dataset: {
      dimensions: [
        {
          name: 'name',
          displayName: 'Container Name',
        },
        {
          name: SeverityEnum.Critical,
          displayName: getSeverityPrettyName(SeverityEnum.Critical),
        },
        {
          name: SeverityEnum.High,
          displayName: getSeverityPrettyName(SeverityEnum.High),
        },
        {
          name: SeverityEnum.Medium,
          displayName: getSeverityPrettyName(SeverityEnum.Medium),
        },
        {
          name: SeverityEnum.Low,
          displayName: getSeverityPrettyName(SeverityEnum.Low),
        },
        {
          name: SeverityEnum.Unknown,
          displayName: getSeverityPrettyName(SeverityEnum.Unknown),
        },
      ],
      source: [...data].reverse(),
    },
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'shadow',
      },
      confine: true,
      borderWidth: 0,
      borderRadius: 5,
      backgroundColor: color['bg-page'],
      textStyle: {
        color: color['text-text-and-icon'],
        fontSize: '13px',
      },
    },
    legend: {
      show: false,
    },
    grid: {
      left: '2%',
      right: '5%',
      top: '10%',
      bottom: '10%',
      containLabel: true,
    },
    xAxis: {
      type: 'value',
      splitLine: {
        lineStyle: {
          opacity: 0.6,
          color: color['chart-splitline'],
        },
      },
      axisLabel: {
        fontSize: 10,
        fontWeight: 600,
        lineHeight: 13,
        color: color['chart-axislabel'],
        formatter: (value) => {
          return abbreviateNumber(value);
        },
      },
    },
    yAxis: {
      type: 'category',
      axisLabel: {
        formatter: (value: string) => {
          return truncate(value, { length: 20 });
        },
        fontSize: '13px',
        lineHeight: 18,
        color: color['text-text-and-icon'],
      },
      axisLine: {
        show: false,
      },
      axisTick: {
        show: false,
      },
    },
    series: [
      {
        type: 'bar',
        stack: 'total',
        color: getSeverityColorMap(theme)[SeverityEnum.Critical],
        cursor: 'pointer',
        barMaxWidth: 20,
      },
      {
        type: 'bar',
        stack: 'total',
        color: getSeverityColorMap(theme)[SeverityEnum.High],
        cursor: 'pointer',
        barMaxWidth: 20,
      },
      {
        type: 'bar',
        stack: 'total',
        color: getSeverityColorMap(theme)[SeverityEnum.Medium],
        cursor: 'pointer',
        barMaxWidth: 20,
      },
      {
        type: 'bar',
        stack: 'total',
        color: getSeverityColorMap(theme)[SeverityEnum.Low],
        cursor: 'pointer',
        barMaxWidth: 20,
      },
      {
        type: 'bar',
        stack: 'total',
        color: getSeverityColorMap(theme)[SeverityEnum.Unknown],
        cursor: 'pointer',
        barMaxWidth: 20,
      },
    ],
  } satisfies ReactEChartsProps['option'];
}

const mappings = {
  image: {
    title: 'Top container images having malware',
    icon: <ImageIcon />,
    path: '/malware/scans?nodeType=container_image',
  },
  host: {
    title: 'Top hosts having malware',
    icon: <HostIcon />,
    path: '/malware/scans?nodeType=host',
  },
  container: {
    title: 'Top containers having malware',
    icon: <ContainerIcon />,
    path: '/malware/scans?nodeType=container',
  },
} as const;

export const TopNMalwareCard = ({ type }: { type: 'image' | 'host' | 'container' }) => {
  const mapping = mappings[type];

  return (
    <Card className="rounded min-h-full flex flex-col">
      <CardHeader icon={mapping.icon} title={mapping.title} path={mapping.path} />
      <div className="flex-1">
        <Suspense
          fallback={
            <div className="flex-1 flex items-center justify-center h-[300px]">
              <CircleSpinner size="md" />
            </div>
          }
        >
          <TopNCardContent type={type} />
        </Suspense>
      </div>
    </Card>
  );
};

const TopNCardContent = ({ type }: { type: 'host' | 'container' | 'image' }) => {
  const { data } = useSuspenseQuery({
    ...queries.malware.top5MalwareAssets({ nodeType: type }),
  });
  const { mode } = useTheme();
  const chartOptions = getChartOptions({ data: data, theme: mode });
  const { navigate } = usePageNavigation();
  return (
    <div className="pb-2 h-[300px] flex items-center justify-center">
      {data.length ? (
        <ReactECharts
          option={chartOptions}
          onChartClick={({ id }: { id?: string }) => {
            if (!id) {
              console.warn('Missing node id to navigate to scan page');
              return;
            }
            if (type === 'host') {
              navigate(`/malware/scans?nodeType=host&hosts=${encodeURIComponent(id)}`);
            } else if (type === 'container') {
              navigate(
                `/malware/scans?nodeType=container&containers=${encodeURIComponent(id)}`,
              );
            } else if (type === 'image') {
              navigate(
                `/malware/scans?nodeType=container_image&containerImages=${encodeURIComponent(
                  id,
                )}`,
              );
            }
          }}
        />
      ) : (
        <div className="flex items-center justify-center gap-2 text-text-text-and-icon">
          <div className="h-6 w-6 shrink-0">
            <ErrorStandardLineIcon />
          </div>
          <div>No data available</div>
        </div>
      )}
    </div>
  );
};
