import { useCallback, useEffect, useRef, useState } from 'react';
import { Alert, AppState, Platform, type AppStateStatus } from 'react-native';
import { useTranslation } from 'react-i18next';
import {
  protection,
  type ProtectionState,
  type ProtectionPhase,
  formatCooldownRemaining,
} from '../lib/protection';

const POLL_MS_ACTIVE_COOLDOWN = 5_000;
const POLL_MS_NORMAL = 30_000;

type UseProtectionStateReturn = {
  state: ProtectionState | null;
  loading: boolean;
  error: string | null;
  /** Live Countdown-String "23:59:42" während Cooldown läuft. */
  cooldownRemainingFormatted: string;
  /** Refetch ohne loading-flicker. */
  refresh: () => Promise<void>;
  /** Aktiviert ALLE Layers (legacy, beide Dialoge nacheinander). */
  activate: () => Promise<{ allLayersOn: boolean; missingLayers: string[] }>;
  /** Aktiviert NUR den URL-Filter (NEFilter). */
  activateUrlFilter: () => Promise<{ enabled: boolean; error?: string }>;
  /** Aktiviert NUR Family Controls (= der Lock — danach nur per Cooldown abschaltbar). */
  activateFamilyControls: () => Promise<{ enabled: boolean; error?: string }>;
  /** Startet 24h Cooldown via Backend. UI muss Friction-Flow vorher durchlaufen. */
  requestDeactivation: (reason?: string) => Promise<void>;
  /** Bricht laufenden Cooldown ab. Schutz bleibt aktiv. */
  cancelDeactivation: () => Promise<void>;
};

/**
 * Single-Source-of-Truth-Hook für Protection-State.
 *
 *  - Initial-Fetch on mount
 *  - Polling: alle 30s normal, 5s während aktivem Cooldown (Live-Countdown)
 *  - Refresh on AppState 'active' (User kommt aus Background zurück)
 *  - Layer-Change-Listener vom Native-Modul (Bypass-Detection)
 */
export function useProtectionState(): UseProtectionStateReturn {
  const { t } = useTranslation();
  const [state, setState] = useState<ProtectionState | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [tickSeconds, setTickSeconds] = useState<number>(0);

  const pollTimer = useRef<ReturnType<typeof setInterval> | null>(null);
  const tickTimer = useRef<ReturnType<typeof setInterval> | null>(null);
  const prevCooldownActiveRef = useRef<boolean | null>(null);
  // Verhindert Mehrfach-Alert wenn fetchState + AppState-Listener beide kurz
  // hintereinander applyCooldownDisableIfElapsed → true sehen.
  const cooldownDisabledNoticeShownRef = useRef(false);

  // Freundlicher Hinweis nachdem der Cooldown abgelaufen ist und der Schutz
  // abgeschaltet wurde.
  //   Android: a11y-Service (Bedienungshilfe) kann sich nicht selbst
  //            deaktivieren → User braucht Settings-Deeplink.
  //   iOS:     NEFilter + Family Controls werden von forceDisable() vollständig
  //            abgeschaltet — User muss NICHTS in den Einstellungen tun.
  //            Kein "Bedienungshilfe"-Text (gibt es auf iOS nicht), kein
  //            Settings-Button.
  const showCooldownElapsedNotice = useCallback(() => {
    if (cooldownDisabledNoticeShownRef.current) return;
    cooldownDisabledNoticeShownRef.current = true;
    if (Platform.OS === 'android') {
      Alert.alert(
        t('blocker.cooldown_elapsed_title'),
        t('blocker.cooldown_elapsed_message'),
        [
          { text: t('common.ok'), style: 'cancel' },
          {
            text: t('blocker.cooldown_elapsed_open_settings'),
            onPress: () => {
              protection.openSystemSettings('accessibility').catch(() => {});
            },
          },
        ],
      );
    } else {
      Alert.alert(
        t('blocker.cooldown_elapsed_title'),
        t('blocker.cooldown_elapsed_message_ios'),
        [{ text: t('common.ok'), style: 'cancel' }],
      );
    }
  }, [t]);

  const fetchState = useCallback(async (showLoading = false) => {
    if (showLoading) setLoading(true);
    try {
      const next = await protection.getCombinedState();
      const prevActive = prevCooldownActiveRef.current;
      prevCooldownActiveRef.current = next.cooldown.active;

      // Cooldown ist gerade von active → inactive gekippt: Auto-Disable.
      // Wir nutzen LOKAL den Cooldown-State aus dem eben gefetchten `next` —
      // KEIN redundanter API-Call zu /api/cooldown/status. Grund: der Backend-
      // GET resolved den Cooldown autom. beim ersten expired-Hit. Ein zweiter
      // Call würde dann cooldownEndsAt=null returnen → false bail → Filter
      // bleibt installiert. Local-state-check ist atomar + race-frei.
      if (
        prevActive === true &&
        !next.cooldown.active &&
        next.cooldown.endsAt !== null
      ) {
        await protection.forceDisable();
        showCooldownElapsedNotice();
        // Nativer State hat sich geändert → ein weiterer Fetch für konsistenten State.
        const afterDisable = await protection.getCombinedState();
        setState(afterDisable);
        setTickSeconds(afterDisable.cooldown.remainingSeconds);
        setError(null);
        return;
      }

      setState(next);
      setTickSeconds(next.cooldown.remainingSeconds);
      setError(null);
    } catch (e: any) {
      setError(e?.message ?? 'unknown');
    } finally {
      if (showLoading) setLoading(false);
    }
  }, [showCooldownElapsedNotice]);

  // Initial fetch
  useEffect(() => {
    fetchState(true);
  }, [fetchState]);

  // Adaptive poll-rate: 5s während Cooldown, 30s sonst
  useEffect(() => {
    const interval = state?.cooldown.active ? POLL_MS_ACTIVE_COOLDOWN : POLL_MS_NORMAL;
    if (pollTimer.current) clearInterval(pollTimer.current);
    pollTimer.current = setInterval(() => fetchState(false), interval);
    return () => {
      if (pollTimer.current) clearInterval(pollTimer.current);
    };
  }, [state?.cooldown.active, fetchState]);

  // Live-Countdown-Tick (nur während Cooldown — 1s-Decrement client-side)
  useEffect(() => {
    if (!state?.cooldown.active) {
      if (tickTimer.current) {
        clearInterval(tickTimer.current);
        tickTimer.current = null;
      }
      return;
    }
    tickTimer.current = setInterval(() => {
      setTickSeconds((s) => Math.max(0, s - 1));
    }, 1000);
    return () => {
      if (tickTimer.current) clearInterval(tickTimer.current);
    };
  }, [state?.cooldown.active]);

  // AppState-Listener: Refresh + Auto-Disable wenn Cooldown elapsed während
  // App backgrounded war. applyCooldownDisableIfElapsed macht hier den initialen
  // API-Call (= keine Race-Condition mit anderem GET, weil das der erste post-
  // background Call ist). fetchState danach räumt den State auf — der neue
  // Guard im fetchState (`next.cooldown.endsAt !== null`) verhindert ein
  // doppeltes forceDisable wenn der AppState-Listener schon disabled hat.
  useEffect(() => {
    const sub = AppState.addEventListener('change', async (status: AppStateStatus) => {
      if (status !== 'active') return;
      const didDisable = await protection.applyCooldownDisableIfElapsed();
      if (didDisable) showCooldownElapsedNotice();
      await fetchState(false);
    });
    return () => sub.remove();
  }, [fetchState, showCooldownElapsedNotice]);

  // Native Layer-Change-Listener (User schaltet VPN extern aus etc.)
  useEffect(() => {
    const sub = protection.addLayerChangeListener(() => fetchState(false));
    return () => sub?.remove();
  }, [fetchState]);

  // ─── Public Actions ────────────────────────────────────────────────

  const activate = useCallback(async () => {
    const result = await protection.activate();
    await fetchState(false);
    return result;
  }, [fetchState]);

  const activateUrlFilter = useCallback(async () => {
    const result = await protection.activateUrlFilter();
    await fetchState(false);
    return result;
  }, [fetchState]);

  const activateFamilyControls = useCallback(async () => {
    const result = await protection.activateFamilyControls();
    await fetchState(false);
    return result;
  }, [fetchState]);

  const requestDeactivation = useCallback(
    async (reason?: string) => {
      await protection.requestDeactivation(reason);
      await fetchState(false);
    },
    [fetchState],
  );

  const cancelDeactivation = useCallback(async () => {
    await protection.cancelDeactivation();
    await fetchState(false);
  }, [fetchState]);

  return {
    state,
    loading,
    error,
    cooldownRemainingFormatted: formatCooldownRemaining(tickSeconds),
    refresh: () => fetchState(false),
    activate,
    activateUrlFilter,
    activateFamilyControls,
    requestDeactivation,
    cancelDeactivation,
  };
}

export type { ProtectionPhase };
