import { useEffect, useMemo, useState } from "react";
import {
  Alert,
  Modal,
  Pressable,
  ScrollView,
  StyleSheet,
  Text,
  View,
} from "react-native";

import { FilterChip } from "@/components/FilterChip";
import { Button } from "@/components/ui/Button";
import { DateTimeField } from "@/components/ui/DateTimeField";
import { Input } from "@/components/ui/Input";
import { fonts, spacing } from "@/constants/theme";
import { useAppTheme } from "@/contexts/ThemeContext";
import { formatCurrency } from "@/lib/format";
import { parseNonNegativeNumber } from "@/lib/form-validation";
import type { ThemeColors } from "@/lib/theme-palette";
import { useThemedStyles } from "@/lib/use-themed-styles";
import { api } from "@/lib/trpc";

type TimeEntryEditSheetProps = {
  entryId: string | null;
  visible: boolean;
  onClose: () => void;
};

export function TimeEntryEditSheet({ entryId, visible, onClose }: TimeEntryEditSheetProps) {
  const { colors } = useAppTheme();
  const styles = useThemedStyles(createStyles);
  const utils = api.useUtils();

  const entryQuery = api.timeEntries.getById.useQuery(
    { id: entryId ?? "" },
    { enabled: visible && Boolean(entryId) },
  );
  const clientsQuery = api.clients.getAll.useQuery(undefined, { enabled: visible });

  const [description, setDescription] = useState("");
  const [clientId, setClientId] = useState("");
  const [invoiceId, setInvoiceId] = useState("");
  const [rateText, setRateText] = useState("");
  const [startedAt, setStartedAt] = useState(() => new Date());
  const [endedAt, setEndedAt] = useState(() => new Date());

  const billableQuery = api.invoices.getBillable.useQuery(
    clientId ? { clientId } : undefined,
    { enabled: visible && Boolean(clientId) },
  );

  useEffect(() => {
    const entry = entryQuery.data;
    if (!entry) return;
    setDescription(entry.description ?? "");
    setClientId(entry.clientId ?? "");
    setInvoiceId(entry.invoiceId ?? "");
    setRateText(entry.rate != null ? String(entry.rate) : "");
    setStartedAt(new Date(entry.startedAt));
    setEndedAt(entry.endedAt ? new Date(entry.endedAt) : new Date());
  }, [entryQuery.data]);

  const hoursPreview = useMemo(() => {
    if (endedAt <= startedAt) return null;
    return Math.max(0, (endedAt.getTime() - startedAt.getTime()) / 3_600_000);
  }, [endedAt, startedAt]);

  const rate = parseNonNegativeNumber(rateText);

  const updateEntry = api.timeEntries.update.useMutation({
    onSuccess: async () => {
      await Promise.all([
        utils.timeEntries.getAll.invalidate(),
        utils.timeEntries.getById.invalidate(),
        utils.invoices.getAll.invalidate(),
        utils.dashboard.getStats.invalidate(),
      ]);
      onClose();
    },
    onError: (err) => Alert.alert("Could not save", err.message),
  });

  const deleteEntry = api.timeEntries.delete.useMutation({
    onSuccess: async () => {
      await Promise.all([
        utils.timeEntries.getAll.invalidate(),
        utils.invoices.getAll.invalidate(),
        utils.dashboard.getStats.invalidate(),
      ]);
      onClose();
    },
    onError: (err) => Alert.alert("Could not delete", err.message),
  });

  function handleSave() {
    if (!entryId) return;
    if (endedAt <= startedAt) {
      Alert.alert("Invalid times", "End time must be after start time.");
      return;
    }

    updateEntry.mutate({
      id: entryId,
      description,
      clientId: clientId || "",
      invoiceId: invoiceId || "",
      rate: rate ?? undefined,
      startedAt,
      endedAt,
      hours: hoursPreview ?? undefined,
    });
  }

  function confirmDelete() {
    if (!entryId) return;
    Alert.alert("Delete time entry?", "This removes the entry and any linked invoice line.", [
      { text: "Cancel", style: "cancel" },
      {
        text: "Delete",
        style: "destructive",
        onPress: () => deleteEntry.mutate({ id: entryId }),
      },
    ]);
  }

  return (
    <Modal visible={visible} animationType="slide" presentationStyle="pageSheet" onRequestClose={onClose}>
      <View style={[styles.container, { backgroundColor: colors.background }]}>
        <View style={styles.header}>
          <Text style={[styles.title, { color: colors.foreground }]}>Edit time entry</Text>
          <Pressable onPress={onClose} hitSlop={8}>
            <Text style={[styles.close, { color: colors.mutedForeground }]}>Close</Text>
          </Pressable>
        </View>

        <ScrollView contentContainerStyle={styles.body} keyboardShouldPersistTaps="handled">
          {entryQuery.isLoading ? (
            <Text style={{ color: colors.mutedForeground }}>Loading…</Text>
          ) : (
            <>
              <Input label="Description" value={description} onChangeText={setDescription} />

              <Text style={[styles.label, { color: colors.foreground }]}>Client</Text>
              <View style={styles.chipWrap}>
                <FilterChip
                  label="None"
                  active={!clientId}
                  onPress={() => {
                    setClientId("");
                    setInvoiceId("");
                  }}
                />
                {(clientsQuery.data ?? []).map((client) => (
                  <FilterChip
                    key={client.id}
                    label={client.name}
                    active={clientId === client.id}
                    onPress={() => {
                      setClientId(client.id);
                      setInvoiceId("");
                    }}
                  />
                ))}
              </View>

              {clientId ? (
                <>
                  <Text style={[styles.label, { color: colors.foreground }]}>Invoice</Text>
                  <View style={styles.chipWrap}>
                    <FilterChip
                      label="Not on invoice"
                      active={!invoiceId}
                      onPress={() => setInvoiceId("")}
                    />
                    {(billableQuery.data ?? []).map((invoice) => (
                      <FilterChip
                        key={invoice.id}
                        label={`${invoice.invoicePrefix ?? "#"}${invoice.invoiceNumber}`}
                        active={invoiceId === invoice.id}
                        onPress={() => setInvoiceId(invoice.id)}
                      />
                    ))}
                  </View>
                </>
              ) : null}

              <Input
                label="Hourly rate"
                value={rateText}
                onChangeText={setRateText}
                keyboardType="decimal-pad"
              />

              <DateTimeField
                label="Started"
                value={startedAt}
                maximumDate={endedAt}
                onChange={setStartedAt}
              />
              <DateTimeField label="Ended" value={endedAt} minimumDate={startedAt} onChange={setEndedAt} />

              {hoursPreview != null ? (
                <Text style={[styles.preview, { color: colors.mutedForeground }]}>
                  {hoursPreview.toFixed(2)}h
                  {rate != null && rate > 0
                    ? ` · ${formatCurrency(hoursPreview * rate)}`
                    : ""}
                </Text>
              ) : null}

              <Button title="Save changes" loading={updateEntry.isPending} onPress={handleSave} />
              <Button
                title="Delete entry"
                variant="danger"
                loading={deleteEntry.isPending}
                onPress={confirmDelete}
              />
            </>
          )}
        </ScrollView>
      </View>
    </Modal>
  );
}

const createStyles = (colors: ThemeColors) =>
  StyleSheet.create({
    container: {
      flex: 1,
    },
    header: {
      flexDirection: "row",
      alignItems: "center",
      justifyContent: "space-between",
      paddingHorizontal: spacing.lg,
      paddingTop: spacing.lg,
      paddingBottom: spacing.md,
      borderBottomWidth: 1,
      borderBottomColor: colors.border,
    },
    title: {
      fontFamily: fonts.bodySemiBold,
      fontSize: 18,
    },
    close: {
      fontFamily: fonts.bodyMedium,
      fontSize: 15,
    },
    body: {
      padding: spacing.lg,
      gap: spacing.md,
    },
    label: {
      fontFamily: fonts.bodySemiBold,
      fontSize: 14,
    },
    chipWrap: {
      flexDirection: "row",
      flexWrap: "wrap",
      gap: spacing.sm,
    },
    preview: {
      fontFamily: fonts.body,
      fontSize: 14,
    },
  });
