import { ResponsiveBar } from "@nivo/bar";
import { format, startOfMonth, subMonths, addMonths } from "date-fns";
import { DollarSign } from "lucide-react";
import { useGetList, useLocaleState, useTranslate } from "ra-core";
import { memo, useMemo } from "react";
import { getDateFnsLocale } from "@/i18n/date-fns";
import { Skeleton } from "@/components/ds/ui/skeleton";

import type { Deal } from "../types";

const stageMultiplier: Record<string, number> = {
  opportunity: 0.2,
  "proposal-sent": 0.5,
  "in-negotiation": 0.8,
  "in-negociation": 0.8, // Legacy spelling support
  delayed: 0.3,
};

const DEFAULT_LOCALE = "en-US";
const CURRENCY = "USD";

export const DealsChart = memo(() => {
  const translate = useTranslate();
  const [locale] = useLocaleState();
  const dateFnsLocale = getDateFnsLocale(locale);
  const acceptedLanguages = navigator
    ? navigator.languages || [navigator.language]
    : [DEFAULT_LOCALE];

  // Rolling window: 3 months past to 6 months future
  const dateRange = useMemo(() => {
    const now = new Date();
    return {
      start: subMonths(now, 3).toISOString(),
      end: addMonths(now, 6).toISOString(),
    };
  }, []);

  const { data, isPending } = useGetList<Deal>("deals", {
    pagination: { perPage: 200, page: 1 },
    sort: {
      field: "expected_closing_date",
      order: "ASC",
    },
    filter: {
      "expected_closing_date@gte": dateRange.start,
      "expected_closing_date@lte": dateRange.end,
    },
  });
  const months = useMemo(() => {
    if (!data) return [];
    const dealsByMonth = data.reduce((acc, deal) => {
      const month = startOfMonth(
        deal.expected_closing_date ?? new Date(),
      ).toISOString();
      if (!acc[month]) {
        acc[month] = [];
      }
      acc[month].push(deal);
      return acc;
    }, {} as any);

    const amountByMonth = Object.keys(dealsByMonth).map((month) => {
      // Calculate positive values (above zero line)
      const wonAmount = dealsByMonth[month]
        .filter((deal: Deal) => deal.stage === "won")
        .reduce((acc: number, deal: Deal) => {
          const amount = deal.amount ?? 0;
          return !isNaN(amount) ? acc + amount : acc;
        }, 0);

      const pendingAmount = dealsByMonth[month]
        .filter((deal: Deal) => !["won", "lost"].includes(deal.stage))
        .reduce((acc: number, deal: Deal) => {
          const amount = deal.amount ?? 0;
          const mult = stageMultiplier[deal.stage] ?? 0;
          return !isNaN(amount) && !isNaN(mult) ? acc + amount * mult : acc;
        }, 0);

      // Calculate negative value (below zero line) - store as negative for diverging chart
      const lostAmount = dealsByMonth[month]
        .filter((deal: Deal) => deal.stage === "lost")
        .reduce((acc: number, deal: Deal) => {
          const amount = deal.amount ?? 0;
          return !isNaN(amount) ? acc + amount : acc;
        }, 0);

      return {
        date: format(month, "MMM", { locale: dateFnsLocale }),
        won: wonAmount,
        pending: pendingAmount,
        lost: -lostAmount, // Negative for diverging chart (renders below zero)
      };
    });

    // Filter out any months with NaN values
    return amountByMonth.filter(
      (month) =>
        !isNaN(month.won) && !isNaN(month.pending) && !isNaN(month.lost),
    );
  }, [data, dateFnsLocale]);

  if (isPending) {
    return (
      <div className="flex flex-col">
        <div className="flex items-center mb-4">
          <Skeleton className="w-6 h-6 mr-3 rounded" />
          <Skeleton className="h-7 w-48" />
        </div>
        <Skeleton className="h-[400px] w-full" />
      </div>
    );
  }

  if (months.length === 0) return null; // No data to display

  const range = months.reduce(
    (acc, month) => {
      acc.min = Math.min(acc.min, month.lost);
      acc.max = Math.max(acc.max, month.won + month.pending);
      return acc;
    },
    { min: 0, max: 0 },
  );

  // Ensure we have a valid range for the chart
  const chartRange = {
    min: range.min === 0 && range.max === 0 ? -100 : range.min * 1.2,
    max: range.min === 0 && range.max === 0 ? 100 : range.max * 1.2,
  };

  return (
    <div className="flex flex-col">
      <div className="flex items-center mb-4">
        <div className="mr-3 flex">
          <DollarSign className="text-muted-foreground w-6 h-6" />
        </div>
        <h2 className="text-xl font-semibold text-muted-foreground">
          {translate("crm.dashboard.upcoming_deal_revenue")}
        </h2>
      </div>
      <div className="h-[400px]">
        <ResponsiveBar
          data={months}
          indexBy="date"
          keys={["won", "pending", "lost"]}
          colors={({ id }) => {
            // won and pending are green shades, lost is red
            if (id === "won") return "#61cdbb";
            if (id === "pending") return "#97e3d5";
            return "#e25c3b";
          }}
          margin={{ top: 30, right: 50, bottom: 30, left: 0 }}
          padding={0.3}
          valueScale={{
            type: "linear",
            min: chartRange.min,
            max: chartRange.max,
          }}
          indexScale={{ type: "band", round: true }}
          enableGridX={true}
          enableGridY={false}
          enableLabel={false}
          tooltip={({ value, indexValue }) => (
            <div className="p-2 bg-secondary rounded shadow inline-flex items-center gap-1 text-secondary-foreground">
              <strong>{indexValue}: </strong>&nbsp;{value > 0 ? "+" : ""}
              {value.toLocaleString(
                locale ?? acceptedLanguages.at(0) ?? DEFAULT_LOCALE,
                {
                  style: "currency",
                  currency: CURRENCY,
                },
              )}
            </div>
          )}
          axisTop={{
            tickSize: 0,
            tickPadding: 12,
            style: {
              ticks: {
                text: {
                  fill: "var(--color-muted-foreground)",
                },
              },
              legend: {
                text: {
                  fill: "var(--color-muted-foreground)",
                },
              },
            },
          }}
          axisBottom={{
            legendPosition: "middle",
            legendOffset: 50,
            tickSize: 0,
            tickPadding: 12,
            style: {
              ticks: {
                text: {
                  fill: "var(--color-muted-foreground)",
                },
              },
              legend: {
                text: {
                  fill: "var(--color-muted-foreground)",
                },
              },
            },
          }}
          axisLeft={null}
          axisRight={{
            format: (v: any) => `${Math.abs(v / 1000)}k`,
            tickValues: 8,
            style: {
              ticks: {
                text: {
                  fill: "var(--color-muted-foreground)",
                },
              },
              legend: {
                text: {
                  fill: "var(--color-muted-foreground)",
                },
              },
            },
          }}
          markers={
            [
              {
                axis: "y",
                value: 0,
                lineStyle: { strokeOpacity: 0 },
                textStyle: { fill: "#2ebca6" },
                legend: translate("crm.dashboard.deals_chart.won"),
                legendPosition: "top-left",
                legendOrientation: "vertical",
              },
              {
                axis: "y",
                value: 0,
                lineStyle: {
                  stroke: "#f47560",
                  strokeWidth: 1,
                },
                textStyle: { fill: "#e25c3b" },
                legend: translate("crm.dashboard.deals_chart.lost"),
                legendPosition: "bottom-left",
                legendOrientation: "vertical",
              },
            ] as any
          }
        />
      </div>
    </div>
  );
});
