import React, { useCallback, useRef, useState } from 'react';
import {
  ActivityIndicator,
  Alert,
  Modal,
  StyleSheet,
  Text,
  TextInput,
  TouchableOpacity,
  View,
} from 'react-native';
import {
  Camera,
  useCameraDevice,
  useCameraPermission,
  useCodeScanner,
} from 'react-native-vision-camera';
import { useNavigation } from '@react-navigation/native';
import type { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { ps } from '@/api/client';
import type { RootStackParamList } from '@/navigation/RootNavigator';

type Nav = NativeStackNavigationProp<RootStackParamList>;

/**
 * Interpret a scanned code. Kiosk QR codes come in two flavors:
 *  - a raw scanner/zone code (e.g. "DSB13") -> use directly
 *  - a ParkSmarter/ips-txt2pay URL. If it has a query with the code
 *    (…/processQR?code=DSB13) we extract it; a bare app-link URL (this older
 *    sticker: …/processQR) carries no zone, so we ask for the printed Zone ID.
 */
export function parseScannedCode(raw: string): { code?: string; isAppLink?: boolean } {
  const v = raw.trim();
  if (!/^https?:\/\//i.test(v)) return { code: v };
  if (v.length > 255) return {};
  const lower = v.toLowerCase();
  if (!(lower.includes('parksmarter.com') || lower.includes('ips-txt2pay'))) {
    return { isAppLink: true };
  }
  const q = v.split('?')[1];
  if (!q) return { isAppLink: true };
  for (const pair of q.split('&')) {
    const [k, val] = pair.split('=');
    if (val && /^(code|zone|zoneid|m|meter)$/i.test(k)) {
      return { code: decodeURIComponent(val) };
    }
  }
  const bare = q.split('&')[0];
  if (bare && !bare.includes('=')) return { code: decodeURIComponent(bare) };
  return { isAppLink: true };
}

export function ScanScreen() {
  const navigation = useNavigation<Nav>();
  const { hasPermission, requestPermission } = useCameraPermission();
  const device = useCameraDevice('back');
  const [busy, setBusy] = useState(false);
  const [manualOpen, setManualOpen] = useState(false);
  const [manual, setManual] = useState('');
  const lock = useRef(false);

  React.useEffect(() => {
    if (!hasPermission) void requestPermission();
  }, [hasPermission, requestPermission]);

  const lookupCode = useCallback(
    async (code: string) => {
      setBusy(true);
      try {
        let res = await ps.getMetersByScannerCode(code);
        let zone = res.Zones?.[0];
        if (!zone) {
          res = await ps.getMetersByZoneName(code);
          zone = res.Zones?.[0];
        }
        if (zone) {
          setManualOpen(false);
          navigation.navigate('MeterDetail', { zone });
        } else {
          Alert.alert('Not found', `No meter matches "${code}".`);
        }
      } catch (e: any) {
        Alert.alert('Lookup failed', e?.serverMessage ?? e?.message ?? 'error');
      } finally {
        setBusy(false);
      }
    },
    [navigation],
  );

  const onScanned = useCallback(
    async (raw: string) => {
      if (lock.current) return;
      lock.current = true;
      try {
        const { code, isAppLink } = parseScannedCode(raw);
        if (code) {
          await lookupCode(code);
        } else if (isAppLink) {
          Alert.alert(
            'App-link QR',
            'This QR just opens the ParkSmarter app — it has no meter info. Enter the Zone ID printed on the kiosk instead.',
            [
              { text: 'Enter Zone ID', onPress: () => setManualOpen(true) },
              { text: 'Cancel', style: 'cancel' },
            ],
          );
        } else {
          Alert.alert('Unrecognized code', 'That QR is not a parking meter code.');
        }
      } finally {
        setTimeout(() => (lock.current = false), 1800);
      }
    },
    [lookupCode],
  );

  const codeScanner = useCodeScanner({
    codeTypes: ['qr', 'ean-13', 'code-128'],
    onCodeScanned: (codes) => {
      const value = codes[0]?.value;
      if (value) void onScanned(value);
    },
  });

  const ManualEntry = () => (
    <Modal visible={manualOpen} transparent animationType="slide" onRequestClose={() => setManualOpen(false)}>
      <View style={styles.modalBackdrop}>
        <View style={styles.modalCard}>
          <Text style={styles.modalTitle}>Enter Zone ID</Text>
          <Text style={styles.modalSub}>The code printed on the kiosk, e.g. DSB13.</Text>
          <TextInput
            style={styles.input}
            placeholder="Zone ID"
            autoCapitalize="characters"
            autoFocus
            value={manual}
            onChangeText={setManual}
          />
          <View style={styles.modalActions}>
            <TouchableOpacity onPress={() => setManualOpen(false)} style={styles.action}>
              <Text style={{ color: '#666', fontWeight: '600' }}>Cancel</Text>
            </TouchableOpacity>
            <TouchableOpacity
              style={styles.lookupBtn}
              disabled={!manual.trim() || busy}
              onPress={() => lookupCode(manual.trim())}
            >
              <Text style={styles.buttonText}>{busy ? 'Looking…' : 'Look up'}</Text>
            </TouchableOpacity>
          </View>
        </View>
      </View>
    </Modal>
  );

  if (!hasPermission) {
    return (
      <View style={styles.center}>
        <Text style={styles.msg}>Camera permission is needed to scan kiosks.</Text>
        <TouchableOpacity style={styles.button} onPress={requestPermission}>
          <Text style={styles.buttonText}>Grant camera access</Text>
        </TouchableOpacity>
        <TouchableOpacity style={[styles.button, styles.buttonAlt]} onPress={() => setManualOpen(true)}>
          <Text style={styles.buttonText}>Enter Zone ID instead</Text>
        </TouchableOpacity>
        <ManualEntry />
      </View>
    );
  }
  if (!device) {
    return (
      <View style={styles.center}>
        <Text style={styles.msg}>No camera available.</Text>
        <TouchableOpacity style={styles.button} onPress={() => setManualOpen(true)}>
          <Text style={styles.buttonText}>Enter Zone ID</Text>
        </TouchableOpacity>
        <ManualEntry />
      </View>
    );
  }

  return (
    <View style={styles.container}>
      <Camera style={StyleSheet.absoluteFill} device={device} isActive codeScanner={codeScanner} />
      <View style={styles.overlay}>
        <View style={styles.reticle} />
        <Text style={styles.hint}>Point at the QR code on the parking kiosk</Text>
      </View>
      <TouchableOpacity style={styles.manualLink} onPress={() => setManualOpen(true)}>
        <Text style={styles.manualText}>Enter Zone ID manually</Text>
      </TouchableOpacity>
      {busy ? (
        <View style={styles.busy}>
          <ActivityIndicator color="#fff" />
          <Text style={styles.busyText}>Looking up meter…</Text>
        </View>
      ) : null}
      <ManualEntry />
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, backgroundColor: '#000' },
  center: { flex: 1, alignItems: 'center', justifyContent: 'center', padding: 24, gap: 12 },
  msg: { fontSize: 16, textAlign: 'center', marginBottom: 8 },
  overlay: { ...StyleSheet.absoluteFillObject, alignItems: 'center', justifyContent: 'center' },
  reticle: { width: 220, height: 220, borderWidth: 3, borderColor: '#fff', borderRadius: 16 },
  hint: { color: '#fff', marginTop: 16, fontSize: 14 },
  button: { backgroundColor: '#1e6f5c', padding: 14, borderRadius: 10 },
  buttonAlt: { backgroundColor: '#555' },
  buttonText: { color: '#fff', fontWeight: '600' },
  manualLink: {
    position: 'absolute',
    bottom: 40,
    alignSelf: 'center',
    backgroundColor: 'rgba(0,0,0,0.6)',
    paddingHorizontal: 16,
    paddingVertical: 10,
    borderRadius: 20,
  },
  manualText: { color: '#fff', fontWeight: '600' },
  busy: {
    position: 'absolute',
    top: 60,
    alignSelf: 'center',
    flexDirection: 'row',
    alignItems: 'center',
    gap: 8,
    backgroundColor: 'rgba(0,0,0,0.7)',
    paddingHorizontal: 16,
    paddingVertical: 10,
    borderRadius: 20,
  },
  busyText: { color: '#fff' },
  modalBackdrop: { flex: 1, backgroundColor: 'rgba(0,0,0,0.5)', justifyContent: 'flex-end' },
  modalCard: { backgroundColor: '#fff', borderTopLeftRadius: 20, borderTopRightRadius: 20, padding: 20, gap: 10 },
  modalTitle: { fontSize: 20, fontWeight: '700' },
  modalSub: { color: '#666', marginBottom: 4 },
  input: { borderWidth: 1, borderColor: '#ccc', borderRadius: 10, padding: 14, fontSize: 18 },
  modalActions: { flexDirection: 'row', justifyContent: 'flex-end', alignItems: 'center', gap: 16, marginTop: 8 },
  action: { paddingHorizontal: 8, paddingVertical: 6 },
  lookupBtn: { backgroundColor: '#1e6f5c', paddingHorizontal: 24, paddingVertical: 12, borderRadius: 10 },
});
