import { router } from "expo-router";
import { useMemo, useState } from "react";
import {
  Pressable,
  RefreshControl,
  ScrollView,
  StyleSheet,
  Text,
  View,
} from "react-native";

import { AppBackground } from "@/components/AppBackground";
import { FilterChip } from "@/components/FilterChip";
import { LoadingScreen } from "@/components/LoadingScreen";
import { PageHeader } from "@/components/PageHeader";
import { SwipeableRow } from "@/components/SwipeableRow";
import { TabPage } from "@/components/TabPage";
import { TabScrollView } from "@/components/TabScrollView";
import { Button } from "@/components/ui/Button";
import { fonts, spacing } from "@/constants/theme";
import { useAppTheme } from "@/contexts/ThemeContext";
import { formatCurrency, formatDate } from "@/lib/format";
import { formatTrpcErrorMessage } from "@/lib/trpc-errors";
import type { ThemeColors } from "@/lib/theme-palette";
import { useThemedStyles } from "@/lib/use-themed-styles";
import { api } from "@/lib/trpc";

type ExpenseFilter = "all" | "billable" | "receipts";

export default function ExpensesScreen() {
  const { colors } = useAppTheme();
  const styles = useThemedStyles(createStyles);
  const utils = api.useUtils();
  const [filter, setFilter] = useState<ExpenseFilter>("all");
  const expensesQuery = api.expenses.getAll.useQuery();

  const deleteExpense = api.expenses.delete.useMutation({
    onSuccess: () => void utils.expenses.getAll.invalidate(),
  });

  const expenses = expensesQuery.data ?? [];
  const filteredExpenses = useMemo(
    () =>
      expenses.filter((expense) => {
        if (filter === "billable") return expense.billable;
        if (filter === "receipts") return expense.receiptCount > 0;
        return true;
      }),
    [expenses, filter],
  );
  const total = filteredExpenses.reduce(
    (sum, expense) => sum + expense.amount,
    0,
  );
  const receiptCount = filteredExpenses.reduce(
    (sum, expense) => sum + (expense.receiptCount ?? 0),
    0,
  );

  if (expensesQuery.isLoading) {
    return <LoadingScreen message="Loading expenses…" />;
  }

  if (expensesQuery.error) {
    return (
      <AppBackground>
        <TabPage>
          <View style={styles.errorBox}>
            <Text style={[styles.errorTitle, { color: colors.foreground }]}>
              Could not load expenses
            </Text>
            <Text style={{ color: colors.mutedForeground }}>
              {formatTrpcErrorMessage(expensesQuery.error)}
            </Text>
          </View>
        </TabPage>
      </AppBackground>
    );
  }

  return (
    <AppBackground>
      <TabPage>
        <TabScrollView
          header={
            <>
              <PageHeader
                title="Expenses"
                subtitle={`${expenses.length} recorded`}
              />
              <Button
                title="Add expense"
                onPress={() => router.push("/(app)/more/expenses/new" as never)}
              />
            </>
          }
          refreshControl={
            <RefreshControl
              refreshing={expensesQuery.isRefetching}
              onRefresh={() => void expensesQuery.refetch()}
              tintColor={colors.primary}
            />
          }
        >
          {expenses.length === 0 ? (
            <Text style={[styles.empty, { color: colors.mutedForeground }]}>
              No expenses yet. Add one with a receipt photo or manual entry.
            </Text>
          ) : (
            <>
              <View style={styles.summary}>
                <View>
                  <Text
                    style={[
                      styles.summaryLabel,
                      { color: colors.mutedForeground },
                    ]}
                  >
                    Visible total
                  </Text>
                  <Text
                    style={[styles.summaryValue, { color: colors.foreground }]}
                  >
                    {formatCurrency(total)}
                  </Text>
                </View>
                <View style={styles.summaryRight}>
                  <Text
                    style={[
                      styles.summaryLabel,
                      { color: colors.mutedForeground },
                    ]}
                  >
                    Receipts
                  </Text>
                  <Text
                    style={[styles.summaryValue, { color: colors.foreground }]}
                  >
                    {receiptCount}
                  </Text>
                </View>
              </View>

              <ScrollView
                horizontal
                showsHorizontalScrollIndicator={false}
                contentContainerStyle={styles.filters}
              >
                <FilterChip
                  label="All"
                  active={filter === "all"}
                  onPress={() => setFilter("all")}
                />
                <FilterChip
                  label="Billable"
                  active={filter === "billable"}
                  onPress={() => setFilter("billable")}
                />
                <FilterChip
                  label="With receipts"
                  active={filter === "receipts"}
                  onPress={() => setFilter("receipts")}
                />
              </ScrollView>

              {filteredExpenses.length === 0 ? (
                <Text style={[styles.empty, { color: colors.mutedForeground }]}>
                  No expenses match this filter.
                </Text>
              ) : (
                filteredExpenses.map((expense) => (
                  <SwipeableRow
                    key={expense.id}
                    actions={[
                      {
                        key: "open",
                        label: "Open",
                        icon: "open-outline",
                        color: "#fff",
                        backgroundColor: colors.primary,
                        onPress: () =>
                          router.push(
                            `/(app)/more/expenses/${expense.id}` as never,
                          ),
                      },
                      {
                        key: "delete",
                        label: "Delete",
                        icon: "trash-outline",
                        color: "#fff",
                        backgroundColor: colors.destructive,
                        onPress: () => deleteExpense.mutate({ id: expense.id }),
                      },
                    ]}
                  >
                    <Pressable
                      accessibilityRole="button"
                      onPress={() =>
                        router.push(
                          `/(app)/more/expenses/${expense.id}` as never,
                        )
                      }
                      style={({ pressed }) => [
                        styles.row,
                        pressed && styles.rowPressed,
                      ]}
                    >
                      <View style={styles.meta}>
                        <View style={styles.titleRow}>
                          <Text
                            style={[styles.title, { color: colors.foreground }]}
                            numberOfLines={1}
                          >
                            {expense.description}
                          </Text>
                          {expense.receiptCount ? (
                            <Text
                              style={[
                                styles.receiptPill,
                                {
                                  color: colors.primary,
                                  borderColor: colors.border,
                                },
                              ]}
                            >
                              {expense.receiptCount}
                            </Text>
                          ) : null}
                        </View>
                        <Text
                          style={[
                            styles.sub,
                            { color: colors.mutedForeground },
                          ]}
                          numberOfLines={2}
                        >
                          {formatDate(expense.date)}
                          {expense.category ? ` · ${expense.category}` : ""}
                          {expense.client?.name
                            ? ` · ${expense.client.name}`
                            : ""}
                          {expense.billable ? " · Billable" : ""}
                        </Text>
                      </View>
                      <Text
                        style={[styles.amount, { color: colors.foreground }]}
                      >
                        {formatCurrency(expense.amount, expense.currency)}
                      </Text>
                    </Pressable>
                  </SwipeableRow>
                ))
              )}
            </>
          )}
        </TabScrollView>
      </TabPage>
    </AppBackground>
  );
}

const createStyles = (colors: ThemeColors) =>
  StyleSheet.create({
    row: {
      flexDirection: "row",
      alignItems: "center",
      justifyContent: "space-between",
      gap: spacing.md,
      paddingVertical: spacing.md,
      borderBottomWidth: 1,
      borderBottomColor: colors.border,
    },
    rowPressed: {
      opacity: 0.82,
    },
    meta: {
      flex: 1,
      gap: 2,
    },
    titleRow: {
      flexDirection: "row",
      alignItems: "center",
      gap: spacing.sm,
    },
    title: {
      flex: 1,
      fontFamily: fonts.bodySemiBold,
      fontSize: 15,
    },
    sub: {
      fontFamily: fonts.body,
      fontSize: 13,
    },
    amount: {
      fontFamily: fonts.bodySemiBold,
      fontSize: 15,
      fontVariant: ["tabular-nums"],
    },
    summary: {
      flexDirection: "row",
      justifyContent: "space-between",
      gap: spacing.md,
      padding: spacing.md,
      borderRadius: 16,
      borderWidth: 1,
      borderColor: colors.border,
      backgroundColor: colors.cardGlass,
    },
    summaryRight: {
      alignItems: "flex-end",
    },
    summaryLabel: {
      fontFamily: fonts.bodyMedium,
      fontSize: 12,
      textTransform: "uppercase",
    },
    summaryValue: {
      marginTop: 2,
      fontFamily: fonts.bodySemiBold,
      fontSize: 20,
      fontVariant: ["tabular-nums"],
    },
    filters: {
      gap: spacing.sm,
      paddingRight: spacing.lg,
    },
    receiptPill: {
      minWidth: 26,
      textAlign: "center",
      borderWidth: 1,
      borderRadius: 999,
      paddingHorizontal: spacing.sm,
      paddingVertical: 2,
      fontFamily: fonts.bodyMedium,
      fontSize: 12,
      overflow: "hidden",
    },
    empty: {
      fontFamily: fonts.body,
      fontSize: 14,
      lineHeight: 20,
    },
    errorBox: {
      padding: spacing.lg,
      gap: spacing.sm,
    },
    errorTitle: {
      fontFamily: fonts.bodySemiBold,
      fontSize: 18,
    },
  });
