"use client";

import { useState, useMemo } from "react";
import { PageLayout, LoadingState, PageHeader } from "@/components/layout";
import {
  StatsSummaryCards,
  MonthlyChart,
  CategoryPieChart,
  BalanceLineChart,
  TopExpensesList,
} from "@/components/statistics";
import { useBankingData } from "@/lib/hooks";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { AccountFilterCombobox } from "@/components/ui/account-filter-combobox";
import { CategoryFilterCombobox } from "@/components/ui/category-filter-combobox";
import { Card, CardContent } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { CategoryIcon } from "@/components/ui/category-icon";
import { Filter, X, Wallet, CircleSlash, Calendar } from "lucide-react";
import type { Account, Category } from "@/lib/types";

type Period = "3months" | "6months" | "12months" | "all";

export default function StatisticsPage() {
  const { data, isLoading } = useBankingData();
  const [period, setPeriod] = useState<Period>("6months");
  const [selectedAccounts, setSelectedAccounts] = useState<string[]>(["all"]);
  const [selectedCategories, setSelectedCategories] = useState<string[]>(["all"]);

  // Get start date based on period
  const startDate = useMemo(() => {
    const now = new Date();
    switch (period) {
      case "3months":
        return new Date(now.getFullYear(), now.getMonth() - 3, 1);
      case "6months":
        return new Date(now.getFullYear(), now.getMonth() - 6, 1);
      case "12months":
        return new Date(now.getFullYear(), now.getMonth() - 12, 1);
      default:
        return new Date(0);
    }
  }, [period]);

  // Transactions filtered for account filter (by categories, period - not accounts)
  const transactionsForAccountFilter = useMemo(() => {
    if (!data) return [];

    return data.transactions.filter(
      (t) => new Date(t.date) >= startDate
    ).filter((t) => {
      if (!selectedCategories.includes("all")) {
        if (selectedCategories.includes("uncategorized")) {
          return !t.categoryId;
        } else {
          return t.categoryId && selectedCategories.includes(t.categoryId);
        }
      }
      return true;
    });
  }, [data, startDate, selectedCategories]);

  // Transactions filtered for category filter (by accounts, period - not categories)
  const transactionsForCategoryFilter = useMemo(() => {
    if (!data) return [];

    return data.transactions.filter(
      (t) => new Date(t.date) >= startDate
    ).filter((t) => {
      if (!selectedAccounts.includes("all")) {
        return selectedAccounts.includes(t.accountId);
      }
      return true;
    });
  }, [data, startDate, selectedAccounts]);

  const stats = useMemo(() => {
    if (!data) return null;

    let transactions = data.transactions.filter(
      (t) => new Date(t.date) >= startDate
    );

    // Filter by accounts
    if (!selectedAccounts.includes("all")) {
      transactions = transactions.filter(
        (t) => selectedAccounts.includes(t.accountId)
      );
    }

    // Filter by categories
    if (!selectedCategories.includes("all")) {
      if (selectedCategories.includes("uncategorized")) {
        transactions = transactions.filter((t) => !t.categoryId);
      } else {
        transactions = transactions.filter(
          (t) => t.categoryId && selectedCategories.includes(t.categoryId)
        );
      }
    }

    // Monthly breakdown
    const monthlyData = new Map<string, { income: number; expenses: number }>();
    transactions.forEach((t) => {
      const monthKey = t.date.substring(0, 7);
      const current = monthlyData.get(monthKey) || { income: 0, expenses: 0 };
      if (t.amount >= 0) {
        current.income += t.amount;
      } else {
        current.expenses += Math.abs(t.amount);
      }
      monthlyData.set(monthKey, current);
    });

    const monthlyChartData = Array.from(monthlyData.entries())
      .sort((a, b) => a[0].localeCompare(b[0]))
      .map(([month, values]) => ({
        month: new Date(month + "-01").toLocaleDateString("fr-FR", {
          month: "short",
          year: "2-digit",
        }),
        revenus: Math.round(values.income),
        depenses: Math.round(values.expenses),
        solde: Math.round(values.income - values.expenses),
      }));

    // Category breakdown (expenses only)
    const categoryTotals = new Map<string, number>();
    transactions
      .filter((t) => t.amount < 0)
      .forEach((t) => {
        const catId = t.categoryId || "uncategorized";
        const current = categoryTotals.get(catId) || 0;
        categoryTotals.set(catId, current + Math.abs(t.amount));
      });

    const categoryChartData = Array.from(categoryTotals.entries())
      .map(([categoryId, total]) => {
        const category = data.categories.find((c) => c.id === categoryId);
        return {
          name: category?.name || "Non catégorisé",
          value: Math.round(total),
          color: category?.color || "#94a3b8",
          icon: category?.icon || "HelpCircle",
        };
      })
      .sort((a, b) => b.value - a.value)
      .slice(0, 8);

    // Top expenses
    const topExpenses = transactions
      .filter((t) => t.amount < 0)
      .sort((a, b) => a.amount - b.amount)
      .slice(0, 5);

    // Summary
    const totalIncome = transactions
      .filter((t) => t.amount >= 0)
      .reduce((sum, t) => sum + t.amount, 0);
    const totalExpenses = transactions
      .filter((t) => t.amount < 0)
      .reduce((sum, t) => sum + Math.abs(t.amount), 0);
    const avgMonthlyExpenses =
      monthlyData.size > 0 ? totalExpenses / monthlyData.size : 0;

    // Balance evolution - Aggregated (using filtered transactions)
    const sortedFilteredTransactions = [...transactions].sort(
      (a, b) => new Date(a.date).getTime() - new Date(b.date).getTime()
    );

    let runningBalance = 0;
    const aggregatedBalanceByDate = new Map<string, number>();
    sortedFilteredTransactions.forEach((t) => {
      runningBalance += t.amount;
      aggregatedBalanceByDate.set(t.date, runningBalance);
    });

    const aggregatedBalanceData = Array.from(
      aggregatedBalanceByDate.entries()
    ).map(([date, balance]) => ({
      date: new Date(date).toLocaleDateString("fr-FR", {
        day: "2-digit",
        month: "short",
      }),
      solde: Math.round(balance),
    }));

    // Balance evolution - Per account (using filtered transactions)
    const accountBalances = new Map<string, Map<string, number>>();
    data.accounts.forEach((account) => {
      accountBalances.set(account.id, new Map());
    });

    // Calculate running balance per account
    const accountRunningBalances = new Map<string, number>();
    data.accounts.forEach((account) => {
      accountRunningBalances.set(account.id, 0);
    });

    sortedFilteredTransactions.forEach((t) => {
      const currentBalance = accountRunningBalances.get(t.accountId) || 0;
      const newBalance = currentBalance + t.amount;
      accountRunningBalances.set(t.accountId, newBalance);

      const accountDates = accountBalances.get(t.accountId);
      if (accountDates) {
        accountDates.set(t.date, newBalance);
      }
    });

    // Merge all dates and create data points
    const allDates = new Set<string>();
    accountBalances.forEach((dates) => {
      dates.forEach((_, date) => allDates.add(date));
    });

    const sortedDates = Array.from(allDates).sort();
    const lastBalances = new Map<string, number>();
    data.accounts.forEach((account) => {
      lastBalances.set(account.id, 0);
    });

    const perAccountBalanceData = sortedDates.map((date) => {
      const point: { date: string; [key: string]: string | number } = {
        date: new Date(date).toLocaleDateString("fr-FR", {
          day: "2-digit",
          month: "short",
        }),
      };

      data.accounts.forEach((account) => {
        const accountDates = accountBalances.get(account.id);
        if (accountDates?.has(date)) {
          lastBalances.set(account.id, accountDates.get(date)!);
        }
        point[account.id] = Math.round(lastBalances.get(account.id) || 0);
      });

      return point;
    });

    return {
      monthlyChartData,
      categoryChartData,
      topExpenses,
      totalIncome,
      totalExpenses,
      avgMonthlyExpenses,
      aggregatedBalanceData,
      perAccountBalanceData,
      transactionCount: transactions.length,
    };
  }, [data, startDate, selectedAccounts, selectedCategories]);

  const formatCurrency = (amount: number) => {
    return new Intl.NumberFormat("fr-FR", {
      style: "currency",
      currency: "EUR",
    }).format(amount);
  };

  if (isLoading || !data || !stats) {
    return <LoadingState />;
  }

  return (
    <PageLayout>
      <PageHeader
        title="Statistiques"
        description="Analysez vos dépenses et revenus"
      />

      <Card className="mb-6">
        <CardContent className="pt-4">
          <div className="flex flex-wrap gap-4">
            <AccountFilterCombobox
              accounts={data.accounts}
              folders={data.folders}
              value={selectedAccounts}
              onChange={setSelectedAccounts}
              className="w-[200px]"
              filteredTransactions={transactionsForAccountFilter}
            />

            <CategoryFilterCombobox
              categories={data.categories}
              value={selectedCategories}
              onChange={setSelectedCategories}
              className="w-[220px]"
              filteredTransactions={transactionsForCategoryFilter}
            />

            <Select
              value={period}
              onValueChange={(v) => setPeriod(v as Period)}
            >
              <SelectTrigger className="w-[150px]">
                <SelectValue placeholder="Période" />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="3months">3 mois</SelectItem>
                <SelectItem value="6months">6 mois</SelectItem>
                <SelectItem value="12months">12 mois</SelectItem>
                <SelectItem value="all">Tout</SelectItem>
              </SelectContent>
            </Select>
          </div>

          <ActiveFilters
            selectedAccounts={selectedAccounts}
            onRemoveAccount={(id) => {
              const newAccounts = selectedAccounts.filter((a) => a !== id);
              setSelectedAccounts(newAccounts.length > 0 ? newAccounts : ["all"]);
            }}
            onClearAccounts={() => setSelectedAccounts(["all"])}
            selectedCategories={selectedCategories}
            onRemoveCategory={(id) => {
              const newCategories = selectedCategories.filter((c) => c !== id);
              setSelectedCategories(newCategories.length > 0 ? newCategories : ["all"]);
            }}
            onClearCategories={() => setSelectedCategories(["all"])}
            period={period}
            onClearPeriod={() => setPeriod("all")}
            accounts={data.accounts}
            categories={data.categories}
          />
        </CardContent>
      </Card>

      <StatsSummaryCards
        totalIncome={stats.totalIncome}
        totalExpenses={stats.totalExpenses}
        avgMonthlyExpenses={stats.avgMonthlyExpenses}
        formatCurrency={formatCurrency}
      />

      <div className="grid gap-6 lg:grid-cols-2">
        <MonthlyChart
          data={stats.monthlyChartData}
          formatCurrency={formatCurrency}
        />
        <CategoryPieChart
          data={stats.categoryChartData}
          formatCurrency={formatCurrency}
        />
        <BalanceLineChart
          aggregatedData={stats.aggregatedBalanceData}
          perAccountData={stats.perAccountBalanceData}
          accounts={data.accounts}
          formatCurrency={formatCurrency}
        />
        <TopExpensesList
          expenses={stats.topExpenses}
          categories={data.categories}
          formatCurrency={formatCurrency}
        />
      </div>
    </PageLayout>
  );
}

function ActiveFilters({
  selectedAccounts,
  onRemoveAccount,
  onClearAccounts,
  selectedCategories,
  onRemoveCategory,
  onClearCategories,
  period,
  onClearPeriod,
  accounts,
  categories,
}: {
  selectedAccounts: string[];
  onRemoveAccount: (id: string) => void;
  onClearAccounts: () => void;
  selectedCategories: string[];
  onRemoveCategory: (id: string) => void;
  onClearCategories: () => void;
  period: Period;
  onClearPeriod: () => void;
  accounts: Account[];
  categories: Category[];
}) {
  const hasAccounts = !selectedAccounts.includes("all");
  const hasCategories = !selectedCategories.includes("all");
  const hasPeriod = period !== "all";

  const hasActiveFilters = hasAccounts || hasCategories || hasPeriod;

  if (!hasActiveFilters) return null;

  const selectedAccs = accounts.filter((a) => selectedAccounts.includes(a.id));
  const selectedCats = categories.filter((c) => selectedCategories.includes(c.id));
  const isUncategorized = selectedCategories.includes("uncategorized");

  const getPeriodLabel = (p: Period) => {
    switch (p) {
      case "3months":
        return "3 mois";
      case "6months":
        return "6 mois";
      case "12months":
        return "12 mois";
      default:
        return "Tout";
    }
  };

  const clearAll = () => {
    onClearAccounts();
    onClearCategories();
    onClearPeriod();
  };

  return (
    <div className="flex items-center gap-2 mt-3 pt-3 border-t border-border flex-wrap">
      <Filter className="h-3.5 w-3.5 text-muted-foreground" />

      {selectedAccs.map((acc) => (
        <Badge key={acc.id} variant="secondary" className="gap-1 text-xs font-normal">
          <Wallet className="h-3 w-3" />
          {acc.name}
          <button
            onClick={() => onRemoveAccount(acc.id)}
            className="ml-1 hover:text-foreground"
          >
            <X className="h-3 w-3" />
          </button>
        </Badge>
      ))}

      {isUncategorized && (
        <Badge variant="secondary" className="gap-1 text-xs font-normal">
          <CircleSlash className="h-3 w-3" />
          Non catégorisé
          <button onClick={onClearCategories} className="ml-1 hover:text-foreground">
            <X className="h-3 w-3" />
          </button>
        </Badge>
      )}

      {selectedCats.map((cat) => (
        <Badge
          key={cat.id}
          variant="secondary"
          className="gap-1 text-xs font-normal"
          style={{
            backgroundColor: `${cat.color}15`,
            borderColor: `${cat.color}30`,
          }}
        >
          <CategoryIcon icon={cat.icon} color={cat.color} size={12} />
          {cat.name}
          <button
            onClick={() => onRemoveCategory(cat.id)}
            className="ml-1 hover:text-foreground"
          >
            <X className="h-3 w-3" />
          </button>
        </Badge>
      ))}

      {hasPeriod && (
        <Badge variant="secondary" className="gap-1 text-xs font-normal">
          <Calendar className="h-3 w-3" />
          {getPeriodLabel(period)}
          <button onClick={onClearPeriod} className="ml-1 hover:text-foreground">
            <X className="h-3 w-3" />
          </button>
        </Badge>
      )}

      <button
        onClick={clearAll}
        className="text-xs text-muted-foreground hover:text-foreground ml-auto"
      >
        Effacer tout
      </button>
    </div>
  );
}
