import { router, Stack, useLocalSearchParams } from "expo-router";
import { useMemo, useState } from "react";
import { Alert, Platform, ScrollView, StyleSheet, Text, View } from "react-native";

import { AppBackground } from "@/components/AppBackground";
import { InvoiceViewChips, type InvoiceViewSection } from "@/components/invoices/InvoiceViewChips";
import { InvoicePdfPreview } from "@/components/invoices/InvoicePdfPreview";
import { InvoiceTotals } from "@/components/invoices/InvoiceTotals";
import { InvoiceDetailActions } from "@/components/invoices/InvoiceDetailActions";
import { LoadingScreen } from "@/components/LoadingScreen";
import { SwipeableRow } from "@/components/SwipeableRow";
import { StatusBadge } from "@/components/StatusBadge";
import { Button } from "@/components/ui/Button";
import { Card } from "@/components/ui/Card";
import { fonts, spacing } from "@/constants/theme";
import { useAppTheme } from "@/contexts/ThemeContext";
import { formatCurrency, formatDate } from "@/lib/format";
import type { ThemeColors } from "@/lib/theme-palette";
import { useThemedStyles } from "@/lib/use-themed-styles";
import { getInvoiceStatus, type InvoiceStatus } from "@/lib/invoice-status";
import { buildPreviewPdfInputFromInvoice } from "@/lib/invoice-pdf-input";
import { useTabBarScrollPadding } from "@/lib/tab-bar-insets";
import { api } from "@/lib/trpc";

export default function InvoiceDetailScreen() {
  const styles = useThemedStyles(createInvoiceDetailStyles);
  const { colors } = useAppTheme();
  const { id } = useLocalSearchParams<{ id: string }>();
  const utils = api.useUtils();
  const scrollPadding = useTabBarScrollPadding();
  const [section, setSection] = useState<InvoiceViewSection>("details");

  const invoiceQuery = api.invoices.getById.useQuery(
    { id: id ?? "" },
    { enabled: Boolean(id) },
  );

  const updateStatus = api.invoices.updateStatus.useMutation({
    onSuccess: () => {
      void utils.invoices.getById.invalidate({ id: id ?? "" });
      void utils.invoices.getAll.invalidate();
      void utils.dashboard.getStats.invalidate();
    },
    onError: (err) => Alert.alert("Update failed", err.message),
  });

  const sendPaymentReminder = api.invoices.sendReminder.useMutation({
    onSuccess: () => {
      Alert.alert("Reminder sent", "Payment reminder emailed to the client.");
      void utils.invoices.getById.invalidate({ id: id ?? "" });
    },
    onError: (err) => Alert.alert("Could not send reminder", err.message),
  });

  const previewInput = useMemo(
    () => (invoiceQuery.data ? buildPreviewPdfInputFromInvoice(invoiceQuery.data) : null),
    [invoiceQuery.data],
  );

  if (!id) {
    return <LoadingScreen message="Invalid invoice" />;
  }

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

  if (invoiceQuery.error || !invoiceQuery.data) {
    return (
      <AppBackground>
        <View style={styles.errorBox}>
          <Text style={styles.errorTitle}>Could not load invoice</Text>
          <Text style={styles.errorText}>
            {invoiceQuery.error?.message ?? "Invoice not found"}
          </Text>
          <Button title="Go back" variant="secondary" onPress={() => router.back()} />
        </View>
      </AppBackground>
    );
  }

  const invoice = invoiceQuery.data;
  const status = getInvoiceStatus(invoice);
  const subtotal = invoice.items.reduce((sum, item) => sum + item.amount, 0);
  const taxAmount = subtotal * (invoice.taxRate / 100);
  const clientEmail = invoice.client?.email?.trim() ?? "";

  function openSendScreen() {
    if (!clientEmail) {
      Alert.alert(
        "No client email",
        "Add an email address to this client on the web app before sending invoices.",
      );
      return;
    }
    if (invoice.items.length === 0) {
      Alert.alert(
        "No line items",
        "Add line items or clock time to this invoice before sending.",
      );
      return;
    }
    router.push(`/(app)/invoices/send/${invoice.id}`);
  }

  function promptPaymentReminder() {
    if (!clientEmail) {
      Alert.alert(
        "No client email",
        "Add an email address to this client before sending payment reminders.",
      );
      return;
    }

    Alert.alert(
      "Send payment reminder",
      `Email a payment reminder to ${clientEmail}?`,
      [
        { text: "Cancel", style: "cancel" },
        {
          text: "Send",
          onPress: () => sendPaymentReminder.mutate({ id: invoice.id }),
        },
      ],
    );
  }

  function promptStatusChange(current: InvoiceStatus) {
    const options: Array<{ label: string; status: "draft" | "sent" | "paid" }> = [];
    if (current !== "draft") options.push({ label: "Mark as draft", status: "draft" });
    if (current !== "sent" && current !== "overdue") {
      options.push({ label: "Mark as sent", status: "sent" });
    }
    if (current !== "paid") options.push({ label: "Mark as paid", status: "paid" });
    if (options.length === 0) return;

    Alert.alert("Update status", "Choose a new status", [
      ...options.map((option) => ({
        text: option.label,
        onPress: () => updateStatus.mutate({ id: invoice.id, status: option.status }),
      })),
      { text: "Cancel", style: "cancel" },
    ]);
  }

  return (
    <AppBackground>
      <Stack.Screen options={{ headerBackTitle: "Invoices" }} />
      <ScrollView
        style={styles.scroll}
        contentContainerStyle={[styles.container, { paddingBottom: scrollPadding }]}
        contentInsetAdjustmentBehavior={Platform.OS === "ios" ? "never" : undefined}
        scrollIndicatorInsets={{ bottom: scrollPadding }}
        keyboardShouldPersistTaps="handled"
      >
        <Card>
          <View style={styles.headerRow}>
            <View style={styles.headerMeta}>
              <Text style={styles.invoiceNumber}>
                {invoice.invoicePrefix}
                {invoice.invoiceNumber}
              </Text>
              <Text style={styles.clientName}>{invoice.client?.name ?? "Client"}</Text>
            </View>
            <StatusBadge status={status} />
          </View>
          <Text style={styles.total}>
            {formatCurrency(invoice.totalAmount, invoice.currency)}
          </Text>
        </Card>

        <InvoiceViewChips
          section={section}
          onSectionChange={setSection}
          status={status}
          onEdit={() => router.push(`/(app)/invoices/edit/${invoice.id}`)}
          onSend={openSendScreen}
        />

        {section === "preview" ? (
          <Card title="PDF preview">
            <InvoicePdfPreview input={previewInput} />
          </Card>
        ) : (
          <>
        <Card title="Details">
          <DetailRow label="Business" value={invoice.business?.name ?? "—"} />
          <DetailRow label="Client" value={invoice.client?.name ?? "Client"} />
          <DetailRow label="Issued" value={formatDate(invoice.issueDate)} />
          <DetailRow label="Due" value={formatDate(invoice.dueDate)} />
          <DetailRow label="Currency" value={invoice.currency} />
          {invoice.taxRate > 0 ? (
            <DetailRow label="Tax rate" value={`${invoice.taxRate}%`} />
          ) : null}
          {invoice.status === "draft" && invoice.sendReminderAt ? (
            <DetailRow
              label="Send reminder"
              value={
                new Date(invoice.sendReminderAt) <= new Date()
                  ? "Due now"
                  : formatDate(invoice.sendReminderAt)
              }
            />
          ) : null}
        </Card>

        <Card title="Line items">
          {invoice.items.length === 0 ? (
            <Text style={styles.emptyLines}>
              No line items yet. Clock time to this invoice from the Timer tab, or edit to
              add lines manually.
            </Text>
          ) : (
            invoice.items.map((item) => {
              const line = (
                <View style={styles.lineItem}>
                  <View style={styles.lineMeta}>
                    <Text style={styles.lineDescription}>{item.description}</Text>
                    <Text style={styles.lineSub}>
                      {formatDate(item.date)} · {item.hours}h ×{" "}
                      {formatCurrency(item.rate, invoice.currency)}
                    </Text>
                  </View>
                  <Text style={styles.lineAmount}>
                    {formatCurrency(item.amount, invoice.currency)}
                  </Text>
                </View>
              );

              if (invoice.status !== "draft") {
                return <View key={item.id}>{line}</View>;
              }

              return (
                <SwipeableRow
                  key={item.id}
                  backgroundColor={colors.card}
                  actions={[
                    {
                      key: "edit",
                      label: "Edit",
                      icon: "create-outline",
                      color: "#fff",
                      backgroundColor: colors.primary,
                      onPress: () => router.push(`/(app)/invoices/edit/${invoice.id}`),
                    },
                  ]}
                >
                  {line}
                </SwipeableRow>
              );
            })
          )}
          <InvoiceTotals
            subtotal={formatCurrency(subtotal, invoice.currency)}
            taxLabel={invoice.taxRate > 0 ? `Tax (${invoice.taxRate}%)` : undefined}
            taxAmount={
              invoice.taxRate > 0 ? formatCurrency(taxAmount, invoice.currency) : undefined
            }
            total={formatCurrency(invoice.totalAmount, invoice.currency)}
          />
        </Card>

        {invoice.notes ? (
          <Card title="Notes">
            <Text style={styles.notes}>{invoice.notes}</Text>
          </Card>
        ) : null}

        <InvoiceDetailActions
          status={status}
          clientEmail={clientEmail}
          onPaymentReminder={
            status === "sent" || status === "overdue" ? promptPaymentReminder : undefined
          }
          paymentReminderLoading={sendPaymentReminder.isPending}
          onUpdateStatus={() => promptStatusChange(status)}
          updateStatusLoading={updateStatus.isPending}
          onTrackTime={() =>
            router.push(`/(app)/timer?clientId=${invoice.clientId}&invoiceId=${invoice.id}`)
          }
        />
          </>
        )}
      </ScrollView>
    </AppBackground>
  );
}

function DetailRow({ label, value }: { label: string; value: string }) {
  const { colors } = useAppTheme();
  return (
    <View style={detailStyles.row}>
      <Text style={[detailStyles.label, { color: colors.mutedForeground }]}>{label}</Text>
      <Text style={[detailStyles.value, { color: colors.foreground }]}>{value}</Text>
    </View>
  );
}

const detailStyles = StyleSheet.create({
  row: {
    flexDirection: "row",
    justifyContent: "space-between",
    gap: spacing.md,
    paddingVertical: 4,
  },
  label: {
    fontSize: 14,
    fontFamily: fonts.body,
  },
  value: {
    fontSize: 14,
    fontFamily: fonts.bodyMedium,
  },
});

const createInvoiceDetailStyles = (colors: ThemeColors, _isDark: boolean) =>
  StyleSheet.create({
  scroll: {
    flex: 1,
  },
  container: {
    padding: spacing.md,
    gap: spacing.md,
  },
  headerRow: {
    flexDirection: "row",
    justifyContent: "space-between",
    alignItems: "flex-start",
    gap: spacing.md,
  },
  headerMeta: {
    flex: 1,
    gap: 4,
  },
  invoiceNumber: {
    fontSize: 22,
    lineHeight: 26,
    fontFamily: fonts.heading,
    color: colors.foreground,
  },
  clientName: {
    fontSize: 15,
    fontFamily: fonts.body,
    color: colors.mutedForeground,
  },
  total: {
    marginTop: spacing.sm,
    fontSize: 28,
    fontFamily: fonts.bodySemiBold,
    color: colors.foreground,
  },
  lineItem: {
    flexDirection: "row",
    justifyContent: "space-between",
    gap: spacing.md,
    paddingVertical: spacing.sm,
    borderTopWidth: 1,
    borderTopColor: colors.border,
  },
  lineMeta: {
    flex: 1,
    gap: 2,
  },
  lineDescription: {
    fontFamily: fonts.bodyMedium,
    color: colors.foreground,
    fontSize: 14,
  },
  lineSub: {
    fontFamily: fonts.body,
    color: colors.mutedForeground,
    fontSize: 12,
  },
  lineAmount: {
    fontFamily: fonts.bodySemiBold,
    color: colors.foreground,
    fontSize: 14,
  },
  emptyLines: {
    fontFamily: fonts.body,
    fontSize: 14,
    lineHeight: 20,
    color: colors.mutedForeground,
  },
  notes: {
    fontFamily: fonts.body,
    color: colors.foreground,
    fontSize: 14,
    lineHeight: 20,
  },
  errorBox: {
    flex: 1,
    justifyContent: "center",
    padding: spacing.lg,
    gap: spacing.md,
  },
  errorTitle: {
    fontSize: 18,
    fontFamily: fonts.bodySemiBold,
    color: colors.foreground,
  },
  errorText: {
    color: colors.mutedForeground,
    fontFamily: fonts.body,
    lineHeight: 20,
  },
});
