/**
 * Global toast system.
 * - ToastProvider mounts the animated host at the root.
 * - useToast() inside components: toast.show('…', 'success').
 * - showNetworkToast()/showToast() work OUTSIDE React (api client etc.) by
 *   pushing onto a simple event bus consumed by the provider.
 */
import React, {createContext, useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';
import {Animated, StyleSheet, Text, View} from 'react-native';
import {SafeAreaView} from 'react-native-safe-area-context';
import {COLORS} from '../theme/colors';
import {RADIUS, SPACING} from '../theme/spacing';

export type ToastType = 'info' | 'success' | 'error';

type ToastItem = {id: number; message: string; type: ToastType};

type ToastContextValue = {
  show: (message: string, type?: ToastType) => void;
};

const ToastContext = createContext<ToastContextValue>({show: () => undefined});

// ---- event bus for non-React callers -------------------------------------
type Listener = (message: string, type: ToastType) => void;
const listeners = new Set<Listener>();

export function showToast(message: string, type: ToastType = 'info'): void {
  listeners.forEach(fn => fn(message, type));
}
export function showNetworkToast(message: string): void {
  showToast(message, 'error');
}
// ---------------------------------------------------------------------------

const TYPE_COLOR: Record<ToastType, string> = {
  info: COLORS.purple,
  success: COLORS.success,
  error: COLORS.danger,
};

let toastId = 0;

export function ToastProvider({children}: {children: React.ReactNode}) {
  const [item, setItem] = useState<ToastItem | null>(null);
  const anim = useRef(new Animated.Value(0)).current;
  const hideTimer = useRef<ReturnType<typeof setTimeout> | null>(null);

  const show = useCallback((message: string, type: ToastType = 'info') => {
    if (hideTimer.current) clearTimeout(hideTimer.current);
    setItem({id: ++toastId, message, type});
    Animated.sequence([
      Animated.timing(anim, {toValue: 1, duration: 180, useNativeDriver: true}),
    ]).start();
    hideTimer.current = setTimeout(() => {
      Animated.timing(anim, {toValue: 0, duration: 220, useNativeDriver: true}).start(() =>
        setItem(null),
      );
    }, 2600);
  }, [anim]);

  useEffect(() => {
    const fn: Listener = (message, type) => show(message, type);
    listeners.add(fn);
    return () => {
      listeners.delete(fn);
    };
  }, [show]);

  const value = useMemo(() => ({show}), [show]);

  return (
    <ToastContext.Provider value={value}>
      {children}
      {item && (
        <Animated.View
          pointerEvents="none"
          style={[
            styles.wrap,
            {
              opacity: anim,
              transform: [
                {
                  translateY: anim.interpolate({
                    inputRange: [0, 1],
                    outputRange: [-24, 0],
                  }),
                },
              ],
            },
          ]}>
          <SafeAreaView edges={['top']} style={styles.safe}>
            <View style={[styles.bar, {backgroundColor: TYPE_COLOR[item.type]}]}>
              <Text style={styles.text} numberOfLines={3}>
                {item.message}
              </Text>
            </View>
          </SafeAreaView>
        </Animated.View>
      )}
    </ToastContext.Provider>
  );
}

export function useToast(): ToastContextValue {
  return useContext(ToastContext);
}

const styles = StyleSheet.create({
  wrap: {position: 'absolute', top: 0, left: 0, right: 0, zIndex: 9999, elevation: 9999},
  safe: {paddingHorizontal: SPACING.l},
  bar: {
    borderRadius: RADIUS.m,
    paddingVertical: SPACING.m,
    paddingHorizontal: SPACING.l,
    marginTop: SPACING.s,
  },
  text: {color: COLORS.white, fontWeight: '600', fontSize: 14, textAlign: 'center'},
});
