

import type { ColumnDef, Row, RowData, Table } from "@tanstack/react-table";
import { observer } from "mobx-react";
import { useTheme } from "next-themes";
import { useParams } from "next/navigation";
import { useMemo } from "react";
import useSWR from "swr";
// buzzwareTech package imports
import type { ChartXAxisDateGrouping } from "@buzzwaretech/constants";
import {
    ANALYTICS_X_AXIS_VALUES,
    ANALYTICS_Y_AXIS_VALUES,
    CHART_COLOR_PALETTES,
    EChartModels,
} from "@buzzwaretech/constants";
import { useTranslation } from "@buzzwaretech/i18n";
import { Button } from "@buzzwaretech/propel/button";
import { BarChart } from "@buzzwaretech/propel/charts/bar-chart";
import { EmptyStateCompact } from "@buzzwaretech/propel/empty-state";
import type {
    ChartXAxisProperty,
    ChartYAxisMetric,
    TBarItem,
    TChart,
    TChartDatum,
} from "@buzzwaretech/types";
import { Download } from "lucide-react";
// buzzwareTech web components
import {
    generateExtendedColors,
    parseChartData,
} from "@/components/chart/utils";
// hooks
import { useAnalytics } from "@/hooks/store/use-analytics";
import { useProjectState } from "@/hooks/store/use-project-state";
import { AnalyticsService } from "@/services/analytics.service";
import { exportCSV } from "../export";
import { DataTable } from "../insight-table/data-table";
import { ChartLoader } from "../loaders";
import { generateBarColor } from "./utils";

declare module "@tanstack/react-table" {
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  interface ColumnMeta<TData extends RowData, TValue> {
    export: {
      key: string;
      value: (row: Row<TData>) => string | number;
      label?: string;
    };
  }
}

interface Props {
  x_axis: ChartXAxisProperty;
  y_axis: ChartYAxisMetric;
  group_by?: ChartXAxisProperty;
  x_axis_date_grouping?: ChartXAxisDateGrouping;
}

const analyticsService = new AnalyticsService();
const PriorityChart = observer(function PriorityChart(props: Props) {
  const { x_axis, y_axis, group_by } = props;
  const { t } = useTranslation();
  // store hooks
  const {
    selectedDuration,
    selectedProjects,
    selectedCycle,
    selectedModule,
    isPeekView,
    isEpic,
  } = useAnalytics();
  const { workspaceStates } = useProjectState();
  const { resolvedTheme } = useTheme();
  // router
  const params = useParams();
  const workspaceSlug = params.workspaceSlug.toString();

  const { data: priorityChartData, isLoading: priorityChartLoading } = useSWR(
    `customized-insights-chart-${workspaceSlug}-${selectedDuration}-
    ${selectedProjects}-${selectedCycle}-${selectedModule}-${props.x_axis}-${props.y_axis}-${props.group_by}-${isPeekView}-${isEpic}`,
    () =>
      analyticsService.getAdvanceAnalyticsCharts<TChart>(
        workspaceSlug,
        "custom-work-items",
        {
          // date_filter: selectedDuration,
          ...(selectedProjects?.length > 0 && {
            project_ids: selectedProjects?.join(","),
          }),
          ...(selectedCycle ? { cycle_id: selectedCycle } : {}),
          ...(selectedModule ? { module_id: selectedModule } : {}),
          ...(isEpic ? { epic: true } : {}),
          ...props,
        },
        isPeekView,
      ),
  );
  const parsedData = useMemo(
    () =>
      priorityChartData &&
      parseChartData(
        priorityChartData,
        props.x_axis,
        props.group_by,
        props.x_axis_date_grouping,
      ),
    [
      priorityChartData,
      props.x_axis,
      props.group_by,
      props.x_axis_date_grouping,
    ],
  );
  const chart_model = props.group_by
    ? EChartModels.STACKED
    : EChartModels.BASIC;

  const bars: TBarItem<string>[] = useMemo(() => {
    if (!parsedData) return [];
    let parsedBars: TBarItem<string>[];
    const schemaKeys = Object.keys(parsedData.schema);
    const baseColors =
      CHART_COLOR_PALETTES[0]?.[resolvedTheme === "dark" ? "dark" : "light"];
    const extendedColors = generateExtendedColors(
      baseColors ?? [],
      schemaKeys.length,
    );
    if (chart_model === EChartModels.BASIC) {
      parsedBars = [
        {
          key: "count",
          label: "Count",
          stackId: "bar-one",
          fill: (payload) =>
            generateBarColor(
              payload.key,
              { x_axis, y_axis, group_by },
              baseColors,
              workspaceStates,
            ),
          textClassName: "",
          showPercentage: false,
          showTopBorderRadius: () => true,
          showBottomBorderRadius: () => true,
        },
      ];
    } else if (chart_model === EChartModels.STACKED && parsedData.schema) {
      const parsedExtremes: {
        [key: string]: {
          top: string | null;
          bottom: string | null;
        };
      } = {};
      parsedData.data.forEach((datum) => {
        let top = null;
        let bottom = null;
        for (let i = 0; i < schemaKeys.length; i++) {
          const key = schemaKeys[i];
          if (datum[key] === 0) continue;
          if (!bottom) bottom = key;
          top = key;
        }
        parsedExtremes[datum.key] = { top, bottom };
      });

      parsedBars = schemaKeys.map((key, index) => ({
        key: key,
        label: parsedData.schema[key],
        stackId: "bar-one",
        fill: extendedColors[index],
        textClassName: "",
        showPercentage: false,
        showTopBorderRadius: (value, payload: TChartDatum) =>
          parsedExtremes[payload.key].top === value,
        showBottomBorderRadius: (value, payload: TChartDatum) =>
          parsedExtremes[payload.key].bottom === value,
      }));
    } else {
      parsedBars = [];
    }
    return parsedBars;
  }, [
    chart_model,
    group_by,
    parsedData,
    resolvedTheme,
    workspaceStates,
    x_axis,
    y_axis,
  ]);

  const yAxisLabel = useMemo(
    () =>
      ANALYTICS_Y_AXIS_VALUES.find((item) => item.value === props.y_axis)
        ?.label ?? props.y_axis,
    [props.y_axis],
  );
  const xAxisLabel = useMemo(
    () =>
      ANALYTICS_X_AXIS_VALUES.find((item) => item.value === props.x_axis)
        ?.label ?? props.x_axis,
    [props.x_axis],
  );

  const defaultColumns: ColumnDef<TChartDatum>[] = useMemo(
    () => [
      {
        accessorKey: "name",
        header: () => xAxisLabel,
        meta: {
          export: {
            key: xAxisLabel,
            value: (row) => row.original.name,
            label: xAxisLabel,
          },
        },
      },
      {
        accessorKey: "count",
        header: () => <div className="text-right">Count</div>,
        cell: ({ row }) => (
          <div className="text-right">{row.original.count}</div>
        ),
        meta: {
          export: {
            key: "Count",
            value: (row) => row.original.count,
            label: "Count",
          },
        },
      },
    ],
    [xAxisLabel],
  );

  const columns: ColumnDef<TChartDatum>[] = useMemo(
    () =>
      parsedData
        ? Object.keys(parsedData?.schema ?? {}).map((key) => ({
            accessorKey: key,
            header: () => (
              <div className="text-right">{parsedData.schema[key]}</div>
            ),
            cell: ({ row }) => (
              <div className="text-right">{row.original[key]}</div>
            ),
            meta: {
              export: {
                key,
                value: (row) => row.original[key],
                label: parsedData.schema[key],
              },
            },
          }))
        : [],
    [parsedData],
  );

  return (
    <div className="flex flex-col gap-12">
      {priorityChartLoading ? (
        <ChartLoader />
      ) : parsedData?.data && parsedData.data.length > 0 ? (
        <>
          <BarChart
            className="h-[370px] w-full"
            data={parsedData.data}
            bars={bars}
            margin={{
              bottom: 30,
            }}
            xAxis={{
              key: "name",
              label: xAxisLabel.replace("_", " "),
              dy: 30,
            }}
            yAxis={{
              key: "count",
              label: t("common.no_of", {
                entity: yAxisLabel.replace("_", " "),
              }),
              offset: -60,
              dx: -26,
            }}
          />
          <DataTable
            data={parsedData.data}
            columns={[...defaultColumns, ...columns]}
            searchPlaceholder={`${parsedData.data.length} ${xAxisLabel}`}
            actions={(table: Table<TChartDatum>) => (
              <Button
                variant="secondary"
                prependIcon={<Download className="h-3.5 w-3.5" />}
                onClick={() =>
                  exportCSV(
                    table.getRowModel().rows,
                    [...defaultColumns, ...columns],
                    workspaceSlug,
                  )
                }
              >
                <div>{t("exporter.csv.short_description")}</div>
              </Button>
            )}
          />
        </>
      ) : (
        <EmptyStateCompact
          assetKey="unknown"
          assetClassName="size-20"
          rootClassName="border border-subtle px-5 py-10 md:py-20 md:px-20"
          title={t("workspace_empty_state.analytics_work_items.title")}
        />
      )}
    </div>
  );
});

export default PriorityChart;
