"use client";

import { useState, useMemo, useEffect } from "react";
import { useSearchParams } from "next/navigation";
import { PageLayout, LoadingState, PageHeader } from "@/components/layout";
import {
  TransactionFilters,
  TransactionBulkActions,
  TransactionTable,
} from "@/components/transactions";
import { OFXImportDialog } from "@/components/import/ofx-import-dialog";
import { useBankingData } from "@/lib/hooks";
import { Button } from "@/components/ui/button";
import { Upload } from "lucide-react";

type SortField = "date" | "amount" | "description";
type SortOrder = "asc" | "desc";

export default function TransactionsPage() {
  const searchParams = useSearchParams();
  const { data, isLoading, refresh, update } = useBankingData();
  const [searchQuery, setSearchQuery] = useState("");
  const [selectedAccount, setSelectedAccount] = useState<string>("all");

  useEffect(() => {
    const accountId = searchParams.get("accountId");
    if (accountId) {
      setSelectedAccount(accountId);
    }
  }, [searchParams]);

  const [selectedCategory, setSelectedCategory] = useState<string>("all");
  const [showReconciled, setShowReconciled] = useState<string>("all");
  const [sortField, setSortField] = useState<SortField>("date");
  const [sortOrder, setSortOrder] = useState<SortOrder>("desc");
  const [selectedTransactions, setSelectedTransactions] = useState<Set<string>>(
    new Set()
  );

  const filteredTransactions = useMemo(() => {
    if (!data) return [];

    let transactions = [...data.transactions];

    if (searchQuery) {
      const query = searchQuery.toLowerCase();
      transactions = transactions.filter(
        (t) =>
          t.description.toLowerCase().includes(query) ||
          t.memo?.toLowerCase().includes(query)
      );
    }

    if (selectedAccount !== "all") {
      transactions = transactions.filter(
        (t) => t.accountId === selectedAccount
      );
    }

    if (selectedCategory !== "all") {
      if (selectedCategory === "uncategorized") {
        transactions = transactions.filter((t) => !t.categoryId);
      } else {
        transactions = transactions.filter(
          (t) => t.categoryId === selectedCategory
        );
      }
    }

    if (showReconciled !== "all") {
      const isReconciled = showReconciled === "reconciled";
      transactions = transactions.filter(
        (t) => t.isReconciled === isReconciled
      );
    }

    transactions.sort((a, b) => {
      let comparison = 0;
      switch (sortField) {
        case "date":
          comparison = new Date(a.date).getTime() - new Date(b.date).getTime();
          break;
        case "amount":
          comparison = a.amount - b.amount;
          break;
        case "description":
          comparison = a.description.localeCompare(b.description);
          break;
      }
      return sortOrder === "asc" ? comparison : -comparison;
    });

    return transactions;
  }, [
    data,
    searchQuery,
    selectedAccount,
    selectedCategory,
    showReconciled,
    sortField,
    sortOrder,
  ]);

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

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

  const formatDate = (dateStr: string) => {
    return new Date(dateStr).toLocaleDateString("fr-FR", {
      day: "2-digit",
      month: "short",
      year: "numeric",
    });
  };

  const toggleReconciled = async (transactionId: string) => {
    const transaction = data.transactions.find((t) => t.id === transactionId);
    if (!transaction) return;

    const updatedTransaction = {
      ...transaction,
      isReconciled: !transaction.isReconciled,
    };

    const updatedTransactions = data.transactions.map((t) =>
      t.id === transactionId ? updatedTransaction : t
    );
    update({ ...data, transactions: updatedTransactions });

    try {
      await fetch("/api/banking/transactions", {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(updatedTransaction),
      });
    } catch (error) {
      console.error("Failed to update transaction:", error);
      refresh();
    }
  };

  const setCategory = async (
    transactionId: string,
    categoryId: string | null
  ) => {
    const transaction = data.transactions.find((t) => t.id === transactionId);
    if (!transaction) return;

    const updatedTransaction = { ...transaction, categoryId };

    const updatedTransactions = data.transactions.map((t) =>
      t.id === transactionId ? updatedTransaction : t
    );
    update({ ...data, transactions: updatedTransactions });

    try {
      await fetch("/api/banking/transactions", {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(updatedTransaction),
      });
    } catch (error) {
      console.error("Failed to update transaction:", error);
      refresh();
    }
  };

  const bulkReconcile = async (reconciled: boolean) => {
    const transactionsToUpdate = data.transactions.filter((t) =>
      selectedTransactions.has(t.id)
    );

    const updatedTransactions = data.transactions.map((t) =>
      selectedTransactions.has(t.id) ? { ...t, isReconciled: reconciled } : t
    );
    update({ ...data, transactions: updatedTransactions });
    setSelectedTransactions(new Set());

    try {
      await Promise.all(
        transactionsToUpdate.map((t) =>
          fetch("/api/banking/transactions", {
            method: "PUT",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ ...t, isReconciled: reconciled }),
          })
        )
      );
    } catch (error) {
      console.error("Failed to update transactions:", error);
      refresh();
    }
  };

  const bulkSetCategory = async (categoryId: string | null) => {
    const transactionsToUpdate = data.transactions.filter((t) =>
      selectedTransactions.has(t.id)
    );

    const updatedTransactions = data.transactions.map((t) =>
      selectedTransactions.has(t.id) ? { ...t, categoryId } : t
    );
    update({ ...data, transactions: updatedTransactions });
    setSelectedTransactions(new Set());

    try {
      await Promise.all(
        transactionsToUpdate.map((t) =>
          fetch("/api/banking/transactions", {
            method: "PUT",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ ...t, categoryId }),
          })
        )
      );
    } catch (error) {
      console.error("Failed to update transactions:", error);
      refresh();
    }
  };

  const toggleSelectAll = () => {
    if (selectedTransactions.size === filteredTransactions.length) {
      setSelectedTransactions(new Set());
    } else {
      setSelectedTransactions(new Set(filteredTransactions.map((t) => t.id)));
    }
  };

  const toggleSelectTransaction = (id: string) => {
    const newSelected = new Set(selectedTransactions);
    if (newSelected.has(id)) {
      newSelected.delete(id);
    } else {
      newSelected.add(id);
    }
    setSelectedTransactions(newSelected);
  };

  const handleSortChange = (field: SortField) => {
    if (sortField === field) {
      setSortOrder(sortOrder === "asc" ? "desc" : "asc");
    } else {
      setSortField(field);
      setSortOrder(field === "date" ? "desc" : "asc");
    }
  };

  return (
    <PageLayout>
      <PageHeader
        title="Transactions"
        description={`${filteredTransactions.length} transaction${filteredTransactions.length > 1 ? "s" : ""}`}
        actions={
          <OFXImportDialog onImportComplete={refresh}>
            <Button>
              <Upload className="w-4 h-4 mr-2" />
              Importer OFX
            </Button>
          </OFXImportDialog>
        }
      />

      <TransactionFilters
        searchQuery={searchQuery}
        onSearchChange={setSearchQuery}
        selectedAccount={selectedAccount}
        onAccountChange={setSelectedAccount}
        selectedCategory={selectedCategory}
        onCategoryChange={setSelectedCategory}
        showReconciled={showReconciled}
        onReconciledChange={setShowReconciled}
        accounts={data.accounts}
        categories={data.categories}
      />

      <TransactionBulkActions
        selectedCount={selectedTransactions.size}
        categories={data.categories}
        onReconcile={bulkReconcile}
        onSetCategory={bulkSetCategory}
      />

      <TransactionTable
        transactions={filteredTransactions}
        accounts={data.accounts}
        categories={data.categories}
        selectedTransactions={selectedTransactions}
        sortField={sortField}
        sortOrder={sortOrder}
        onSortChange={handleSortChange}
        onToggleSelectAll={toggleSelectAll}
        onToggleSelectTransaction={toggleSelectTransaction}
        onToggleReconciled={toggleReconciled}
        onSetCategory={setCategory}
        formatCurrency={formatCurrency}
        formatDate={formatDate}
      />
    </PageLayout>
  );
}
