import { useEffect, useMemo, useState } from "react";
import { acotService } from "@/services/dashboard/acotService";
import { Card, CardContent } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import { Separator } from "@/components/ui/separator";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import {
  Area,
  CartesianGrid,
  ComposedChart,
  Legend,
  Line,
  ResponsiveContainer,
  Tooltip,
  XAxis,
  YAxis,
} from "recharts";
import type { TooltipProps } from "recharts";
import { TrendingUp, DollarSign, Package, PiggyBank, Percent } from "lucide-react";
import PeriodSelectionPopover, {
  type QuickPreset,
} from "@/components/dashboard/PeriodSelectionPopover";
import type { CustomPeriod, NaturalLanguagePeriodResult } from "@/utils/naturalLanguagePeriod";
import { CARD_STYLES } from "@/lib/dashboard/designTokens";
import { toDateOnly } from "@/utils/businessTime";
import {
  DashboardSectionHeader,
  DashboardStatCard,
  DashboardStatCardSkeleton,
  ChartSkeleton,
  DashboardEmptyState,
  DashboardErrorState,
  TOOLTIP_STYLES,
  METRIC_COLORS,
} from "@/components/dashboard/shared";

type ComparisonValue = {
  absolute: number | null;
  percentage: number | null;
};

type FinancialTotals = {
  grossSales?: number;
  refunds?: number;
  taxCollected?: number;
  shippingFees?: number;
  discounts?: number;
  cogs: number;
  income?: number;
  profit: number;
  margin: number;
};

type FinancialTrendPoint = {
  date: string | Date | null;
  income: number;
  cogs: number;
  profit: number;
  margin: number;
  grossSales?: number;
  refunds?: number;
  shippingFees?: number;
  taxCollected?: number;
  discounts?: number;
  timestamp: string | null;
};

type FinancialComparison = {
  grossSales?: ComparisonValue;
  refunds?: ComparisonValue;
  taxCollected?: ComparisonValue;
  discounts?: ComparisonValue;
  cogs?: ComparisonValue;
  income?: ComparisonValue;
  profit?: ComparisonValue;
  margin?: ComparisonValue;
  [key: string]: ComparisonValue | undefined;
};

type FinancialDateRange = {
  label?: string;
};

type FinancialResponse = {
  dateRange?: FinancialDateRange;
  totals: FinancialTotals;
  previousTotals?: FinancialTotals | null;
  comparison?: FinancialComparison | null;
  trend: FinancialTrendPoint[];
};

type ChartSeriesKey = "income" | "cogs" | "cogsPercentage" | "profit" | "margin";

type GroupByOption = "day" | "month" | "quarter" | "year";

type ChartPoint = {
  label: string;
  timestamp: string | null;
  income: number | null;
  cogs: number | null;
  cogsPercentage: number | null;
  profit: number | null;
  margin: number | null;
  tooltipLabel: string;
  isFuture: boolean;
};

// Chart colors mapped from semantic METRIC_COLORS tokens
const chartColors: Record<ChartSeriesKey, string> = {
  income: METRIC_COLORS.orders,       // Blue - revenue/income streams
  cogs: METRIC_COLORS.expense,        // Orange - costs/expenses
  cogsPercentage: "#f97316",          // Orange-500 - slightly brighter for percentage line
  profit: METRIC_COLORS.profit,       // Green - profit metrics
  margin: METRIC_COLORS.aov,          // Violet - percentage/derived metrics
};

const SERIES_LABELS: Record<ChartSeriesKey, string> = {
  income: "Total Income",
  cogs: "COGS",
  cogsPercentage: "COGS % of Income",
  profit: "Gross Profit",
  margin: "Profit Margin",
};

const SERIES_DEFINITIONS: Array<{
  key: ChartSeriesKey;
  label: string;
  type: "currency" | "percentage";
}> = [
  { key: "income", label: SERIES_LABELS.income, type: "currency" },
  { key: "cogs", label: SERIES_LABELS.cogs, type: "currency" },
  { key: "cogsPercentage", label: SERIES_LABELS.cogsPercentage, type: "percentage" },
  { key: "profit", label: SERIES_LABELS.profit, type: "currency" },
  { key: "margin", label: SERIES_LABELS.margin, type: "percentage" },
];

const GROUP_BY_CHOICES: Array<{ value: GroupByOption; label: string }> = [
  { value: "day", label: "Days" },
  { value: "month", label: "Months" },
  { value: "quarter", label: "Quarters" },
  { value: "year", label: "Years" },
];

const MONTHS = [
  "January",
  "February",
  "March",
  "April",
  "May",
  "June",
  "July",
  "August",
  "September",
  "October",
  "November",
  "December",
];

const QUARTERS = ["Q1", "Q2", "Q3", "Q4"];

const MONTH_COUNT_LIMIT = 999;
const QUARTER_COUNT_LIMIT = 999;
const YEAR_COUNT_LIMIT = 999;

const formatMonthLabel = (year: number, monthIndex: number) => `${MONTHS[monthIndex]} ${year}`;

const formatQuarterLabel = (year: number, quarterIndex: number) => `${QUARTERS[quarterIndex]} ${year}`;

function formatPeriodRangeLabel(period: CustomPeriod): string {
  const range = computePeriodRange(period);
  if (!range) {
    return "";
  }

  const start = range.start;
  const end = range.end;

  if (period.type === "month") {
    const startLabel = formatMonthLabel(start.getFullYear(), start.getMonth());
    const endLabel = formatMonthLabel(end.getFullYear(), end.getMonth());
    return period.count === 1 ? startLabel : `${startLabel} – ${endLabel}`;
  }

  if (period.type === "quarter") {
    const startQuarter = Math.floor(start.getMonth() / 3);
    const endQuarter = Math.floor(end.getMonth() / 3);
    const startLabel = formatQuarterLabel(start.getFullYear(), startQuarter);
    const endLabel = formatQuarterLabel(end.getFullYear(), endQuarter);
    return period.count === 1 ? startLabel : `${startLabel} – ${endLabel}`;
  }

  const startYear = start.getFullYear();
  const endYear = end.getFullYear();
  return period.count === 1 ? `${startYear}` : `${startYear} – ${endYear}`;
}


const formatCurrency = (value: number, minimumFractionDigits = 0) => {
  if (!Number.isFinite(value)) {
    return "$0";
  }

  return new Intl.NumberFormat("en-US", {
    style: "currency",
    currency: "USD",
    minimumFractionDigits,
    maximumFractionDigits: minimumFractionDigits,
  }).format(value);
};

const formatPercentage = (value: number, digits = 1, suffix = "%") => {
  if (!Number.isFinite(value)) {
    return `0${suffix}`;
  }

  return `${value.toFixed(digits)}${suffix}`;
};

type RawTrendPoint = {
  date: Date;
  income: number;
  cogs: number;
  shippingFees: number;
  taxCollected: number;
  grossSales: number;
  discounts: number;
};

type AggregatedTrendPoint = {
  id: string;
  label: string;
  tooltipLabel: string;
  detailLabel: string;
  timestamp: string;
  income: number;
  cogs: number;
  cogsPercentage: number;
  profit: number;
  margin: number;
  isFuture: boolean;
};

const pad = (value: number) => value.toString().padStart(2, "0");

const getGroupKey = (date: Date, groupBy: GroupByOption) => {
  switch (groupBy) {
    case "day":
      return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
    case "month":
      return `${date.getFullYear()}-${pad(date.getMonth() + 1)}`;
    case "quarter": {
      const quarter = Math.floor(date.getMonth() / 3) + 1;
      return `${date.getFullYear()}-Q${quarter}`;
    }
    case "year":
    default:
      return `${date.getFullYear()}`;
  }
};

const formatQuarterRange = (start: Date) => {
  const quarterIndex = Math.floor(start.getMonth() / 3);
  const quarterLabel = QUARTERS[quarterIndex];
  return `${quarterLabel} ${start.getFullYear()}`;
};

const buildGroupLabels = (start: Date, end: Date, groupBy: GroupByOption) => {
  switch (groupBy) {
    case "day": {
      const axisLabel = start.toLocaleDateString("en-US", { month: "short", day: "numeric" });
      const detailLabel = start.toLocaleDateString("en-US", {
        weekday: "short",
        month: "short",
        day: "numeric",
        year: "numeric",
      });
      return { axisLabel, tooltipLabel: detailLabel, detailLabel };
    }
    case "month": {
      const axisLabel = start.toLocaleDateString("en-US", { month: "short", year: "numeric" });
      const detailLabel = start.toLocaleDateString("en-US", { month: "long", year: "numeric" });
      return { axisLabel, tooltipLabel: detailLabel, detailLabel };
    }
    case "quarter": {
      const axisLabel = formatQuarterRange(start);
      let tooltipLabel = axisLabel;
      if (start && end) {
        const startLabel = start.toLocaleDateString("en-US", { month: "short" });
        const endLabel = end.toLocaleDateString("en-US", { month: "short" });
        tooltipLabel = `${axisLabel} (${startLabel} – ${endLabel})`;
      }
      return { axisLabel, tooltipLabel, detailLabel: axisLabel };
    }
    case "year":
    default: {
      const axisLabel = start.getFullYear().toString();
      return { axisLabel, tooltipLabel: axisLabel, detailLabel: axisLabel };
    }
  }
};

const aggregateTrendPoints = (points: RawTrendPoint[], groupBy: GroupByOption): AggregatedTrendPoint[] => {
  if (!points.length) {
    return [];
  }

  const bucketMap = new Map<
    string,
    {
      key: string;
      start: Date;
      end: Date;
      income: number;
      cogs: number;
    }
  >();

  points.forEach((point) => {
    const key = getGroupKey(point.date, groupBy);
    const bucket = bucketMap.get(key);
    if (!bucket) {
      bucketMap.set(key, {
        key,
        start: point.date,
        end: point.date,
        income: point.income,
        cogs: point.cogs,
      });
      return;
    }

    if (point.date < bucket.start) {
      bucket.start = point.date;
    }
    if (point.date > bucket.end) {
      bucket.end = point.date;
    }

    bucket.income += point.income;
    bucket.cogs += point.cogs;
  });

  return Array.from(bucketMap.values())
    .sort((a, b) => a.start.getTime() - b.start.getTime())
    .map((bucket) => {
      const { axisLabel, tooltipLabel, detailLabel } = buildGroupLabels(bucket.start, bucket.end, groupBy);
      const income = bucket.income;
      const profit = income - bucket.cogs;
      const margin = income !== 0 ? (profit / income) * 100 : 0;
      const cogsPercentage = income !== 0 ? (bucket.cogs / income) * 100 : 0;

      return {
        id: bucket.key,
        label: axisLabel,
        tooltipLabel,
        detailLabel,
        timestamp: bucket.start.toISOString(),
        income,
        cogs: bucket.cogs,
        cogsPercentage,
        profit,
        margin,
        isFuture: false,
      };
    });
};

const alignToGroupStart = (date: Date, groupBy: GroupByOption) => {
  const aligned = new Date(date);
  aligned.setHours(0, 0, 0, 0);

  switch (groupBy) {
    case "month":
      aligned.setDate(1);
      break;
    case "quarter": {
      const quarterStartMonth = Math.floor(aligned.getMonth() / 3) * 3;
      aligned.setMonth(quarterStartMonth, 1);
      break;
    }
    case "year":
      aligned.setMonth(0, 1);
      break;
    case "day":
    default:
      break;
  }

  return aligned;
};

const advanceGroupStart = (date: Date, groupBy: GroupByOption) => {
  const next = new Date(date);

  switch (groupBy) {
    case "day":
      next.setDate(next.getDate() + 1);
      break;
    case "month":
      next.setMonth(next.getMonth() + 1, 1);
      break;
    case "quarter":
      next.setMonth(next.getMonth() + 3, 1);
      break;
    case "year":
    default:
      next.setFullYear(next.getFullYear() + 1);
      next.setMonth(0, 1);
      break;
  }

  next.setHours(0, 0, 0, 0);
  return next;
};

const computeBucketRange = (start: Date, groupBy: GroupByOption) => {
  const bucketStart = alignToGroupStart(start, groupBy);
  const nextStart = advanceGroupStart(bucketStart, groupBy);
  const bucketEnd = new Date(nextStart.getTime() - 1);
  return { start: bucketStart, end: bucketEnd };
};

const extendAggregatedTrendPoints = (
  points: AggregatedTrendPoint[],
  groupBy: GroupByOption,
  fullRange: { start: Date; end: Date } | null,
  effectiveRangeEnd: Date | null
) => {
  if (!fullRange) {
    return points;
  }

  const ordered = new Map(points.map((point) => [point.id, point]));
  const results: AggregatedTrendPoint[] = [];
  const start = alignToGroupStart(fullRange.start, groupBy);
  const rangeEndMs = fullRange.end.getTime();
  const effectiveEndMs = effectiveRangeEnd?.getTime() ?? null;

  for (let cursor = start; cursor.getTime() <= rangeEndMs; cursor = advanceGroupStart(cursor, groupBy)) {
    const key = getGroupKey(cursor, groupBy);
    const existing = ordered.get(key);

    if (existing) {
      results.push(existing);
      continue;
    }

    const { start: bucketStart, end: bucketEnd } = computeBucketRange(cursor, groupBy);
    const { axisLabel, tooltipLabel, detailLabel } = buildGroupLabels(bucketStart, bucketEnd, groupBy);
    const isFutureBucket = effectiveEndMs != null && cursor.getTime() >= effectiveEndMs;

    results.push({
      id: key,
      label: axisLabel,
      tooltipLabel,
      detailLabel,
      timestamp: bucketStart.toISOString(),
      income: 0,
      cogs: 0,
      cogsPercentage: 0,
      profit: 0,
      margin: 0,
      isFuture: isFutureBucket,
    });
  }

  return results;
};

const monthsBetween = (start: Date, end: Date) => {
  const diffMs = Math.max(0, end.getTime() - start.getTime());
  const monthApprox = diffMs / (1000 * 60 * 60 * 24 * 30);
  return monthApprox;
};

const safeNumeric = (value: number | null | undefined) =>
  typeof value === "number" && Number.isFinite(value) ? value : 0;

const computeTotalIncome = (totals?: FinancialTotals | null) => {
  if (!totals || typeof totals.income !== "number" || !Number.isFinite(totals.income)) {
    return 0;
  }

  return totals.income;
};

const computeProfitFrom = (income: number, cogs?: number | null | undefined) => income - safeNumeric(cogs);

const computeMarginFrom = (profit: number, income: number) => (income !== 0 ? (profit / income) * 100 : 0);

const buildComparisonFromValues = (current?: number | null, previous?: number | null): ComparisonValue | null => {
  if (current == null || previous == null) {
    return null;
  }

  if (!Number.isFinite(current) || !Number.isFinite(previous)) {
    return null;
  }

  const absolute = current - previous;
  const percentage = previous !== 0 ? (absolute / Math.abs(previous)) * 100 : null;

  return {
    absolute,
    percentage,
  };
};


const ensureValidCustomPeriod = (period: CustomPeriod): CustomPeriod => {
  if (period.count < 1) {
    return { ...period, count: 1 };
  }

  switch (period.type) {
    case "month":
      return {
        ...period,
        startMonth: Math.min(Math.max(period.startMonth, 0), 11),
        count: Math.min(period.count, MONTH_COUNT_LIMIT),
      };
    case "quarter":
      return {
        ...period,
        startQuarter: Math.min(Math.max(period.startQuarter, 0), 3),
        count: Math.min(period.count, QUARTER_COUNT_LIMIT),
      };
    case "year":
    default:
      return {
        ...period,
        count: Math.min(period.count, YEAR_COUNT_LIMIT),
      };
  }
};

function computePeriodRange(period: CustomPeriod): { start: Date; end: Date } | null {
  const safePeriod = ensureValidCustomPeriod(period);
  let start: Date;

  if (safePeriod.type === "month") {
    start = new Date(safePeriod.startYear, safePeriod.startMonth, 1, 0, 0, 0, 0);
    const endExclusive = new Date(start);
    endExclusive.setMonth(endExclusive.getMonth() + safePeriod.count);
    endExclusive.setMilliseconds(endExclusive.getMilliseconds() - 1);
    return { start, end: endExclusive };
  }

  if (safePeriod.type === "quarter") {
    const startMonth = safePeriod.startQuarter * 3;
    start = new Date(safePeriod.startYear, startMonth, 1, 0, 0, 0, 0);
    const endExclusive = new Date(start);
    endExclusive.setMonth(endExclusive.getMonth() + safePeriod.count * 3);
    endExclusive.setMilliseconds(endExclusive.getMilliseconds() - 1);
    return { start, end: endExclusive };
  }

  start = new Date(safePeriod.startYear, 0, 1, 0, 0, 0, 0);
  const endExclusive = new Date(start);
  endExclusive.setFullYear(endExclusive.getFullYear() + safePeriod.count);
  endExclusive.setMilliseconds(endExclusive.getMilliseconds() - 1);
  return { start, end: endExclusive };
}

const FinancialOverview = () => {
  const currentDate = useMemo(() => new Date(), []);
  const currentYear = currentDate.getFullYear();

  const [customPeriod, setCustomPeriod] = useState<CustomPeriod>({
    type: "month",
    startYear: currentYear,
    startMonth: currentDate.getMonth(),
    count: 1,
  });
  const [isLast30DaysMode, setIsLast30DaysMode] = useState<boolean>(true);
  const [isPeriodPopoverOpen, setIsPeriodPopoverOpen] = useState<boolean>(false);
  const [metrics, setMetrics] = useState<Record<ChartSeriesKey, boolean>>({
    income: true,
    cogs: true,
    cogsPercentage: true,
    profit: true,
    margin: true,
  });
  const [groupBy, setGroupBy] = useState<GroupByOption>("day");
  const [groupByAuto, setGroupByAuto] = useState<boolean>(true);
  const [data, setData] = useState<FinancialResponse | null>(null);
  const [loading, setLoading] = useState<boolean>(true);
  const [error, setError] = useState<string | null>(null);

  const selectedRange = useMemo(() => {
    if (isLast30DaysMode) {
      const end = new Date(currentDate);
      const start = new Date(currentDate);
      start.setHours(0, 0, 0, 0);
      end.setHours(23, 59, 59, 999);
      start.setDate(start.getDate() - 29);
      return { start, end };
    }

    return computePeriodRange(customPeriod);
  }, [isLast30DaysMode, customPeriod, currentDate]);

  const effectiveRangeEnd = useMemo(() => {
    if (!selectedRange) {
      return null;
    }

    const rangeEndMs = selectedRange.end.getTime();
    const currentMs = currentDate.getTime();
    const startMs = selectedRange.start.getTime();
    const clampedMs = Math.min(rangeEndMs, currentMs);
    const safeEndMs = clampedMs < startMs ? startMs : clampedMs;
    return new Date(safeEndMs);
  }, [selectedRange, currentDate]);

  const requestRange = useMemo(() => {
    if (!selectedRange) {
      return null;
    }

    const end = effectiveRangeEnd ?? selectedRange.end;

    return {
      start: new Date(selectedRange.start),
      end: new Date(end),
    };
  }, [selectedRange, effectiveRangeEnd]);


  const rawTrendPoints = useMemo<RawTrendPoint[]>(() => {
    if (!data?.trend?.length) {
      return [];
    }

    const rangeBoundary = effectiveRangeEnd?.getTime() ?? null;
    const toNumber = (value: number | null | undefined) =>
      typeof value === "number" && Number.isFinite(value) ? value : 0;

    return data.trend
      .map((point) => {
        const timestamp =
          point.timestamp ??
          (typeof point.date === "string"
            ? point.date
            : point.date instanceof Date
            ? point.date.toISOString()
            : null);

        let date: Date | null = null;
        if (timestamp) {
          const parsed = new Date(timestamp);
          if (!Number.isNaN(parsed.getTime())) {
            date = parsed;
          }
        } else if (point.date instanceof Date && !Number.isNaN(point.date.getTime())) {
          date = point.date;
        }

        if (!date) {
          return null;
        }

        if (typeof point.income !== "number" || !Number.isFinite(point.income)) {
          return null;
        }

        const grossSalesValue = toNumber((point as { grossSales?: number }).grossSales);
        const shippingFeesValue = toNumber((point as { shippingFees?: number }).shippingFees);
        const taxCollectedValue = toNumber((point as { taxCollected?: number }).taxCollected);
        const discountsValue = toNumber((point as { discounts?: number }).discounts);
        const incomeValue = point.income;

        return {
          date,
          income: incomeValue,
          shippingFees: shippingFeesValue,
          taxCollected: taxCollectedValue,
          grossSales: grossSalesValue,
          discounts: discountsValue,
          cogs: toNumber(point.cogs),
        };
      })
      .filter((value): value is RawTrendPoint => Boolean(value))
      .filter((value) => (rangeBoundary == null ? true : value.date.getTime() <= rangeBoundary))
      .sort((a, b) => a.date.getTime() - b.date.getTime());
  }, [data, effectiveRangeEnd]);

  useEffect(() => {
    if (!groupByAuto) {
      return;
    }

    let range: { start: Date; end: Date } | null = null;

    if (rawTrendPoints.length > 1) {
      range = {
        start: rawTrendPoints[0].date,
        end: rawTrendPoints[rawTrendPoints.length - 1].date,
      };
    } else if (requestRange) {
      range = {
        start: new Date(requestRange.start),
        end: new Date(requestRange.end),
      };
    } else if (selectedRange) {
      range = {
        start: new Date(selectedRange.start),
        end: new Date(selectedRange.end),
      };
    }

    if (!range) {
      return;
    }

    const spanInMonths = monthsBetween(range.start, range.end);
    const suggested = spanInMonths > 6 ? "month" : "day";

    if (suggested !== groupBy) {
      setGroupBy(suggested);
    }
  }, [groupByAuto, rawTrendPoints, requestRange, selectedRange, groupBy]);

  useEffect(() => {
    let cancelled = false;

    const fetchData = async () => {
      setLoading(true);
      setError(null);

      try {
        const params: Record<string, string> = {};

        if (isLast30DaysMode) {
          params.timeRange = "last30days";
        } else {
          if (!selectedRange || !requestRange) {
            setData(null);
            return;
          }
          params.timeRange = "custom";
          // Date-only strings = business dates; the server resolves them to
          // business-day bounds (1am ET / Chicago midnight). Never send
          // browser-local-midnight instants.
          params.startDate = toDateOnly(requestRange.start);
          params.endDate = toDateOnly(requestRange.end);
        }

        const response = (await acotService.getFinancials(params)) as FinancialResponse;
        if (!cancelled) {
          setData(response);
        }
      } catch (err: unknown) {
        if (!cancelled) {
          let message = "Failed to load financial data";

          if (typeof err === "object" && err !== null) {
            const maybeAxiosError = err as {
              response?: { data?: { error?: unknown } };
              message?: unknown;
            };

            const responseError = maybeAxiosError.response?.data?.error;
            if (typeof responseError === "string" && responseError.trim().length > 0) {
              message = responseError;
            } else if (typeof maybeAxiosError.message === "string") {
              message = maybeAxiosError.message;
            }
          }

          setError(message);
        }
      } finally {
        if (!cancelled) {
          setLoading(false);
        }
      }
    };

    void fetchData();

    return () => {
      cancelled = true;
    };
  }, [isLast30DaysMode, selectedRange, requestRange]);

  const cards = useMemo(
    () => {
      if (!data?.totals) {
        return [] as FinancialStatCardConfig[];
      }

      const totals = data.totals;
      const previous = data.previousTotals ?? undefined;
      const safeCurrency = (value: number | undefined | null, digits = 0) =>
        typeof value === "number" && Number.isFinite(value) ? formatCurrency(value, digits) : "—";

      const safePercentage = (value: number | undefined | null, digits = 1) =>
        typeof value === "number" && Number.isFinite(value) ? formatPercentage(value, digits) : "—";

      const comparison = data.comparison ?? {};

      const totalIncome = computeTotalIncome(totals);
      const previousIncome = previous ? computeTotalIncome(previous) : null;

      const cogsValue = safeNumeric(totals.cogs);
      const previousCogs = previous?.cogs != null ? safeNumeric(previous.cogs) : null;

      const profitValue = Number.isFinite(totals.profit)
        ? safeNumeric(totals.profit)
        : computeProfitFrom(totalIncome, totals.cogs);
      const previousProfitValue = previousIncome != null
        ? Number.isFinite(previous?.profit)
          ? safeNumeric(previous?.profit)
          : computeProfitFrom(previousIncome, previous?.cogs)
        : null;

      const marginValue = Number.isFinite(totals.margin)
        ? safeNumeric(totals.margin)
        : computeMarginFrom(profitValue, totalIncome);
      const previousMarginValue = previousIncome != null
        ? Number.isFinite(previous?.margin)
          ? safeNumeric(previous?.margin)
          : computeMarginFrom(previousProfitValue ?? 0, previousIncome)
        : null;

      const incomeDescription = previousIncome != null ? `Previous: ${safeCurrency(previousIncome, 0)}` : undefined;
      const cogsDescription = previousCogs != null ? `Previous: ${safeCurrency(previousCogs, 0)}` : undefined;
      const profitDescription = previousProfitValue != null ? `Previous: ${safeCurrency(previousProfitValue, 0)}` : undefined;
      const marginDescription = previousMarginValue != null ? `Previous: ${safePercentage(previousMarginValue, 1)}` : undefined;

      const incomeComparison = comparison?.income ?? buildComparisonFromValues(totalIncome, previousIncome ?? null);
      const cogsComparison = comparison?.cogs ?? buildComparisonFromValues(cogsValue, previousCogs ?? null);
      const profitComparison = comparison?.profit ?? buildComparisonFromValues(profitValue, previousProfitValue ?? null);
      const marginComparison = comparison?.margin ?? buildComparisonFromValues(marginValue, previousMarginValue ?? null);

      return [
        {
          key: "income",
          title: "Total Income",
          value: safeCurrency(totalIncome, 0),
          description: incomeDescription,
          trendValue: incomeComparison?.percentage,
          iconColor: "blue" as const,
          tooltip:
            "Gross sales minus refunds and discounts, plus shipping fees collected (shipping, small-order, and rush fees). Taxes are excluded.",
        },
        {
          key: "cogs",
          title: "COGS",
          value: safeCurrency(cogsValue, 0),
          description: cogsDescription,
          trendValue: cogsComparison?.percentage,
          trendInverted: true,
          iconColor: "orange" as const,
          tooltip: "Sum of reported product cost of goods sold (cogs_amount) for completed sales actions in the period.",
        },
        {
          key: "profit",
          title: "Gross Profit",
          value: safeCurrency(profitValue, 0),
          description: profitDescription,
          trendValue: profitComparison?.percentage,
          iconColor: "emerald" as const,
          tooltip: "Total Income minus COGS.",
        },
        {
          key: "margin",
          title: "Profit Margin",
          value: safePercentage(marginValue, 1),
          description: marginDescription,
          trendValue: marginComparison?.absolute,
          iconColor: "purple" as const,
          tooltip: "Gross Profit divided by Total Income, expressed as a percentage.",
        },
      ];
    },
    [data]
  );

  const aggregatedPoints = useMemo<AggregatedTrendPoint[]>(() => {
    const aggregated = aggregateTrendPoints(rawTrendPoints, groupBy);
    return extendAggregatedTrendPoints(aggregated, groupBy, selectedRange, effectiveRangeEnd);
  }, [rawTrendPoints, groupBy, selectedRange, effectiveRangeEnd]);

  const chartData = useMemo<ChartPoint[]>(() => {
    if (!aggregatedPoints.length) {
      return [];
    }

    return aggregatedPoints.map((point) => ({
      label: point.label,
      timestamp: point.timestamp,
      income: point.isFuture ? null : point.income,
      cogs: point.isFuture ? null : point.cogs,
      cogsPercentage: point.isFuture ? null : point.cogsPercentage,
      profit: point.isFuture ? null : point.profit,
      margin: point.isFuture ? null : point.margin,
      tooltipLabel: point.tooltipLabel,
      isFuture: point.isFuture,
    }));
  }, [aggregatedPoints]);

  const selectedRangeLabel = useMemo(() => {
    if (isLast30DaysMode) {
      return "Last 30 Days";
    }
    const label = formatPeriodRangeLabel(customPeriod);
    if (!label) {
      return "";
    }

    if (!selectedRange || !effectiveRangeEnd) {
      return label;
    }

    const isPartial = effectiveRangeEnd.getTime() < selectedRange.end.getTime();
    if (!isPartial) {
      return label;
    }

    const partialLabel = effectiveRangeEnd.toLocaleDateString("en-US", {
      month: "short",
      day: "numeric",

    });

    return `${label} (through ${partialLabel})`;
  }, [isLast30DaysMode, customPeriod, selectedRange, effectiveRangeEnd]);

  const percentageDomain = useMemo<[number, number]>(() => {
    if ((!metrics.margin && !metrics.cogsPercentage) || !chartData.length) {
      return [0, 100];
    }

    const values: number[] = [];

    if (metrics.margin) {
      values.push(
        ...chartData
          .map((point) => point.margin)
          .filter((value): value is number => typeof value === "number" && Number.isFinite(value))
      );
    }

    if (metrics.cogsPercentage) {
      values.push(
        ...chartData
          .map((point) => point.cogsPercentage)
          .filter((value): value is number => typeof value === "number" && Number.isFinite(value))
      );
    }

    if (!values.length) {
      return [0, 100];
    }

    const min = Math.min(...values);
    const max = Math.max(...values);

    if (min === max) {
      const padding = Math.max(Math.abs(min) * 0.1, 5);
      return [min - padding, max + padding];
    }

    const padding = (max - min) * 0.1;
    return [min - padding, max + padding];
  }, [chartData, metrics.margin, metrics.cogsPercentage]);

  const hasActiveMetrics = useMemo(() => Object.values(metrics).some(Boolean), [metrics]);
  const showPercentageAxis = metrics.margin || metrics.cogsPercentage;

  const detailRows = useMemo(
    () =>
      aggregatedPoints.map((point) => ({
        id: point.id,
        label: point.detailLabel,
        timestamp: point.timestamp,
        income: point.income,
        cogs: point.cogs,
        cogsPercentage: point.cogsPercentage,
        profit: point.profit,
        margin: point.margin,
        isFuture: point.isFuture,
      })),
    [aggregatedPoints]
  );

  const hasData = chartData.length > 0;

  const enableAutoGrouping = () => setGroupByAuto(true);

  const handleGroupByChange = (value: string) => {
    setGroupBy(value as GroupByOption);
    setGroupByAuto(false);
  };



  const toggleMetric = (series: ChartSeriesKey) => {
    setMetrics((prev) => ({
      ...prev,
      [series]: !prev[series],
    }));
  };
  const handleNaturalLanguageResult = (result: NaturalLanguagePeriodResult) => {
    if (result === "last30days") {
      setIsLast30DaysMode(true);
      return;
    }

    if (result) {
      setIsLast30DaysMode(false);
      setCustomPeriod(result);
    }
  };

  const handleQuickPeriod = (preset: QuickPreset) => {
    const now = new Date();
    const currentYear = now.getFullYear();
    const currentMonth = now.getMonth();
    const currentQuarter = Math.floor(currentMonth / 3);

    enableAutoGrouping();
    
    switch (preset) {
      case "last30days":
        // For Last 30 Days, we keep the special mode but this is temporary
        // The UI will show this as selected but the period inputs won't reflect it
        setIsLast30DaysMode(true);
        break;
      case "thisMonth":
        setIsLast30DaysMode(false);
        setCustomPeriod({
          type: "month",
          startYear: currentYear,
          startMonth: currentMonth,
          count: 1,
        });
        break;
      case "lastMonth":
        setIsLast30DaysMode(false);
        const lastMonth = currentMonth === 0 ? 11 : currentMonth - 1;
        const lastMonthYear = currentMonth === 0 ? currentYear - 1 : currentYear;
        setCustomPeriod({
          type: "month",
          startYear: lastMonthYear,
          startMonth: lastMonth,
          count: 1,
        });
        break;
      case "thisQuarter":
        setIsLast30DaysMode(false);
        setCustomPeriod({
          type: "quarter",
          startYear: currentYear,
          startQuarter: currentQuarter,
          count: 1,
        });
        break;
      case "lastQuarter":
        setIsLast30DaysMode(false);
        const lastQuarter = currentQuarter === 0 ? 3 : currentQuarter - 1;
        const lastQuarterYear = currentQuarter === 0 ? currentYear - 1 : currentYear;
        setCustomPeriod({
          type: "quarter",
          startYear: lastQuarterYear,
          startQuarter: lastQuarter,
          count: 1,
        });
        break;
      case "thisYear":
        setIsLast30DaysMode(false);
        setCustomPeriod({
          type: "year",
          startYear: currentYear,
          count: 1,
        });
        break;
      default:
        break;
    }
  };


  // Header actions: Details dialog and Period selector
  const headerActions = !error ? (
    <>
      <Dialog>
        <DialogTrigger asChild>
          <Button variant="outline" className="h-9" disabled={loading || !detailRows.length}>
            Details
          </Button>
        </DialogTrigger>
        <DialogContent className={`p-4 max-w-[95vw] w-fit max-h-[85vh] overflow-hidden flex flex-col ${CARD_STYLES.base}`}>
          <DialogHeader className="flex-none">
            <DialogTitle className="text-foreground">
              Financial Details
            </DialogTitle>
            <div className="flex items-center justify-center gap-2 pt-4">
              <div className="flex flex-wrap gap-1">
                {SERIES_DEFINITIONS.map((series) => (
                  <Button
                    key={series.key}
                    variant={metrics[series.key] ? "default" : "outline"}
                    size="sm"
                    onClick={() => toggleMetric(series.key)}
                  >
                    {series.label}
                  </Button>
                ))}
              </div>
              <Separator orientation="vertical" className="h-6" />
              <Select value={groupBy} onValueChange={handleGroupByChange}>
                <SelectTrigger className="w-[140px]">
                  <SelectValue placeholder="Group By" />
                </SelectTrigger>
                <SelectContent>
                  {GROUP_BY_CHOICES.map((option) => (
                    <SelectItem key={option.value} value={option.value}>
                      {option.label}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
          </DialogHeader>
          <div className="flex-1 overflow-auto mt-6">
            <div className={`rounded-lg border ${CARD_STYLES.base} w-full`}>
              <Table className="w-full">
                <TableHeader>
                  <TableRow>
                    <TableHead className="text-center whitespace-nowrap px-6">
                      Date
                    </TableHead>
                    {metrics.income && (
                      <TableHead className="text-center whitespace-nowrap px-6">
                        Total Income
                      </TableHead>
                    )}
                    {metrics.cogs && (
                      <TableHead className="text-center whitespace-nowrap px-6">
                        COGS
                      </TableHead>
                    )}
                    {metrics.cogsPercentage && (
                      <TableHead className="text-center whitespace-nowrap px-6">
                        COGS % of Income
                      </TableHead>
                    )}
                    {metrics.profit && (
                      <TableHead className="text-center whitespace-nowrap px-6">
                        Gross Profit
                      </TableHead>
                    )}
                    {metrics.margin && (
                      <TableHead className="text-center whitespace-nowrap px-6">
                        Margin
                      </TableHead>
                    )}
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {detailRows.map((row) => (
                    <TableRow key={row.id}>
                      <TableCell className="text-center whitespace-nowrap px-6">
                        {row.label || "—"}
                      </TableCell>
                      {metrics.income && (
                        <TableCell className="text-center whitespace-nowrap px-6">
                          {row.isFuture ? "—" : formatCurrency(row.income, 0)}
                        </TableCell>
                      )}
                      {metrics.cogs && (
                        <TableCell className="text-center whitespace-nowrap px-6">
                          {row.isFuture ? "—" : formatCurrency(row.cogs, 0)}
                        </TableCell>
                      )}
                      {metrics.cogsPercentage && (
                        <TableCell className="text-center whitespace-nowrap px-6">
                          {row.isFuture ? "—" : formatPercentage(row.cogsPercentage, 1)}
                        </TableCell>
                      )}
                      {metrics.profit && (
                        <TableCell className="text-center whitespace-nowrap px-6">
                          {row.isFuture ? "—" : formatCurrency(row.profit, 0)}
                        </TableCell>
                      )}
                      {metrics.margin && (
                        <TableCell className="text-center whitespace-nowrap px-6">
                          {row.isFuture ? "—" : formatPercentage(row.margin, 1)}
                        </TableCell>
                      )}
                    </TableRow>
                  ))}
                </TableBody>
              </Table>
            </div>
          </div>
        </DialogContent>
      </Dialog>

      <PeriodSelectionPopover
        open={isPeriodPopoverOpen}
        onOpenChange={setIsPeriodPopoverOpen}
        selectedLabel={selectedRangeLabel}
        referenceDate={currentDate}
        isLast30DaysActive={isLast30DaysMode}
        onQuickSelect={handleQuickPeriod}
        onApplyResult={handleNaturalLanguageResult}
      />
    </>
  ) : null;

  return (
    <Card className={`w-full ${CARD_STYLES.elevated}`}>
      <DashboardSectionHeader
        title="Profit & Loss Overview"
        size="large"
        actions={headerActions}
      />

      <CardContent className="p-6 pt-0 space-y-4">
        {/* Show stats only if not in error state */}
        {!error && (
          loading ? (
            <SkeletonStats />
          ) : (
            cards.length > 0 && <FinancialStatGrid cards={cards} />
          )
        )}

        {/* Show metric toggles only if not in error state */}
        {!error && (
          <div className="flex items-center flex-col sm:flex-row gap-0 sm:gap-4">
            <div className="flex flex-wrap gap-1">
              {SERIES_DEFINITIONS.map((series) => (
                <Button
                  key={series.key}
                  variant={metrics[series.key] ? "default" : "outline"}
                  size="sm"
                  onClick={() => toggleMetric(series.key)}
                >
                  {series.label}
                </Button>
              ))}
            </div>

            <Separator
              orientation="vertical"
              className="h-6 hidden sm:block"
            />
            <Separator
              orientation="horizontal"
              className="sm:hidden w-20 my-2"
            />

            <div className="flex items-center gap-2">
              <div className="text-sm text-muted-foreground">Group By:</div>

              <Select value={groupBy} onValueChange={handleGroupByChange}>
                <SelectTrigger className="w-[110px]">
                  <SelectValue placeholder="Group By" />
                </SelectTrigger>
                <SelectContent>
                  {GROUP_BY_CHOICES.map((option) => (
                    <SelectItem key={option.value} value={option.value}>
                      {option.label}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
          </div>
        )}
        {loading ? (
          <div className="space-y-6">
            <SkeletonChartSection />
          </div>
        ) : error ? (
          <DashboardErrorState error={`Failed to load financial data: ${error}`} className="mx-0 my-0" />
        ) : !hasData ? (
          <DashboardEmptyState
            icon={TrendingUp}
            title="No financial data available"
            description="Try selecting a different time range"
          />
        ) : (
          <>
            <div className={`h-[400px] mt-4 ${CARD_STYLES.base} rounded-lg p-0 relative`}>
              {!hasActiveMetrics ? (
                <DashboardEmptyState
                  icon={TrendingUp}
                  title="No metrics selected"
                  description="Select at least one metric to visualize."
                />
              ) : (
                <ResponsiveContainer width="100%" height="100%">
                  <ComposedChart data={chartData} margin={{ top: 5, right: -25, left: 15, bottom: 5 }}>
                    <defs>
                      <linearGradient id="financialCogs" x1="0" y1="0" x2="0" y2="1">
                        <stop offset="5%" stopColor={chartColors.cogs} stopOpacity={0.8} />
                        <stop offset="95%" stopColor={chartColors.cogs} stopOpacity={0.6} />
                      </linearGradient>
                      <linearGradient id="financialProfit" x1="0" y1="0" x2="0" y2="1">
                        <stop offset="5%" stopColor={chartColors.profit} stopOpacity={0.8} />
                        <stop offset="95%" stopColor={chartColors.profit} stopOpacity={0.6} />
                      </linearGradient>
                    </defs>
                    <CartesianGrid
                      strokeDasharray="3 3"
                      className="stroke-muted"
                    />
                    <XAxis
                      dataKey="label"
                      className="text-xs text-muted-foreground"
                      tick={{ fill: "currentColor" }}
                    />
                    <YAxis
                      yAxisId="left"
                      tickFormatter={(value: number) => formatCurrency(value, 0)}
                      className="text-xs text-muted-foreground"
                      tick={{ fill: "currentColor" }}
                    />
                    {showPercentageAxis && (
                      <YAxis
                        yAxisId="right"
                        orientation="right"
                        tickFormatter={(value: number) => formatPercentage(value, 0)}
                        domain={percentageDomain}
                        className="text-xs text-muted-foreground"
                        tick={{ fill: "currentColor" }}
                      />
                    )}
                    <Tooltip content={<FinancialTooltip />} />
                    <Legend formatter={(value: string) => SERIES_LABELS[value as ChartSeriesKey] ?? value} />
                    {/* Stacked areas showing revenue breakdown */}
                    {metrics.cogs ? (
                      <Area
                        yAxisId="left"
                        type="monotone"
                        dataKey="cogs"
                        stackId="revenue"
                        name={SERIES_LABELS.cogs}
                        stroke={chartColors.cogs}
                        fill="url(#financialCogs)"
                        strokeWidth={1}
                      />
                    ) : null}
                    {metrics.profit ? (
                      <Area
                        yAxisId="left"
                        type="monotone"
                        dataKey="profit"
                        stackId="revenue"
                        name={SERIES_LABELS.profit}
                        stroke={chartColors.profit}
                        fill="url(#financialProfit)"
                        strokeWidth={1}
                      />
                    ) : null}
                    {/* Show total income as a line for reference if selected */}
                    {metrics.income ? (
                      <Line
                        yAxisId="left"
                        type="monotone"
                        dataKey="income"
                        name={SERIES_LABELS.income}
                        stroke={chartColors.income}
                        strokeWidth={2}
                        dot={false}
                        activeDot={{ r: 4 }}
                        connectNulls
                      />
                    ) : null}
                    {metrics.cogsPercentage ? (
                      <Line
                        yAxisId="right"
                        type="monotone"
                        dataKey="cogsPercentage"
                        name={SERIES_LABELS.cogsPercentage}
                        stroke={chartColors.cogsPercentage}
                        strokeWidth={2}
                        strokeDasharray="6 3"
                        dot={false}
                        activeDot={{ r: 4 }}
                        connectNulls
                      />
                    ) : null}
                    {metrics.margin ? (
                      <Line
                        yAxisId="right"
                        type="monotone"
                        dataKey="margin"
                        name={SERIES_LABELS.margin}
                        stroke={chartColors.margin}
                        strokeWidth={3}
                        dot={false}
                        activeDot={{ r: 4 }}
                        connectNulls
                      />
                    ) : null}
                  </ComposedChart>
                </ResponsiveContainer>
              )}
            </div>
          </>
        )}
      </CardContent>
    </Card>
  );
};

type FinancialStatCardConfig = {
  key: string;
  title: string;
  value: string;
  description?: string;
  trendValue?: number | null;
  trendInverted?: boolean;
  iconColor: "blue" | "orange" | "emerald" | "purple";
  tooltip?: string;
};

const ICON_MAP = {
  income: DollarSign,
  cogs: Package,
  profit: PiggyBank,
  margin: Percent,
} as const;

function FinancialStatGrid({
  cards,
}: {
  cards: FinancialStatCardConfig[];
}) {
  return (
    <div className="grid grid-cols-2 lg:grid-cols-4 gap-4 py-4 w-full dashboard-stagger">
      {cards.map((card) => (
        <DashboardStatCard
          key={card.key}
          title={card.title}
          value={card.value}
          subtitle={card.description}
          trend={
            card.trendValue != null && Number.isFinite(card.trendValue)
              ? {
                  value: card.trendValue,
                  moreIsBetter: !card.trendInverted,
                }
              : undefined
          }
          icon={ICON_MAP[card.key as keyof typeof ICON_MAP]}
          iconColor={card.iconColor}
          tooltip={card.tooltip}
        />
      ))}
    </div>
  );
}

function SkeletonStats() {
  return (
    <div className="grid grid-cols-2 lg:grid-cols-4 gap-4 py-4 w-full">
      {Array.from({ length: 4 }).map((_, index) => (
        <DashboardStatCardSkeleton key={index} hasIcon hasSubtitle />
      ))}
    </div>
  );
}

function SkeletonChartSection() {
  return (
    <ChartSkeleton type="area" height="default" withCard={false} />
  );
}


const FinancialTooltip = ({ active, payload, label }: TooltipProps<number, string>) => {
  if (!active || !payload?.length) {
    return null;
  }

  const basePoint = payload[0]?.payload as ChartPoint | undefined;
  const resolvedLabel = basePoint?.tooltipLabel ?? label;
  const isFuturePoint = basePoint?.isFuture ?? false;

  // Calculate total income for percentage calculations
  const income = basePoint?.income ?? 0;

  // Define the desired order: income, cogs, cogs %, profit, margin
  const desiredOrder: ChartSeriesKey[] = ["income", "cogs", "cogsPercentage", "profit", "margin"];
  
  // Create a map of payload entries by dataKey for easy lookup
  const payloadMap = new Map(payload.map(entry => [entry.dataKey as ChartSeriesKey, entry]));
  
  // Sort payload according to desired order
  const orderedPayload = desiredOrder
    .map(key => payloadMap.get(key))
    .filter((entry): entry is typeof payload[0] => entry !== undefined);

  return (
    <div className={TOOLTIP_STYLES.container}>
      <p className={TOOLTIP_STYLES.header}>{resolvedLabel}</p>
      <div className={TOOLTIP_STYLES.content}>
        {orderedPayload.map((entry, index) => {
          const key = (entry.dataKey ?? "") as ChartSeriesKey;
          const rawValue = entry.value;
          let formattedValue: string;
          let percentageOfRevenue = "";

          if (isFuturePoint || rawValue == null) {
            formattedValue = "—";
          } else if (typeof rawValue === "number") {
            const isPercentageSeries = key === "margin" || key === "cogsPercentage";
            formattedValue = isPercentageSeries ? formatPercentage(rawValue, 1) : formatCurrency(rawValue, 0);

            // Add percentage of revenue for COGS only
            if (key === "cogs" && income > 0 && !isFuturePoint) {
              const percentage = (rawValue / income) * 100;
              percentageOfRevenue = ` (${formatPercentage(percentage, 1)})`;
            }
          } else if (typeof rawValue === "string") {
            formattedValue = rawValue;
          } else {
            formattedValue = "—";
          }

          return (
            <div key={`${key}-${index}`} className={TOOLTIP_STYLES.row}>
              <div className={TOOLTIP_STYLES.rowLabel}>
                <span
                  className={TOOLTIP_STYLES.dot}
                  style={{ backgroundColor: entry.stroke || entry.color || "#888" }}
                />
                <span className={TOOLTIP_STYLES.name}>
                  {SERIES_LABELS[key] ?? entry.name ?? key}
                </span>
              </div>
              <span className={TOOLTIP_STYLES.value}>
                {formattedValue}{percentageOfRevenue}
              </span>
            </div>
          );
        })}
      </div>
    </div>
  );
};

export default FinancialOverview;
