import axios from 'axios';
import * as Location from 'expo-location';
import { Link, useLocalSearchParams, useRouter } from 'expo-router';
import { useEffect, useMemo, useState } from 'react';
import { Alert, Linking, StyleSheet, Text, TextInput, TouchableOpacity, View } from 'react-native';
import { DriverShell } from '../components/driver-shell';
import { API_URL } from '../src/runtime-config';
import { useDriverSession } from '../src/store/session';
import { driverTheme, formatCurrency, formatDistance, toNumber } from '../src/lib/driver-ui';
import { extractErrorMessage, isUnauthorizedError } from '../src/lib/driver-api';

type TrackingPayload = {
  orderId: string;
  trackingStatusLabel: string;
  restaurant: { name: string; latitude?: number | string | null; longitude?: number | string | null; addressLabel?: string | null };
  customer: { name: string; latitude?: number | string | null; longitude?: number | string | null; addressLabel?: string | null };
  delivery: { id: string; status: string; driverEarning?: number | string | null } | null;
  route: { estimatedPickupTime?: number | null; estimatedDeliveryTime?: number | null; pickupDistanceKm?: number | string | null; deliveryDistanceKm?: number | string | null } | null;
};

function validationCode(orderId: string) {
  return orderId.slice(-6).toUpperCase();
}

function encodeMapPoint(latitude?: number | string | null, longitude?: number | string | null, addressLabel?: string | null) {
  const lat = toNumber(latitude);
  const lng = toNumber(longitude);
  if (lat !== null && lng !== null) {
    return `${lat},${lng}`;
  }

  return addressLabel ? encodeURIComponent(addressLabel) : null;
}

async function openPickupMap(tracking: TrackingPayload | null) {
  const pickupPoint = encodeMapPoint(tracking?.restaurant.latitude, tracking?.restaurant.longitude, tracking?.restaurant.addressLabel);

  if (!pickupPoint) {
    Alert.alert('Mapa indisponivel', 'O ponto da loja ainda nao foi localizado.');
    return;
  }

  await Linking.openURL(`https://www.google.com/maps/dir/?api=1&origin=Current+Location&destination=${pickupPoint}&travelmode=driving`);
}

async function openDropoffMap(tracking: TrackingPayload | null) {
  const dropPoint = encodeMapPoint(tracking?.customer.latitude, tracking?.customer.longitude, tracking?.customer.addressLabel);

  if (!dropPoint) {
    Alert.alert('Mapa indisponivel', 'O ponto do cliente ainda nao foi localizado.');
    return;
  }

  await Linking.openURL(`https://www.google.com/maps/dir/?api=1&origin=Current+Location&destination=${dropPoint}&travelmode=driving`);
}

export default function ActiveDeliveryScreen() {
  const router = useRouter();
  const params = useLocalSearchParams<{ orderId?: string; deliveryId?: string }>();
  const { accessToken, clearSession, setOnline } = useDriverSession();
  const [tracking, setTracking] = useState<TrackingPayload | null>(null);
  const [typedCode, setTypedCode] = useState('');
  const [error, setError] = useState('');
  const [loading, setLoading] = useState(true);
  const [submitting, setSubmitting] = useState(false);
  const [finishCountdown, setFinishCountdown] = useState<number | null>(null);

  const orderId = typeof params.orderId === 'string' ? params.orderId : '';
  const deliveryId = typeof params.deliveryId === 'string' ? params.deliveryId : '';
  const code = useMemo(() => (orderId ? validationCode(orderId) : '------'), [orderId]);
  const codeMatches = typedCode.trim().toUpperCase() === code;
  const deliveryFinished = finishCountdown !== null;
  const alreadyPickedUp =
    tracking?.delivery?.status === 'PICKED_UP' ||
    tracking?.delivery?.status === 'ON_THE_WAY' ||
    tracking?.delivery?.status === 'DELIVERED';

  const expireSession = (message = 'Sua sessao expirou. Entre novamente para continuar.') => {
    setOnline(false);
    clearSession();
    setError(message);
    router.replace('/' as never);
  };

  useEffect(() => {
    if (!orderId || !deliveryId) {
      setLoading(false);
      setError('Entrega ativa nao identificada.');
    }
  }, [deliveryId, orderId]);

  useEffect(() => {
    if (finishCountdown === null) {
      return;
    }

    if (finishCountdown <= 0) {
      router.replace('/' as never);
      return;
    }

    const timeoutId = setTimeout(() => {
      setFinishCountdown((current) => (current === null ? null : current - 1));
    }, 1000);

    return () => clearTimeout(timeoutId);
  }, [finishCountdown, router]);

  useEffect(() => {
    if (!accessToken || !orderId || deliveryFinished) {
      setLoading(false);
      return;
    }

    let active = true;

    const fetchTracking = async () => {
      try {
        const response = await axios.get<TrackingPayload>(`${API_URL}/tracking/order/${orderId}`, {
          headers: { Authorization: `Bearer ${accessToken}` },
        });
        if (!active) {
          return;
        }
        setTracking(response.data);
        setError('');
      } catch (loadError) {
        if (active && isUnauthorizedError(loadError)) {
          expireSession();
          return;
        }
        if (active) {
          setError(extractErrorMessage(loadError, 'Falha ao carregar a entrega ativa.'));
        }
      } finally {
        if (active) {
          setLoading(false);
        }
      }
    };

    void fetchTracking();
    const refreshId = setInterval(() => {
      void fetchTracking();
    }, 10000);

    return () => {
      active = false;
      clearInterval(refreshId);
    };
  }, [accessToken, orderId, deliveryFinished]);

  useEffect(() => {
    if (!accessToken || !deliveryId || deliveryFinished) {
      return;
    }

    let mounted = true;
    let subscription: Location.LocationSubscription | null = null;

    const startTracking = async () => {
      try {
        const permission = await Location.requestForegroundPermissionsAsync();
        if (permission.status !== 'granted' || !mounted) {
          return;
        }

        const current = await Location.getCurrentPositionAsync({
          accuracy: Location.Accuracy.Highest,
        });

        if (!mounted) {
          return;
        }

        await axios.patch(
          `${API_URL}/driver/deliveries/${deliveryId}/location`,
          {
            latitude: current.coords.latitude,
            longitude: current.coords.longitude,
            heading: current.coords.heading ?? undefined,
            speed: current.coords.speed ?? undefined,
            accuracy: current.coords.accuracy ?? undefined,
          },
          {
            headers: { Authorization: `Bearer ${accessToken}` },
          },
        );

        subscription = await Location.watchPositionAsync(
          {
            accuracy: Location.Accuracy.High,
            timeInterval: 15000,
            distanceInterval: 50,
          },
          (position) => {
            void axios.patch(
              `${API_URL}/driver/deliveries/${deliveryId}/location`,
              {
                latitude: position.coords.latitude,
                longitude: position.coords.longitude,
                heading: position.coords.heading ?? undefined,
                speed: position.coords.speed ?? undefined,
                accuracy: position.coords.accuracy ?? undefined,
              },
              {
                headers: { Authorization: `Bearer ${accessToken}` },
              },
            ).catch((requestError) => {
              if (isUnauthorizedError(requestError) && mounted) {
                expireSession();
              }
            });
          },
        );
      } catch (locationError) {
        if (mounted) {
          setError((currentError) => currentError || extractErrorMessage(locationError, 'Nao foi possivel usar a localizacao do celular.'));
        }
      }
    };

    void startTracking();

    return () => {
      mounted = false;
      subscription?.remove();
    };
  }, [accessToken, deliveryId, deliveryFinished]);

  const patchDelivery = async (path: 'pickup' | 'delivered') => {
    if (!accessToken || !deliveryId) {
      Alert.alert('Entrega indisponivel', 'Nao foi possivel identificar a corrida.');
      return;
    }

    setSubmitting(true);
    try {
      await axios.patch(
        `${API_URL}/driver/deliveries/${deliveryId}/${path}`,
        { confirmationCode: code },
        {
          headers: { Authorization: `Bearer ${accessToken}` },
        },
      );

      if (path === 'pickup') {
        setTracking((current) =>
          current
            ? {
                ...current,
                delivery: current.delivery ? { ...current.delivery, status: 'PICKED_UP' } : current.delivery,
              }
            : current,
        );
        await openDropoffMap({
          ...(tracking as TrackingPayload),
          delivery: tracking?.delivery ? { ...tracking.delivery, status: 'PICKED_UP' } : tracking?.delivery ?? null,
        });
      } else {
        setTracking((current) =>
          current
            ? {
                ...current,
                delivery: current.delivery ? { ...current.delivery, status: 'DELIVERED' } : current.delivery,
              }
            : current,
        );
        setError('');
        setFinishCountdown(3);
      }
      setTypedCode('');
    } catch (requestError) {
      if (isUnauthorizedError(requestError)) {
        expireSession();
        return;
      }
      Alert.alert('Falha', extractErrorMessage(requestError, 'Nao foi possivel concluir a acao.'));
    } finally {
      setSubmitting(false);
    }
  };

  const canStart = tracking?.delivery?.status === 'ACCEPTED';
  const canFinish = tracking?.delivery?.status === 'PICKED_UP' || tracking?.delivery?.status === 'ON_THE_WAY';

  return (
    <DriverShell
      eyebrow="Entrega ativa"
      title={tracking?.trackingStatusLabel ?? 'Aguardando atualizacao'}
      subtitle={
        alreadyPickedUp
          ? `Agora siga para a entrega final de ${tracking?.customer.name ?? '--'}.`
          : `Primeiro va ate ${tracking?.restaurant.name ?? '--'} para retirar o pedido.`
      }
      afterHero={
        finishCountdown !== null ? (
          <View style={styles.finishCard}>
            <Text style={styles.finishTitle}>Entrega concluida</Text>
            <Text style={styles.finishBody}>Voltando para o painel em {finishCountdown}s...</Text>
          </View>
        ) : undefined
      }
    >
      {error ? <View style={styles.warningCard}><Text style={styles.warningText}>{error}</Text></View> : null}

      <View style={styles.routeCard}>
        <Text style={styles.routeTitle}>Rota da corrida</Text>
        <Text style={styles.routePhase}>{alreadyPickedUp ? '2. Entregar ao cliente' : '1. Ir ate a loja'}</Text>
        <Text style={styles.routeLine}>Coleta: {tracking?.restaurant.addressLabel ?? 'Endereco da loja pendente'}</Text>
        <Text style={styles.routeLine}>Entrega: {tracking?.customer.addressLabel ?? 'Endereco do cliente pendente'}</Text>
        <View style={styles.routeStats}>
          <View style={styles.statPill}>
            <Text style={styles.statLabel}>Loja</Text>
            <Text style={styles.statValue}>{formatDistance(tracking?.route?.pickupDistanceKm)}</Text>
          </View>
          <View style={styles.statPill}>
            <Text style={styles.statLabel}>Cliente</Text>
            <Text style={styles.statValue}>{formatDistance(tracking?.route?.deliveryDistanceKm)}</Text>
          </View>
          <View style={styles.statPillWide}>
            <Text style={styles.statLabel}>Ganho</Text>
            <Text style={styles.statValue}>{formatCurrency(tracking?.delivery?.driverEarning)}</Text>
          </View>
        </View>
        <TouchableOpacity onPress={() => void (alreadyPickedUp ? openDropoffMap(tracking) : openPickupMap(tracking))} style={styles.mapButton}>
          <Text style={styles.mapButtonText}>{alreadyPickedUp ? 'Abrir rota para o cliente' : 'Abrir rota para a loja'}</Text>
        </TouchableOpacity>
      </View>

      <View style={styles.codeCard}>
        <Text style={styles.codeLabel}>{alreadyPickedUp ? 'Codigo do cliente' : 'Codigo da retirada'}</Text>
        <Text style={styles.codeValue}>{code}</Text>
        <Text style={styles.codeHint}>
          {alreadyPickedUp ? 'Confirme o codigo do cliente para encerrar a corrida.' : 'Use esse codigo na retirada para liberar a rota final.'}
        </Text>
      </View>

      <View style={styles.actionsCard}>
        <Text style={styles.sectionTitle}>Confirmacao da entrega</Text>
        <TextInput
          value={typedCode}
          onChangeText={setTypedCode}
          placeholder={alreadyPickedUp ? 'Digite o codigo do cliente' : 'Digite o codigo da retirada'}
          placeholderTextColor="#94A3B8"
          autoCapitalize="characters"
          style={styles.input}
        />

        <TouchableOpacity onPress={() => setTypedCode(code)} disabled={submitting} style={styles.quickCodeButton}>
          <Text style={styles.quickCodeButtonText}>Usar codigo automaticamente</Text>
        </TouchableOpacity>

        <TouchableOpacity
          onPress={() => {
            if (!codeMatches) {
              setTypedCode(code);
            }
            void patchDelivery('pickup');
          }}
          disabled={!canStart || submitting}
          style={[styles.actionButton, (!canStart || submitting) && styles.actionButtonDisabled]}
        >
          <Text style={styles.actionText}>{submitting ? 'Processando...' : 'Confirmar retirada e abrir rota do cliente'}</Text>
        </TouchableOpacity>

        <TouchableOpacity
          onPress={() => {
            if (!codeMatches) {
              setTypedCode(code);
            }
            void patchDelivery('delivered');
          }}
          disabled={!canFinish || submitting}
          style={[styles.actionButtonSecondary, (!canFinish || submitting) && styles.actionButtonDisabled]}
        >
          <Text style={styles.actionTextSecondary}>{submitting ? 'Processando...' : 'Confirmar entrega e finalizar corrida'}</Text>
        </TouchableOpacity>

        <Link href="/" style={styles.secondaryButton}>Voltar para corridas</Link>
      </View>

      {loading ? <Text style={styles.helperText}>Carregando entrega...</Text> : null}
    </DriverShell>
  );
}

const styles = StyleSheet.create({
  finishCard: {
    marginTop: 14,
    borderRadius: 18,
    padding: 14,
    backgroundColor: driverTheme.successSoft,
  },
  finishTitle: { fontSize: 16, fontWeight: '900', color: '#166534' },
  finishBody: { marginTop: 4, fontSize: 13, color: '#166534', fontWeight: '700' },
  warningCard: { borderRadius: 18, padding: 14, backgroundColor: driverTheme.warningSoft },
  warningText: { color: '#92400E', fontSize: 13, lineHeight: 19, fontWeight: '700' },
  routeCard: { borderRadius: 22, padding: 18, backgroundColor: driverTheme.card },
  routeTitle: { fontSize: 18, fontWeight: '900', color: driverTheme.textDark },
  routePhase: { marginTop: 6, fontSize: 11, fontWeight: '900', color: driverTheme.accentDark, textTransform: 'uppercase', letterSpacing: 1.3 },
  routeLine: { marginTop: 8, fontSize: 14, lineHeight: 21, color: '#334155' },
  routeStats: { marginTop: 14, flexDirection: 'row', gap: 8 },
  statPill: { flex: 1, borderRadius: 16, padding: 12, backgroundColor: '#F8FAFC' },
  statPillWide: { flex: 1.2, borderRadius: 16, padding: 12, backgroundColor: '#F8FAFC' },
  statLabel: { fontSize: 10, textTransform: 'uppercase', color: '#64748B', fontWeight: '900' },
  statValue: { marginTop: 6, fontSize: 15, color: driverTheme.textDark, fontWeight: '900' },
  mapButton: { marginTop: 14, borderRadius: 16, paddingHorizontal: 14, paddingVertical: 13, backgroundColor: '#DBEAFE' },
  mapButtonText: { textAlign: 'center', color: '#0F172A', fontWeight: '900' },
  codeCard: { borderRadius: 22, paddingHorizontal: 16, paddingVertical: 16, backgroundColor: driverTheme.successSoft, alignItems: 'center' },
  codeLabel: { fontSize: 11, fontWeight: '900', textTransform: 'uppercase', color: '#047857', letterSpacing: 1.1 },
  codeValue: { marginTop: 8, fontSize: 28, fontWeight: '900', letterSpacing: 5, color: '#064E3B' },
  codeHint: { marginTop: 8, fontSize: 12, color: '#047857', fontWeight: '700', textAlign: 'center' },
  actionsCard: { borderRadius: 22, padding: 18, backgroundColor: driverTheme.card, gap: 10 },
  sectionTitle: { fontSize: 18, fontWeight: '900', color: driverTheme.textDark },
  input: { borderRadius: 16, borderWidth: 1, borderColor: '#CBD5E1', backgroundColor: '#FFFFFF', paddingHorizontal: 16, paddingVertical: 14, fontSize: 15, color: '#0F172A' },
  quickCodeButton: { borderRadius: 16, paddingHorizontal: 14, paddingVertical: 12, backgroundColor: '#E2E8F0' },
  quickCodeButtonText: { textAlign: 'center', color: '#0F172A', fontWeight: '900' },
  actionButton: { borderRadius: 16, paddingHorizontal: 14, paddingVertical: 14, backgroundColor: driverTheme.accent },
  actionButtonSecondary: { borderRadius: 16, paddingHorizontal: 14, paddingVertical: 14, backgroundColor: '#0F766E' },
  actionButtonDisabled: { opacity: 0.4 },
  actionText: { color: '#FFFFFF', fontWeight: '900', textAlign: 'center' },
  actionTextSecondary: { color: '#FFFFFF', fontWeight: '900', textAlign: 'center' },
  secondaryButton: { marginTop: 4, borderRadius: 999, backgroundColor: '#E2E8F0', color: '#0F172A', textAlign: 'center', paddingHorizontal: 18, paddingVertical: 14, fontWeight: '800', overflow: 'hidden' },
  helperText: { textAlign: 'center', color: driverTheme.textMuted, fontSize: 13 },
});
