import React, { useState } from "react";
import { ChevronDown, ChevronRight, ListFilter } from "lucide-react";
import { Card, CardContent, CardHeader, CardTitle } from "./card";
import { Spinner } from "./spinner";
import { InfoTooltip } from "./info-tooltip";
import { cn } from "@/lib/utils";
import { formatCurrency } from "@/lib/format-currency";

// ─── Types ───────────────────────────────────────────────────────────────────

export interface ExpenseSubCategory {
  id: string;
  name: string;
  /** Absolute dollar amount */
  amount: number;
  /** Percentage of parent category 0–100 */
  pct: number;
}

export interface ExpenseCategoryItem {
  id: string;
  name: string;
  /** Absolute dollar amount */
  amount: number;
  /** Percentage of total budget 0–100 */
  pct: number;
  /** Optional lucide-react icon element */
  icon?: React.ReactNode;
  subCategories?: ExpenseSubCategory[];
}

export interface DashboardExpenseCategoriesProps {
  categories?: ExpenseCategoryItem[];
  title?: string;
  subtitle?: string;
  /**
   * Optional explanatory note shown as an info-icon tooltip next to the subtitle
   * (e.g. the Income bucket's internal-transfer caveat). Omit to hide the icon.
   */
  tooltipText?: string;
  /**
   * Message shown when there are no categories to display. Lets each bucket give
   * a specific empty state (e.g. "No income categories available").
   */
  emptyMessage?: string;
  isLoading?: boolean;
  className?: string;
  /** Currently active filter category ID (parent or sub-category) */
  selectedCategoryId?: string | null;
  /** Called with the category ID to filter by, or null to clear */
  onCategorySelect?: (id: string | null) => void;
  /**
   * Color scheme for progress bars and active states.
   * Use "secondary" for the Expense tab to distinguish from Income (primary).
   * Defaults to "primary".
   */
  colorScheme?: "primary" | "secondary";
}

// ─── Constants ────────────────────────────────────────────────────────────────

const SECONDARY_ACTIVE_BG =
  "color-mix(in oklch, var(--brand-secondary) 8%, transparent)";
const SECONDARY_ACTIVE_HOVER_BG =
  "color-mix(in oklch, var(--brand-secondary) 12%, transparent)";

// ─── Progress bar ─────────────────────────────────────────────────────────────

function ProgressBar({
  pct,
  className,
  colorScheme = "primary",
}: {
  pct: number;
  className?: string;
  colorScheme?: "primary" | "secondary";
}) {
  return (
    <div className={cn("h-1.5 w-full overflow-hidden bg-muted", className)}>
      <div
        className="h-full bg-primary transition-all"
        style={{
          width: `${Math.min(100, Math.max(0, pct))}%`,
          ...(colorScheme === "secondary" && {
            backgroundColor: "var(--brand-secondary)",
          }),
        }}
        aria-hidden="true"
      />
    </div>
  );
}

// ─── Sub-category row ─────────────────────────────────────────────────────────

function SubCategoryRow({
  sub,
  isSelected,
  colorScheme = "primary",
  onClick,
}: {
  sub: ExpenseSubCategory;
  isSelected: boolean;
  colorScheme?: "primary" | "secondary";
  onClick: () => void;
}) {
  const isSecondary = colorScheme === "secondary";
  return (
    <div
      className={cn(
        "flex w-full flex-col gap-1 py-1.5 pl-8",
        isSelected && !isSecondary && "bg-primary/5",
      )}
      style={
        isSelected && isSecondary
          ? { backgroundColor: SECONDARY_ACTIVE_BG }
          : undefined
      }
    >
      <div className="flex items-center justify-between gap-2 text-sm">
        <div className="flex min-w-0 items-center gap-1">
          <span
            className={cn(
              "truncate text-muted-foreground",
              isSelected && "font-medium",
            )}
          >
            {sub.name}
          </span>
          <button
            type="button"
            onClick={onClick}
            aria-label={`Filter by ${sub.name}`}
            aria-pressed={isSelected}
            className={cn(
              "shrink-0 transition-colors",
              isSelected
                ? isSecondary
                  ? "text-[var(--brand-secondary)]"
                  : "text-primary"
                : "text-muted-foreground/50 hover:text-muted-foreground",
            )}
          >
            <ListFilter size={12} />
          </button>
        </div>
        <span className="shrink-0 font-medium text-foreground">
          {formatCurrency(sub.amount)}
        </span>
      </div>
      <ProgressBar pct={sub.pct} colorScheme={colorScheme} />
    </div>
  );
}

// ─── Category row ─────────────────────────────────────────────────────────────

function CategoryRow({
  item,
  selectedCategoryId,
  colorScheme = "primary",
  onFilterClick,
}: {
  item: ExpenseCategoryItem;
  selectedCategoryId?: string | null;
  colorScheme?: "primary" | "secondary";
  onFilterClick: (id: string | null) => void;
}) {
  const [expanded, setExpanded] = useState(false);
  const [hovered, setHovered] = useState(false);

  const hasChildren = (item.subCategories?.length ?? 0) > 0;
  const isSelected = selectedCategoryId === item.id;
  const isChildSelected =
    hasChildren &&
    (item.subCategories?.some((s) => s.id === selectedCategoryId) ?? false);
  const isActive = isSelected || isChildSelected;
  const isSecondary = colorScheme === "secondary";

  // Secondary scheme active background is set via inline style (color-mix not
  // expressible as a Tailwind arbitrary value here). Hover darkens the tint.
  const wrapperStyle =
    isSecondary && isActive
      ? {
          backgroundColor: hovered
            ? SECONDARY_ACTIVE_HOVER_BG
            : SECONDARY_ACTIVE_BG,
        }
      : undefined;

  return (
    <div
      className={cn(
        "border-b border-border last:border-0 transition-colors",
        isActive && !isSecondary && "bg-primary/5",
      )}
      style={wrapperStyle}
    >
      {/* Main row — click expands/collapses; filter icon inside triggers filter */}
      <button
        type="button"
        className={cn(
          "flex w-full items-start gap-3 py-3 text-left transition-colors",
          !isSecondary && "hover:bg-muted/40",
          !isSecondary && isActive && "hover:bg-primary/10",
        )}
        onMouseEnter={() => setHovered(true)}
        onMouseLeave={() => setHovered(false)}
        onClick={() => hasChildren && setExpanded((v) => !v)}
        aria-expanded={hasChildren ? expanded : undefined}
      >
        {/* Expand chevron */}
        <span className="mt-0.5 shrink-0 text-muted-foreground">
          {hasChildren ? (
            expanded ? (
              <ChevronDown size={14} />
            ) : (
              <ChevronRight size={14} />
            )
          ) : (
            <span className="inline-block size-3.5" />
          )}
        </span>

        {/* Domain icon */}
        {item.icon && (
          <span className="mt-0.5 shrink-0 text-muted-foreground">
            {item.icon}
          </span>
        )}

        {/* Name + filter icon + amounts */}
        <div className="min-w-0 flex-1">
          <div className="flex items-center justify-between gap-2">
            <div className="flex min-w-0 items-center gap-1">
              <span className="truncate text-base font-medium text-foreground">
                {item.name}
              </span>
              {/* Filter icon — only this triggers the category filter */}
              <button
                type="button"
                onClick={(e) => {
                  e.stopPropagation();
                  onFilterClick(isSelected ? null : item.id);
                }}
                aria-label={`Filter by ${item.name}`}
                aria-pressed={isSelected}
                className={cn(
                  "shrink-0 transition-colors",
                  isActive
                    ? isSecondary
                      ? "text-[var(--brand-secondary)]"
                      : "text-primary"
                    : "text-muted-foreground/50 hover:text-muted-foreground",
                )}
              >
                <ListFilter size={13} />
              </button>
            </div>
            <div className="flex shrink-0 items-center gap-2">
              <span className="text-sm text-muted-foreground">
                {item.pct.toFixed(0)}%
              </span>
              <span className="text-base font-semibold text-foreground">
                {formatCurrency(item.amount)}
              </span>
            </div>
          </div>
          <ProgressBar
            pct={item.pct}
            className="mt-1.5"
            colorScheme={colorScheme}
          />
        </div>
      </button>

      {/* Sub-categories */}
      {hasChildren && expanded && (
        <div className="pb-2">
          {item.subCategories!.map((sub) => (
            <SubCategoryRow
              key={sub.id}
              sub={sub}
              isSelected={selectedCategoryId === sub.id}
              colorScheme={colorScheme}
              onClick={() =>
                onFilterClick(selectedCategoryId === sub.id ? null : sub.id)
              }
            />
          ))}
        </div>
      )}
    </div>
  );
}

// ─── Component ────────────────────────────────────────────────────────────────

export function DashboardExpenseCategories({
  categories = [],
  title = "Expenses Categories",
  subtitle,
  tooltipText,
  emptyMessage = "No expense categories available",
  isLoading = false,
  className,
  selectedCategoryId,
  onCategorySelect,
  colorScheme = "primary",
}: DashboardExpenseCategoriesProps) {
  return (
    <Card className={cn("flex flex-col", className)}>
      <CardHeader className="px-4 pb-2">
        <div className="flex items-baseline justify-between gap-2">
          <CardTitle className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
            {title}
          </CardTitle>
          {subtitle && (
            <span className="flex shrink-0 items-center gap-1 text-xs text-muted-foreground">
              {subtitle}
              {tooltipText && <InfoTooltip text={tooltipText} />}
            </span>
          )}
        </div>
      </CardHeader>

      <CardContent className="flex flex-1 flex-col p-0 px-4 pb-2">
        {isLoading ? (
          <div className="flex flex-1 items-center justify-center py-8">
            <Spinner size="default" />
          </div>
        ) : categories.length === 0 ? (
          <p className="py-8 text-center text-sm text-muted-foreground">
            {emptyMessage}
          </p>
        ) : (
          <div>
            {categories.map((item) => (
              <CategoryRow
                key={item.id}
                item={item}
                selectedCategoryId={selectedCategoryId}
                colorScheme={colorScheme}
                onFilterClick={(id) => onCategorySelect?.(id)}
              />
            ))}
          </div>
        )}
      </CardContent>
    </Card>
  );
}
