import { useRef, useState } from "react";
import {
  ActivityIndicator,
  Alert,
  Linking,
  Modal,
  Pressable,
  ScrollView,
  Text,
  TextInput,
  View,
} from "react-native";
import { CameraView, useCameraPermissions } from "expo-camera";
import { readAsStringAsync, EncodingType } from "expo-file-system/legacy";
import { useRouter } from "expo-router";
import { Ionicons } from "@expo/vector-icons";
import { useTranslation } from "react-i18next";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { useQueryClient } from "@tanstack/react-query";

import { apiRequest } from "@/src/lib/api-client";
import { useCategories } from "@/src/hooks/useCategories";
import { TAB_COLORS } from "@/src/constants/colors";

const ACCENT = TAB_COLORS.household;

type ScreenState = "camera" | "scanning" | "confirm" | "booking";

type OcrResponse = {
  amount: number | null;
  label: string | null;
  date: string | null;
  confidence: number;
};

type CreateTransactionBody = {
  amount: number;
  merchant: string;
  description: string;
  date: string;
  type: "expense";
  scope: "household" | "private";
  categoryId?: string;
};

const FALLBACK_CATEGORIES = [
  "Lebensmittel",
  "Restaurant",
  "Transport",
  "Shopping",
  "Haushalt",
  "Sonstiges",
];

function todayIso(): string {
  return new Date().toISOString().slice(0, 10);
}

export default function ScannerScreen() {
  const { t } = useTranslation();
  const router = useRouter();
  const insets = useSafeAreaInsets();
  const queryClient = useQueryClient();

  const [permission, requestPermission] = useCameraPermissions();
  const cameraRef = useRef<CameraView>(null);

  const [screenState, setScreenState] = useState<ScreenState>("camera");
  const [cameraKey, setCameraKey] = useState(0);

  // Confirm sheet state
  const [label, setLabel] = useState("");
  const [amountStr, setAmountStr] = useState("");
  const [date, setDate] = useState(todayIso()); // always YYYY-MM-DD internally
  const [dateDisplay, setDateDisplay] = useState(() => {
    const d = todayIso();
    return `${d.slice(8, 10)}.${d.slice(5, 7)}.${d.slice(0, 4)}`;
  });
  const [selectedCategoryId, setSelectedCategoryId] = useState<string | undefined>(undefined);
  const [scope, setScope] = useState<"household" | "private">("household");

  const { data: categories = [] } = useCategories();
  const expenseCategories = categories.filter((c) => c.type === "expense");
  const displayCategories =
    expenseCategories.length > 0
      ? expenseCategories.map((c) => ({ id: c.id, name: c.name }))
      : FALLBACK_CATEGORIES.map((name, i) => ({ id: String(i), name }));

  // ── Permission not yet determined ─────────────────────────────────────────
  if (!permission) {
    return (
      <View className="flex-1 bg-black items-center justify-center">
        <ActivityIndicator color="#fff" />
      </View>
    );
  }

  // ── Permission denied ─────────────────────────────────────────────────────
  if (!permission.granted) {
    return (
      <View
        className="flex-1 bg-black items-center justify-center px-8 gap-4"
        style={{ paddingTop: insets.top, paddingBottom: insets.bottom }}
      >
        {/* Back button */}
        <Pressable
          onPress={() => router.back()}
          className="absolute top-0 left-4 p-3"
          style={{ top: insets.top }}
        >
          <Ionicons name="chevron-back" size={26} color="#fff" />
        </Pressable>

        <Ionicons name="camera-outline" size={64} color="#6b7280" />
        <Text className="text-white text-center text-base font-medium">
          {t("scanner.permissionDenied")}
        </Text>
        <Pressable
          onPress={() => void requestPermission()}
          style={{ backgroundColor: ACCENT }}
          className="px-6 py-3 rounded-xl"
        >
          <Text className="text-white font-semibold">{t("scanner.openSettings")}</Text>
        </Pressable>
        <Pressable
          onPress={() => void Linking.openSettings()}
          className="px-6 py-3"
        >
          <Text className="text-gray-400 text-sm">{t("scanner.openSettings")}</Text>
        </Pressable>
      </View>
    );
  }

  // ── Capture & OCR ─────────────────────────────────────────────────────────
  async function handleCapture() {
    if (!cameraRef.current) return;
    setScreenState("scanning");

    try {
      const photo = await cameraRef.current.takePictureAsync({ base64: false, quality: 0.7 });
      if (!photo?.uri) throw new Error("No photo URI");

      const base64 = await readAsStringAsync(photo.uri, {
        encoding: EncodingType.Base64,
      });

      const result = await apiRequest<OcrResponse>("/api/scanner/receipt", {
        method: "POST",
        body: JSON.stringify({ imageBase64: base64, mimeType: "image/jpeg" }),
      });

      setLabel(result.label ?? "");
      setAmountStr(result.amount != null ? String(result.amount) : "");
      const isoDate = result.date ?? todayIso();
      setDate(isoDate);
      setDateDisplay(`${isoDate.slice(8, 10)}.${isoDate.slice(5, 7)}.${isoDate.slice(0, 4)}`);
      setScreenState("confirm");
    } catch {
      Alert.alert(t("common.error"), t("scanner.error"));
      setScreenState("camera");
    }
  }

  // ── Book transaction ──────────────────────────────────────────────────────
  async function handleBook() {
    const amount = parseFloat(amountStr.replace(",", "."));
    if (!amount || amount <= 0) {
      Alert.alert(t("common.error"), t("scanner.notRecognized"));
      return;
    }

    setScreenState("booking");
    try {
      const body: CreateTransactionBody = {
        amount,
        merchant: label.trim() || t("scanner.title"),
        description: label.trim() || t("scanner.title"),
        date: new Date(date).toISOString(),
        type: "expense",
        scope,
        ...(selectedCategoryId ? { categoryId: selectedCategoryId } : {}),
      };
      await apiRequest<unknown>("/api/transactions", {
        method: "POST",
        body: JSON.stringify(body),
      });
      await queryClient.invalidateQueries({ queryKey: ["transactions"] });
      handleRetry(); // reset all state
      router.back();
    } catch {
      Alert.alert(t("common.error"), t("scanner.error"));
      setScreenState("confirm");
    }
  }

  function handleRetry() {
    const today = todayIso();
    setScreenState("camera");
    setLabel("");
    setAmountStr("");
    setDate(today);
    setDateDisplay(`${today.slice(8, 10)}.${today.slice(5, 7)}.${today.slice(0, 4)}`);
    setSelectedCategoryId(undefined);
    setScope("household");
    setCameraKey((k) => k + 1);
  }

  // ── Render ─────────────────────────────────────────────────────────────────
  return (
    <View className="flex-1 bg-black">
      {/* Camera */}
      <CameraView
        key={cameraKey}
        ref={cameraRef}
        style={{ flex: 1 }}
        facing="back"
      />

      {/* Header overlay */}
      <View
        className="absolute left-0 right-0 flex-row items-center px-4"
        style={{ top: insets.top, paddingTop: 8 }}
      >
        <Pressable
          onPress={() => router.back()}
          className="w-10 h-10 rounded-full bg-black/40 items-center justify-center"
        >
          <Ionicons name="chevron-back" size={22} color="#fff" />
        </Pressable>
        <Text className="flex-1 text-center text-white font-semibold text-base mr-10">
          {t("scanner.title")}
        </Text>
      </View>

      {/* Hint text */}
      {screenState === "camera" && (
        <View
          className="absolute left-0 right-0 items-center"
          style={{ top: insets.top + 64 }}
        >
          <View className="bg-black/40 px-4 py-2 rounded-full">
            <Text className="text-white text-sm">{t("scanner.hint")}</Text>
          </View>
        </View>
      )}

      {/* Viewfinder frame */}
      {screenState === "camera" && (
        <View className="absolute inset-0 items-center justify-center">
          <View
            className="border-2 border-white/60 rounded-2xl"
            style={{ width: "85%", height: "75%" }}
          />
        </View>
      )}

      {/* Capture button */}
      {screenState === "camera" && (
        <View
          className="absolute left-0 right-0 items-center"
          style={{ bottom: insets.bottom + 40 }}
        >
          <Pressable
            onPress={() => void handleCapture()}
            className="w-[72px] h-[72px] rounded-full bg-white items-center justify-center active:opacity-80"
            style={{
              shadowColor: "#000",
              shadowOpacity: 0.3,
              shadowRadius: 8,
              shadowOffset: { width: 0, height: 2 },
            }}
          >
            <View className="w-16 h-16 rounded-full border-4 border-gray-300" />
          </Pressable>
          <Text className="text-white/70 text-xs mt-3">{t("scanner.capture")}</Text>
        </View>
      )}

      {/* Scanning overlay */}
      {screenState === "scanning" && (
        <View className="absolute inset-0 bg-black/70 items-center justify-center gap-4">
          <ActivityIndicator size="large" color="#fff" />
          <Text className="text-white text-base font-medium">{t("scanner.scanning")}</Text>
        </View>
      )}

      {/* Booking overlay */}
      {screenState === "booking" && (
        <View className="absolute inset-0 bg-black/70 items-center justify-center gap-4">
          <ActivityIndicator size="large" color="#fff" />
          <Text className="text-white text-base font-medium">{t("common.loading")}</Text>
        </View>
      )}

      {/* Confirmation sheet */}
      <Modal
        visible={screenState === "confirm"}
        animationType="slide"
        presentationStyle="pageSheet"
        onRequestClose={handleRetry}
      >
        <View className="flex-1 bg-white">
          {/* Sheet header */}
          <View
            className="flex-row items-center px-4 py-4 border-b border-gray-100"
            style={{ paddingTop: insets.top > 0 ? 12 : 12 }}
          >
            <Pressable onPress={handleRetry} className="py-1 pr-4">
              <Text className="text-base" style={{ color: ACCENT }}>
                {t("scanner.retry")}
              </Text>
            </Pressable>
            <Text className="flex-1 text-center font-semibold text-base text-gray-900">
              {t("scanner.detected")}
            </Text>
            <Pressable
              onPress={() => void handleBook()}
              className="py-1 pl-4"
              style={{ opacity: !amountStr || parseFloat(amountStr) <= 0 ? 0.4 : 1 }}
              disabled={!amountStr || parseFloat(amountStr) <= 0}
            >
              <Text className="text-base font-semibold" style={{ color: ACCENT }}>
                {t("scanner.book")}
              </Text>
            </Pressable>
          </View>

          <ScrollView className="flex-1 px-4 pt-4" keyboardShouldPersistTaps="handled">
            {/* Merchant */}
            <Text className="text-xs text-gray-400 font-medium mb-1 ml-1">
              {t("scanner.merchant").toUpperCase()}
            </Text>
            <TextInput
              value={label}
              onChangeText={setLabel}
              placeholder={t("scanner.merchant")}
              placeholderTextColor="#9ca3af"
              className="bg-gray-50 border border-gray-200 rounded-xl px-4 py-3 text-base text-gray-900 mb-4"
            />

            {/* Amount */}
            <Text className="text-xs text-gray-400 font-medium mb-1 ml-1">
              {t("scanner.amount").toUpperCase()}
            </Text>
            <View className="bg-gray-50 border border-gray-200 rounded-xl px-4 py-3 flex-row items-center mb-4">
              <TextInput
                value={amountStr}
                onChangeText={setAmountStr}
                placeholder="0.00"
                placeholderTextColor="#9ca3af"
                keyboardType="decimal-pad"
                className="flex-1 text-base text-gray-900"
              />
              <Text className="text-base text-gray-400 ml-2">€</Text>
            </View>

            {/* Date */}
            <Text className="text-xs text-gray-400 font-medium mb-1 ml-1">
              {t("scanner.date").toUpperCase()}
            </Text>
            <TextInput
              value={dateDisplay}
              onChangeText={(v) => {
                setDateDisplay(v);
                // Convert DD.MM.YYYY → YYYY-MM-DD for internal state
                const parts = v.split(".");
                if (parts.length === 3 && parts[2]?.length === 4) {
                  setDate(`${parts[2]}-${parts[1]?.padStart(2, "0")}-${parts[0]?.padStart(2, "0")}`);
                }
              }}
              placeholder="TT.MM.JJJJ"
              placeholderTextColor="#9ca3af"
              keyboardType="numbers-and-punctuation"
              className="bg-gray-50 border border-gray-200 rounded-xl px-4 py-3 text-base text-gray-900 mb-4"
            />

            {/* Category */}
            <Text className="text-xs text-gray-400 font-medium mb-2 ml-1">
              {t("scanner.category").toUpperCase()}
            </Text>
            <ScrollView
              horizontal
              showsHorizontalScrollIndicator={false}
              className="mb-4"
              contentContainerStyle={{ gap: 8, paddingRight: 16 }}
            >
              {displayCategories.map((cat) => {
                const isSelected = selectedCategoryId === cat.id;
                return (
                  <Pressable
                    key={cat.id}
                    onPress={() =>
                      setSelectedCategoryId(isSelected ? undefined : cat.id)
                    }
                    style={{
                      backgroundColor: isSelected ? ACCENT : "#f3f4f6",
                      borderWidth: 1,
                      borderColor: isSelected ? ACCENT : "#e5e7eb",
                    }}
                    className="px-4 py-2 rounded-full active:opacity-70"
                  >
                    <Text
                      className="text-sm font-medium"
                      style={{ color: isSelected ? "#fff" : "#4b5563" }}
                    >
                      {cat.name}
                    </Text>
                  </Pressable>
                );
              })}
            </ScrollView>

            {/* Scope */}
            <Text className="text-xs text-gray-400 font-medium mb-2 ml-1">
              {t("scanner.scope").toUpperCase()}
            </Text>
            <View className="flex-row gap-3 mb-8">
              <Pressable
                onPress={() => setScope("household")}
                style={{
                  flex: 1,
                  backgroundColor: scope === "household" ? ACCENT : "#f3f4f6",
                  borderWidth: 1,
                  borderColor: scope === "household" ? ACCENT : "#e5e7eb",
                }}
                className="py-3 rounded-xl items-center active:opacity-70"
              >
                <Text
                  className="text-sm font-semibold"
                  style={{ color: scope === "household" ? "#fff" : "#4b5563" }}
                >
                  {t("scanner.household")}
                </Text>
              </Pressable>
              <Pressable
                onPress={() => setScope("private")}
                style={{
                  flex: 1,
                  backgroundColor: scope === "private" ? "#7C3AED" : "#f3f4f6",
                  borderWidth: 1,
                  borderColor: scope === "private" ? "#7C3AED" : "#e5e7eb",
                }}
                className="py-3 rounded-xl items-center active:opacity-70"
              >
                <Text
                  className="text-sm font-semibold"
                  style={{ color: scope === "private" ? "#fff" : "#4b5563" }}
                >
                  {t("scanner.private")}
                </Text>
              </Pressable>
            </View>
          </ScrollView>
        </View>
      </Modal>
    </View>
  );
}
