/**
 * MapMap Nav design tokens.
 *
 * Source of truth: MAPMAP-NAV-UI-SPEC.md ▸ "Brand & global rules".
 * Signal colour #3A86FF (route line, CTAs, active states) always has white
 * text on it; ink #10182A is the primary text colour on light surfaces.
 * White cards/sheets, 12–16px radius, one soft shadow style, 4pt spacing,
 * ≥44pt touch targets, system font.
 *
 * Colours are keyed by ThemeName so a dark theme (spec: "stretch") can slot
 * in later without touching consumers — everything else (spacing, radius,
 * type scale, shadow shape) is theme-agnostic. Nothing in the app currently
 * switches themes (AppSettings has no themeMode field yet); `theme` below
 * is the static light default every primitive imports today.
 */
import { Platform, TextStyle, ViewStyle } from "react-native";

export type ThemeName = "light" | "dark";

/** 4pt base grid. */
export const spacing = {
  0: 0,
  1: 4,
  2: 8,
  3: 12,
  4: 16,
  5: 20,
  6: 24,
  8: 32,
  10: 40,
  12: 48,
} as const;

export type SpacingKey = keyof typeof spacing;

export const radius = {
  none: 0,
  sm: 8,
  md: 12,
  lg: 16,
  pill: 999,
} as const;

const palette = {
  signal: "#3A86FF",
  signalPressed: "#2E6FD9",
  signalMuted: "#B9D3FF",
  onSignal: "#FFFFFF",
  ink: "#10182A",
  white: "#FFFFFF",
  destructive: "#E5484D",
  destructivePressed: "#C93B40",
  onDestructive: "#FFFFFF",
} as const;

export type Theme = {
  name: ThemeName;
  background: string;
  surface: string;
  surfaceAlt: string;
  border: string;
  textPrimary: string;
  textSecondary: string;
  textOnSignal: string;
  signal: string;
  signalPressed: string;
  signalMuted: string;
  destructive: string;
  destructivePressed: string;
  onDestructive: string;
  /** The app's one shadow style — never use ad hoc shadows. */
  shadow: ViewStyle;
};

const softShadow: ViewStyle =
  Platform.OS === "android"
    ? { elevation: 4 }
    : {
        shadowColor: "#10182A",
        shadowOpacity: 0.12,
        shadowRadius: 12,
        shadowOffset: { width: 0, height: 4 },
      };

export const lightTheme: Theme = {
  name: "light",
  background: "#F4F6FA",
  surface: palette.white,
  surfaceAlt: "#EEF1F6",
  border: "#E1E5EC",
  textPrimary: palette.ink,
  textSecondary: "#5B6472",
  textOnSignal: palette.onSignal,
  signal: palette.signal,
  signalPressed: palette.signalPressed,
  signalMuted: palette.signalMuted,
  destructive: palette.destructive,
  destructivePressed: palette.destructivePressed,
  onDestructive: palette.onDestructive,
  shadow: softShadow,
};

/**
 * Stretch per the UI spec ("dark theme stretch (map style + surfaces
 * together)"). Not wired to anything yet — no screen reads it, no setting
 * selects it — but present so a future ThemeProvider only has to switch
 * `getTheme`'s argument, not invent values under deadline.
 */
export const darkTheme: Theme = {
  name: "dark",
  background: "#0B0F19",
  surface: "#151B2B",
  surfaceAlt: "#1D2436",
  border: "#2A3247",
  textPrimary: "#F4F6FA",
  textSecondary: "#A7B0C0",
  textOnSignal: palette.onSignal,
  signal: palette.signal,
  signalPressed: "#5C9CFF",
  signalMuted: "#254075",
  destructive: "#FF6B70",
  destructivePressed: palette.destructive,
  onDestructive: palette.onDestructive,
  shadow: { ...softShadow, shadowOpacity: 0.4 },
};

export function getTheme(name: ThemeName = "light"): Theme {
  return name === "dark" ? darkTheme : lightTheme;
}

/** Static default every primitive imports; see module doc above. */
export const theme = lightTheme;

type TypeStyle = Pick<TextStyle, "fontSize" | "lineHeight" | "fontWeight">;

export const typeScale: Record<
  "display" | "title" | "headline" | "body" | "label" | "caption",
  TypeStyle
> = {
  display: { fontSize: 34, lineHeight: 40, fontWeight: "700" },
  title: { fontSize: 24, lineHeight: 30, fontWeight: "700" },
  headline: { fontSize: 20, lineHeight: 26, fontWeight: "600" },
  body: { fontSize: 16, lineHeight: 22, fontWeight: "400" },
  label: { fontSize: 14, lineHeight: 18, fontWeight: "600" },
  caption: { fontSize: 12, lineHeight: 16, fontWeight: "400" },
};

/** Minimum touch target per the spec ("≥44pt touch targets"). */
export const minTouchTarget = 44;
