/**
 * S2c. Onboarding — Territory setup — MAPMAP-NAV-UI-SPEC.md.
 *
 * Pick a region (UK preselected; list from the territory index with flag,
 * name, size in GB). Download with real progress (MiB / %), then verify →
 * activate states shown ("Checking signature…"). Failure = retry card, not
 * a dead end.
 */
import React, { useEffect, useRef, useState } from "react";
import { ActivityIndicator, ScrollView, StyleSheet, Text, View } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { Button, Card, ProgressBar } from "../../components";
import { radius, spacing, theme, typeScale } from "../../theme";
import type {
  BridgeError,
  TerritoryPhase,
  TerritorySummary,
} from "../../state/types";

export type OnboardingTerritoryInstallState = {
  territoryId: string;
  phase: TerritoryPhase;
  bytesDone: number;
  bytesTotal: number;
  error?: BridgeError;
};

export type OnboardingTerritoryScreenProps = {
  territories: TerritorySummary[];
  /** "uk" preselected per spec. */
  recommendedTerritoryId?: string;
  installState: OnboardingTerritoryInstallState | null;
  onInstall: (territoryId: string) => void;
  onRetry: (territoryId: string) => void;
  /** Fires once a territory is active — advances the onboarding gate. */
  onDone: () => void;
};

const FLAG_BY_TERRITORY: Record<string, string> = {
  uk: "🇬🇧",
  ireland: "🇮🇪",
};

function territoryFlag(territoryId: string): string {
  return FLAG_BY_TERRITORY[territoryId] ?? "🌍";
}

function formatGB(sizeBytes: number): string {
  return `${(sizeBytes / 1_000_000_000).toFixed(1)} GB`;
}

function formatMiB(bytes: number): string {
  return `${(bytes / (1024 * 1024)).toFixed(1)} MiB`;
}

function phaseLabel(phase: TerritoryPhase): string {
  switch (phase) {
    case "downloading":
      return "Downloading…";
    case "verifying":
      return "Checking signature…";
    case "activating":
      return "Activating…";
    case "done":
      return "Ready";
    case "failed":
      return "Couldn't download";
  }
}

export function OnboardingTerritoryScreen({
  territories,
  recommendedTerritoryId,
  installState,
  onInstall,
  onRetry,
  onDone,
}: OnboardingTerritoryScreenProps): React.JSX.Element {
  const insets = useSafeAreaInsets();
  const [selectedId, setSelectedId] = useState<string | null>(null);
  const doneFiredForRef = useRef<string | null>(null);

  useEffect(() => {
    if (selectedId !== null || territories.length === 0) return;
    const preferred =
      recommendedTerritoryId &&
      territories.some((t) => t.id === recommendedTerritoryId)
        ? recommendedTerritoryId
        : territories[0].id;
    setSelectedId(preferred);
  }, [territories, recommendedTerritoryId, selectedId]);

  useEffect(() => {
    if (
      installState?.phase === "done" &&
      doneFiredForRef.current !== installState.territoryId
    ) {
      doneFiredForRef.current = installState.territoryId;
      onDone();
    }
  }, [installState, onDone]);

  const isInstalling = installState !== null && installState.phase !== "failed";
  const installingTerritory = installState
    ? territories.find((t) => t.id === installState.territoryId)
    : undefined;

  return (
    <View style={[styles.container, { paddingTop: insets.top }]} testID="onboarding-territory">
      <View style={styles.headerBlock}>
        <Text style={styles.title}>Choose your territory</Text>
        <Text style={styles.subtitle}>
          Download offline maps to search and navigate without a connection.
        </Text>
      </View>

      <ScrollView
        style={styles.list}
        contentContainerStyle={styles.listContent}
        showsVerticalScrollIndicator={false}
      >
        {territories.map((territory) => {
          const selected = territory.id === selectedId;
          return (
            <Card
              key={territory.id}
              padded={false}
              onPress={isInstalling ? undefined : () => setSelectedId(territory.id)}
              style={[
                styles.territoryCard,
                selected && styles.territoryCardSelected,
                isInstalling && !selected && styles.territoryCardDimmed,
              ]}
              testID={`territory-row-${territory.id}`}
            >
              <View style={styles.territoryRow}>
                <Text style={styles.flag}>{territoryFlag(territory.id)}</Text>
                <View style={styles.territoryText}>
                  <Text style={styles.territoryName}>{territory.name}</Text>
                  <Text style={styles.territorySize}>{formatGB(territory.sizeBytes)}</Text>
                </View>
                <View style={[styles.radio, selected && styles.radioSelected]}>
                  {selected && <View style={styles.radioDot} />}
                </View>
              </View>
            </Card>
          );
        })}
        {territories.length === 0 && (
          <Text style={styles.loadingText}>Loading territories…</Text>
        )}
      </ScrollView>

      <View style={[styles.footer, { paddingBottom: insets.bottom + spacing[6] }]}>
        {installState === null ? (
          <Button
            label="Download and continue"
            variant="primary"
            fullWidth
            disabled={!selectedId}
            onPress={() => selectedId && onInstall(selectedId)}
          />
        ) : installState.phase === "failed" ? (
          <Card style={styles.progressCard}>
            <Text style={styles.progressTitle}>
              Couldn&apos;t download {installingTerritory?.name ?? "this territory"}
            </Text>
            <Text style={styles.progressSubtitle}>
              {installState.error?.message ??
                "Something went wrong. Check your connection and try again."}
            </Text>
            <Button
              label="Retry"
              variant="primary"
              fullWidth
              onPress={() => onRetry(installState.territoryId)}
              style={styles.retryButton}
            />
          </Card>
        ) : (
          <Card style={styles.progressCard}>
            <View style={styles.progressHeader}>
              <Text style={styles.flag}>{territoryFlag(installState.territoryId)}</Text>
              <Text style={styles.progressTitle}>
                {installingTerritory?.name ?? installState.territoryId.toUpperCase()}
              </Text>
            </View>
            <Text style={styles.progressSubtitle}>{phaseLabel(installState.phase)}</Text>
            {installState.phase === "downloading" ? (
              <>
                <ProgressBar
                  progress={
                    installState.bytesTotal > 0
                      ? installState.bytesDone / installState.bytesTotal
                      : 0
                  }
                  tone="signal"
                />
                <Text style={styles.progressDetail}>
                  {formatMiB(installState.bytesDone)} / {formatMiB(installState.bytesTotal)}
                  {installState.bytesTotal > 0
                    ? ` · ${Math.round(
                        (installState.bytesDone / installState.bytesTotal) * 100
                      )}%`
                    : ""}
                </Text>
              </>
            ) : installState.phase !== "done" ? (
              <ActivityIndicator color={theme.signal} style={styles.spinner} />
            ) : null}
          </Card>
        )}
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: theme.background,
  },
  headerBlock: {
    paddingHorizontal: spacing[6],
    paddingTop: spacing[6],
  },
  title: {
    fontSize: typeScale.title.fontSize,
    lineHeight: typeScale.title.lineHeight,
    fontWeight: typeScale.title.fontWeight,
    color: theme.textPrimary,
  },
  subtitle: {
    marginTop: spacing[2],
    fontSize: typeScale.body.fontSize,
    lineHeight: typeScale.body.lineHeight,
    color: theme.textSecondary,
  },
  list: {
    flex: 1,
    marginTop: spacing[5],
  },
  listContent: {
    paddingHorizontal: spacing[6],
    paddingBottom: spacing[4],
    gap: spacing[3],
  },
  loadingText: {
    fontSize: typeScale.body.fontSize,
    color: theme.textSecondary,
    textAlign: "center",
    marginTop: spacing[6],
  },
  territoryCard: {
    borderWidth: 1,
    borderColor: theme.border,
  },
  territoryCardSelected: {
    borderColor: theme.signal,
  },
  territoryCardDimmed: {
    opacity: 0.5,
  },
  territoryRow: {
    flexDirection: "row",
    alignItems: "center",
    padding: spacing[4],
    gap: spacing[3],
  },
  flag: {
    fontSize: 28,
  },
  territoryText: {
    flex: 1,
  },
  territoryName: {
    fontSize: typeScale.body.fontSize,
    fontWeight: "600",
    color: theme.textPrimary,
  },
  territorySize: {
    marginTop: 2,
    fontSize: typeScale.caption.fontSize,
    color: theme.textSecondary,
  },
  radio: {
    width: 22,
    height: 22,
    borderRadius: radius.pill,
    borderWidth: 2,
    borderColor: theme.border,
    alignItems: "center",
    justifyContent: "center",
  },
  radioSelected: {
    borderColor: theme.signal,
  },
  radioDot: {
    width: 12,
    height: 12,
    borderRadius: radius.pill,
    backgroundColor: theme.signal,
  },
  footer: {
    paddingHorizontal: spacing[6],
    paddingTop: spacing[3],
  },
  progressCard: {
    gap: spacing[2],
  },
  progressHeader: {
    flexDirection: "row",
    alignItems: "center",
    gap: spacing[2],
  },
  progressTitle: {
    fontSize: typeScale.headline.fontSize,
    fontWeight: typeScale.headline.fontWeight,
    color: theme.textPrimary,
  },
  progressSubtitle: {
    fontSize: typeScale.body.fontSize,
    color: theme.textSecondary,
  },
  progressDetail: {
    fontSize: typeScale.caption.fontSize,
    color: theme.textSecondary,
  },
  spinner: {
    marginTop: spacing[1],
    alignSelf: "flex-start",
  },
  retryButton: {
    marginTop: spacing[2],
  },
});
