import { useCallback, useEffect, useRef, useState } from 'react';
import { AppState, Platform, ScrollView, View, Alert, ActivityIndicator } from 'react-native';
import { useRouter } from 'expo-router';
import { useBottomTabBarHeight } from 'react-native-bottom-tabs';
import { useTranslation } from 'react-i18next';
import { AppHeader } from '../../components/AppHeader';
import { LayerSwitchCard } from '../../components/blocker/LayerSwitchCard';
import { ProtectionLockedCard } from '../../components/blocker/ProtectionLockedCard';
import { CooldownBanner } from '../../components/blocker/CooldownBanner';
import { AddDomainSheet } from '../../components/blocker/AddDomainSheet';
import { VipSwapSheet } from '../../components/blocker/VipSwapSheet';
import { MyFiltersList, VipDomainList } from '../../components/blocker/VipDomainList';
import { ProtectionDetailsSheet } from '../../components/blocker/ProtectionDetailsSheet';
import { DeactivationExplainerSheet } from '../../components/blocker/DeactivationExplainerSheet';
import { PermissionDeniedSheet } from '../../components/PermissionDeniedSheet';
import { ProtectionOffSheet } from '../../components/ProtectionOffSheet';
import { IosUnsupervisedSetupFlow, AndroidSetupFlow } from '../../components/blocker/SetupFlows';
import { useProtectionState } from '../../hooks/useProtectionState';
import { useCustomDomains } from '../../hooks/useCustomDomains';
import { useBlocklistSync } from '../../hooks/useBlocklistSync';
import { useDomainSubmissionRealtime } from '../../hooks/useDomainSubmissionRealtime';
import { protection, FAMILY_CONTROLS_AVAILABLE } from '../../lib/protection';
import { useColors } from '../../lib/theme';
import { useBlockerStatsStore } from '../../stores/blockerStats';

export default function BlockerScreen() {
  const router = useRouter();
  const { t } = useTranslation();
  const colors = useColors();
  // react-native-bottom-tabs Tab-Bar ist iOS-nativ + translucent → unsere Content-View
  // erstreckt sich UNTER den Tab-Bar. Ohne diese Höhe würden FAB + Bottom-Padding
  // hinterm Tab-Bar verschwinden.
  const tabBarHeight = useBottomTabBarHeight();
  const {
    state,
    loading,
    cooldownRemainingFormatted,
    mdmManaged,
    refresh,
    activateUrlFilter,
    activateFamilyControls,
    requestDeactivation,
    cancelDeactivation,
  } = useProtectionState();
  const refreshBlockerStatsIfStale = useBlockerStatsStore((s) => s.refreshIfStale);
  const refreshBlockerStats = useBlockerStatsStore((s) => s.refresh);

  const plan = state?.plan ?? 'free';
  const {
    domains,
    tier,
    count: domainCount,
    limit: domainLimit,
    addDomain,
    submitDomain,
    submitVipSwap,
    refresh: refreshDomains,
  } = useCustomDomains(plan);
  const { sync: syncBlocklist, syncWebContent } = useBlocklistSync();

  // Realtime: Domain-Submission-Status (approved/rejected/in_review) live patchen.
  const onDomainChange = useCallback(async () => {
    await refreshDomains();
    await refreshBlockerStats().catch(() => {});
    if (urlFilterActiveRef.current) {
      const sync = await syncBlocklist();
      console.log('[blocker] resync after domain change:', sync);
      await refresh();
    }
  }, [refreshDomains, refreshBlockerStats, syncBlocklist, refresh]);
  useDomainSubmissionRealtime(onDomainChange, true);

  // Stats fürs Info-Sheet früh laden, damit beim Öffnen kein Loader-Flicker entsteht.
  useEffect(() => {
    refreshBlockerStatsIfStale(120_000).catch(() => {});
  }, [refreshBlockerStatsIfStale]);

  const [vipOpen, setVipOpen] = useState(false);
  const [addSheetOpen, setAddSheetOpen] = useState(false);
  const [vipSwapOpen, setVipSwapOpen] = useState(false);
  const [pendingNewDomainId, setPendingNewDomainId] = useState<string>('');

  const [detailsOpen, setDetailsOpen] = useState(false);
  const [explainerOpen, setExplainerOpen] = useState(false);
  const [permissionDeniedOpen, setPermissionDeniedOpen] = useState(false);
  const [familyControlsErrorOpen, setFamilyControlsErrorOpen] = useState(false);
  const [protectionOffOpen, setProtectionOffOpen] = useState(false);

  // Screen Time Passcode (iOS Layer 3)
  const [screentimeCode, setScreentimeCode] = useState<string | null>(null);
  const [screentimeConfirmed, setScreentimeConfirmed] = useState(false);
  const [screentimeSaving, setScreentimeSaving] = useState(false);
  // Load persisted screentime status on mount so the card stays hidden if already set
  useEffect(() => {
    if (Platform.OS !== 'ios') return;
    protection.getScreenTimePasscode().then((p) => {
      if (p) setScreentimeConfirmed(true);
    }).catch(() => {});
  }, []);

  const urlFilterActive = state?.layers.urlFilter === true;
  const familyControlsActive = state?.layers.familyControls === true;
  const appDeletionLockActive = (state?.layers.appDeletionLock ?? familyControlsActive) === true;
  const nefilterActive = state?.layers.nefilterActive === true;
  const deviceAdminActive = state?.layers.deviceAdmin === true;
  const batteryUnrestricted = state?.layers.batteryUnrestricted === true;
  // "lockedIn" = beide Layer aktiv: URL-Filter (echter Schutz) UND App-Lock
  // (Hardening). Family-Controls ALLEINE = kein Schutz, nur denyAppRemoval —
  // ohne URL-Filter sieht der User trotzdem Glücksspielseiten. Daher BEIDE
  // müssen an sein damit der "Schutz aktiv"-Banner gezeigt wird.
  // Ausnahmen:
  //  - !FAMILY_CONTROLS_AVAILABLE (Distribution-Build ohne FC-Entitlement) →
  //    es kann gar keinen App-Lock geben, URL-Filter allein reicht.
  //  - mdmManaged → der App-Lock wird MDM-seitig durch nicht-entfernbares
  //    Profile + non-removable App enforced, FC-Toggle ist irrelevant.
  // nefilterActive → Schutz via System-Profil, kein VPN-Toggle nötig → locked-in
  const lockedIn = Platform.OS === 'android'
    // Akku-Ausnahme MUSS dabei sein — ohne sie schläfert Samsung & Co. den
    // a11y-Service ein (Lock entbunden → Schutz fällt still aus). Sonst zeigt der
    // Banner „geschützt" + versteckt den (offenen) Akku-Step. Konsistent mit der
    // Onboarding-`allDone`.
    ? (urlFilterActive && appDeletionLockActive && deviceAdminActive && batteryUnrestricted)
    : (nefilterActive || urlFilterActive) && (mdmManaged || nefilterActive || appDeletionLockActive || !FAMILY_CONTROLS_AVAILABLE);

  const urlFilterActiveRef = useRef(urlFilterActive);
  useEffect(() => { urlFilterActiveRef.current = urlFilterActive; }, [urlFilterActive]);

  // Auto-Sync wenn URL-Filter oder NEFilter (MDM-Mode) beim Mount aktiv ist.
  // Im MDM-Mode läuft NEFilter via System-Profil — urlFilterActive ist false (kein VPN),
  // aber nefilterActive=true. Sync muss auch in diesem Fall laufen.
  const syncedOnceRef = useRef(false);
  useEffect(() => {
    if (!urlFilterActive && !nefilterActive) return;
    if (syncedOnceRef.current) return;
    syncedOnceRef.current = true;
    syncBlocklist().then((res) => {
      console.log('[blocker] auto-sync on mount:', res);
      if (res.ok) refresh();
    });
  }, [urlFilterActive, nefilterActive, syncBlocklist, refresh]);

  // Layer 2 / VIP: webContent-Domain-Liste IMMER beim Mount syncen — ungated,
  // da Layer 2 an Family Controls hängt, nicht am URL-Filter.
  const webContentSyncedRef = useRef(false);
  useEffect(() => {
    if (webContentSyncedRef.current) return;
    webContentSyncedRef.current = true;
    syncWebContent();
  }, [syncWebContent]);

  // Wenn User aus System-Settings zurückkommt (z.B. nach a11y-Aktivierung) → State neu laden.
  useEffect(() => {
    const sub = AppState.addEventListener('change', (next) => {
      if (next === 'active') {
        refresh();
        syncWebContent();
      }
    });
    return () => sub.remove();
  }, [refresh, syncWebContent]);

  // ─── Android Device-Admin ────────────────────────────────────────────

  async function handleRequestDeviceAdmin() {
    try {
      const result = await protection.requestDeviceAdmin();
      if (!result.launched) {
        Alert.alert(t('blocker.android_admin_failed_title'), t('blocker.android_admin_failed_msg'));
      } else {
        await refresh();
      }
      return result;
    } catch (e: any) {
      Alert.alert(t('blocker.activation_failed_title'), e?.message ?? t('common.unknown_error'));
      return { launched: false };
    }
  }

  // ─── Akku-Ausnahme (gegen Samsung-Sleep, der den a11y-Lock entbindet) ──

  async function handleRequestBattery() {
    // System-Dialog „Akku-Optimierung ignorieren?" (ein Tap). Der State zieht via
    // AppState-'active'-Refresh nach, wenn der User zurückkommt.
    return protection.requestIgnoreBatteryOptimizations();
  }
  async function handleOpenAppDetails() {
    // Samsung-Sonderweg: App-Detail → Akku „Uneingeschränkt" + raus aus
    // „Schlafende Apps" (deckt der AOSP-Whitelist-Dialog nicht ab).
    return protection.openAppDetailsSettings();
  }

  // ─── Activate-Handler pro Layer ──────────────────────────────────────

  async function handleActivateUrlFilter() {
    try {
      const result = await activateUrlFilter();
      console.log('[blocker] activateUrlFilter:', result);
      if (!result.enabled) {
        // iOS-spezifisch: NEFilterErrorDomain code 5 = User hat „Nicht erlauben"
        // im System-Dialog getippt → iOS cached den Denied-State. Special-Sheet
        // statt rohem Alert (Recovery via removeFromPreferences + Settings-Deep-Link).
        const isPermissionDenied =
          Platform.OS === 'ios' &&
          typeof result.error === 'string' &&
          /NEFilterErrorDomain:\s*5/i.test(result.error);
        if (isPermissionDenied) {
          setPermissionDeniedOpen(true);
          return result;
        }
        Alert.alert(
          t('blocker.activate_url_failed_title'),
          result.error ?? t('blocker.activate_url_failed_msg'),
          [
            { text: t('common.ok') },
            { text: t('blocker.activate_settings_btn'), onPress: () => protection.openSystemSettings() },
          ],
        );
      } else {
        const sync = await syncBlocklist();
        console.log('[blocker] post-activate sync:', sync);
        if (sync.ok) {
          await refresh();
        } else {
          Alert.alert(
            t('blocker.sync_list_failed_title'),
            sync.error ?? t('blocker.sync_list_failed_msg'),
          );
        }
      }
      return result;
    } catch (e: any) {
      console.error('[blocker] activateUrlFilter threw:', e);
      Alert.alert(t('blocker.activation_failed_title'), e?.message ?? t('common.unknown_error'));
      return { enabled: false };
    }
  }

  async function handleActivateFamilyControls() {
    try {
      const result = await activateFamilyControls();
      console.log('[blocker] activateFamilyControls:', result);
      // `accessibility_pending` = a11y-Berechtigung fehlt noch → System-Settings wurden
      // geöffnet. Kein Fehler-Modal (sonst Modal-Loop bei jedem Tap).
      if (!result.enabled && result.error !== 'accessibility_pending') {
        // iOS: NSCocoaErrorDomain code 4099 = XPC-Communication-Failure zum
        // FamilyControls-Daemon (häufig nach „Don't Allow" oder bei iOS-Auth-
        // Daemon-State-Issue). Recovery-Sheet statt rohem Alert — mit Anleitung
        // (Restart Device / Settings / App reinstall).
        const isXpcFailure =
          Platform.OS === 'ios' &&
          typeof result.error === 'string' &&
          /NSCocoaErrorDomain:\s*4099/i.test(result.error);
        if (isXpcFailure) {
          setFamilyControlsErrorOpen(true);
          return result;
        }
        Alert.alert(
          t('blocker.activate_app_lock_failed_title'),
          result.error ?? t('blocker.activate_app_lock_failed_msg'),
        );
      }
      return result;
    } catch (e: any) {
      console.error('[blocker] activateFamilyControls threw:', e);
      Alert.alert(t('blocker.activation_failed_title'), e?.message ?? t('common.unknown_error'));
    }
    return { enabled: false };
  }

  // ─── Screen Time Passcode (iOS Layer 3) ─────────────────────────────

  function handleGenerateScreentimeCode() {
    const code = Math.floor(1000 + Math.random() * 9000).toString();
    setScreentimeCode(code);
    setScreentimeConfirmed(false);
  }

  async function handleScreentimeConfirm() {
    if (!screentimeCode) return;
    setScreentimeSaving(true);
    try {
      await protection.saveScreenTimePasscode(screentimeCode);
      setScreentimeConfirmed(true);
      setScreentimeCode(null);
    } catch (e: any) {
      Alert.alert(t('common.error'), e?.message ?? t('common.unknown_error'));
    } finally {
      setScreentimeSaving(false);
    }
  }

  // ─── 3-Click Cooldown-Trigger ────────────────────────────────────────

  function openDetails() {
    setDetailsOpen(true);
  }

  function fromDetailsToExplainer() {
    setDetailsOpen(false);
    setTimeout(() => setExplainerOpen(true), 250);
  }

  function deflectToLyra() {
    setDetailsOpen(false);
    setTimeout(() => router.push('/lyra' as any), 250);
  }

  function deflectToBreathe() {
    setExplainerOpen(false);
    setTimeout(() => router.push('/urge' as any), 250);
  }

  async function handleStartCooldown(reason: string) {
    await requestDeactivation(reason);
  }

  async function handleCancelCooldown() {
    try {
      await cancelDeactivation();
    } catch (e: any) {
      Alert.alert(t('common.error'), e?.message ?? t('blocker.deactivation_cancel_failed'));
    }
  }

  const bypassAlertShownRef = useRef(false);
  useEffect(() => {
    if (state?.phase !== 'recoveringFromBypass') {
      bypassAlertShownRef.current = false;
      return;
    }
    if (bypassAlertShownRef.current) return;
    bypassAlertShownRef.current = true;
    setProtectionOffOpen(true);
  }, [state?.phase]);

  // ─── Render ──────────────────────────────────────────────────────────

  return (
    <View className="flex-1 bg-neutral-50">
      <AppHeader />

      {loading && !state ? (
        <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
          <ActivityIndicator size="large" color="#737373" />
        </View>
      ) : state ? (
        <>
          <ScrollView
            contentContainerStyle={{
              padding: 16,
              paddingBottom: tabBarHeight + 80,
              gap: 14,
            }}
            showsVerticalScrollIndicator={false}
          >
            {/* Locked-In Mode (FC / NEFilter aktiv) → NUR Schutz-Status + Cooldown-Pfad */}
            {lockedIn ? (
              <ProtectionLockedCard
                state={state}
                mdmManaged={mdmManaged}
                nefilterActive={nefilterActive}
                onPressSettings={openDetails}
              />
            ) : Platform.OS === 'ios' && FAMILY_CONTROLS_AVAILABLE && !mdmManaged && !nefilterActive ? (
              /* iOS unsupervised: geführter 3-Schritt-Setup-Flow */
              <IosUnsupervisedSetupFlow
                familyControlsActive={appDeletionLockActive}
                screentimeCode={screentimeCode}
                screentimeConfirmed={screentimeConfirmed}
                screentimeSaving={screentimeSaving}
                urlFilterActive={urlFilterActive}
                onActivateFamilyControls={handleActivateFamilyControls}
                onGenerateScreentimeCode={handleGenerateScreentimeCode}
                onConfirmScreentime={handleScreentimeConfirm}
                onActivateUrlFilter={handleActivateUrlFilter}
                colors={colors}
                t={t}
              />
            ) : Platform.OS === 'android' ? (
              <AndroidSetupFlow
                vpnActive={urlFilterActive}
                accessibilityLocked={appDeletionLockActive}
                deviceAdminActive={deviceAdminActive}
                batteryUnrestricted={batteryUnrestricted}
                onActivateVpn={handleActivateUrlFilter}
                onActivateAccessibility={handleActivateFamilyControls}
                onRequestDeviceAdmin={handleRequestDeviceAdmin}
                onRequestBattery={handleRequestBattery}
                onOpenAppDetails={handleOpenAppDetails}
                colors={colors}
                t={t}
              />
            ) : (
              <View style={{ gap: 10 }}>
                <LayerSwitchCard
                  icon="globe-outline"
                  title={t('blocker.layers_url_filter_title')}
                  subtitle={
                    urlFilterActive
                      ? t('blocker.layers_url_filter_subtitle_active')
                      : t('blocker.layers_url_filter_subtitle_inactive')
                  }
                  active={urlFilterActive}
                  onActivate={handleActivateUrlFilter}
                />
              </View>
            )}

            {/* CooldownBanner */}
            {state.cooldown.active && (
              <CooldownBanner
                remainingFormatted={cooldownRemainingFormatted}
                onCancel={handleCancelCooldown}
              />
            )}


            {/* Sektion 1: Meine Filter (unified web + mail_domain) */}
            <MyFiltersList
              domains={domains}
              tier={tier}
              totalCount={domainCount}
              totalLimit={domainLimit}
              globalBlocklistCount={state.blocklistCount}
              onAddPress={() => setAddSheetOpen(true)}
              onSubmitDomain={submitDomain}
              colors={colors}
            />

            {/* Sektion 2: VIP-Liste (Zweitschutz, collapsible) */}
            <VipDomainList
              domains={domains}
              open={vipOpen}
              onToggle={() => setVipOpen((v) => !v)}
              colors={colors}
            />
          </ScrollView>

          {/* Sheets */}
          <AddDomainSheet
            visible={addSheetOpen}
            tier={tier}
            onClose={() => {
              setAddSheetOpen(false);
              refreshDomains();
            }}
            onAdd={async (pattern, kind, opts) => {
              const result = await addDomain(pattern, kind, opts);
              if (result.ok) {
                syncWebContent();
                const sync = await syncBlocklist();
                if (sync.ok) refresh();
                if (result.vipFull && result.newDomainId) {
                  setAddSheetOpen(false);
                  setPendingNewDomainId(result.newDomainId);
                  // AddDomainSheet erst zu Ende dismissen lassen, DANN den
                  // VipSwapSheet präsentieren — sonst verschluckt iOS das
                  // zweite Modal (gleiches Muster wie fromDetailsToExplainer).
                  setTimeout(() => setVipSwapOpen(true), 320);
                }
              }
              return result;
            }}
          />

          <VipSwapSheet
            visible={vipSwapOpen}
            newDomainId={pendingNewDomainId}
            candidates={domains}
            onClose={() => {
              setVipSwapOpen(false);
              setPendingNewDomainId('');
            }}
            onSwap={async (newId, evictedId) => {
              const result = await submitVipSwap(newId, evictedId);
              if (result.ok) {
                syncWebContent();
              }
              return result;
            }}
          />

          <ProtectionDetailsSheet
            visible={detailsOpen}
            state={state}
            mdmManaged={mdmManaged}
            onClose={() => setDetailsOpen(false)}
            onRequestDeactivation={fromDetailsToExplainer}
            onTalkToLyra={deflectToLyra}
          />

          <DeactivationExplainerSheet
            visible={explainerOpen}
            onClose={() => setExplainerOpen(false)}
            onBreathe={deflectToBreathe}
            onStartCooldown={handleStartCooldown}
          />

          <PermissionDeniedSheet
            visible={permissionDeniedOpen}
            onClose={() => setPermissionDeniedOpen(false)}
            onRetry={async () => {
              const res = await protection.resetUrlFilter();
              if (res.enabled) {
                await refresh();
              }
              return res;
            }}
          />

          <PermissionDeniedSheet
            visible={familyControlsErrorOpen}
            onClose={() => setFamilyControlsErrorOpen(false)}
            variant="family_controls"
            onRetry={async () => {
              const res = await protection.activateFamilyControls();
              if (res.enabled) {
                await refresh();
              }
              return res;
            }}
          />

          <ProtectionOffSheet
            visible={protectionOffOpen}
            onClose={() => setProtectionOffOpen(false)}
            onReactivate={() => handleActivateUrlFilter()}
          />
        </>
      ) : null}
    </View>
  );
}
