import { type AnimationLevel } from '../../utils/animationLevel'
import { type TrackColorPreset, type TrackDisplayMode, type TrackStyleProfile, type TrackTailLengthPreset } from '../presentation/trackStyleConfig'
import { type GpsMarkerColorPreset, type GpsMarkerSizePreset, type GpsMarkerStyleId } from '../presentation/gpsMarkerStyleConfig'

export type SideButtonPlacement = 'left' | 'right'
export type CenterScaleRulerAnchorMode = 'screen-center' | 'compass-center'
export type UserNorthReferenceMode = 'magnetic' | 'true'
export type CompassTuningProfile = 'smooth' | 'balanced' | 'responsive'

export type SettingLockKey =
  | 'lockAnimationLevel'
  | 'lockTrackMode'
  | 'lockTrackTailLength'
  | 'lockTrackColor'
  | 'lockTrackStyle'
  | 'lockGpsMarkerVisible'
  | 'lockGpsMarkerStyle'
  | 'lockGpsMarkerSize'
  | 'lockGpsMarkerColor'
  | 'lockSideButtonPlacement'
  | 'lockAutoRotate'
  | 'lockCompassTuning'
  | 'lockScaleRulerVisible'
  | 'lockScaleRulerAnchor'
  | 'lockNorthReference'
  | 'lockHeartRateDevice'

export type StoredUserSettings = {
  animationLevel?: AnimationLevel
  trackDisplayMode?: TrackDisplayMode
  trackTailLength?: TrackTailLengthPreset
  trackColorPreset?: TrackColorPreset
  trackStyleProfile?: TrackStyleProfile
  gpsMarkerVisible?: boolean
  gpsMarkerStyle?: GpsMarkerStyleId
  gpsMarkerSize?: GpsMarkerSizePreset
  gpsMarkerColorPreset?: GpsMarkerColorPreset
  autoRotateEnabled?: boolean
  compassTuningProfile?: CompassTuningProfile
  northReferenceMode?: UserNorthReferenceMode
  sideButtonPlacement?: SideButtonPlacement
  showCenterScaleRuler?: boolean
  centerScaleRulerAnchorMode?: CenterScaleRulerAnchorMode
}

export interface SystemSettingsConfig {
  values: Partial<StoredUserSettings>
  locks: Partial<Record<SettingLockKey, boolean>>
}

export type ResolvedSystemSettingsState = {
  values: Required<StoredUserSettings>
  locks: Record<SettingLockKey, boolean>
}

export const USER_SETTINGS_STORAGE_KEY = 'cmr_user_settings_v1'

export const DEFAULT_STORED_USER_SETTINGS: Required<StoredUserSettings> = {
  animationLevel: 'standard',
  trackDisplayMode: 'full',
  trackTailLength: 'medium',
  trackColorPreset: 'mint',
  trackStyleProfile: 'neon',
  gpsMarkerVisible: true,
  gpsMarkerStyle: 'beacon',
  gpsMarkerSize: 'medium',
  gpsMarkerColorPreset: 'cyan',
  autoRotateEnabled: true,
  compassTuningProfile: 'balanced',
  northReferenceMode: 'magnetic',
  sideButtonPlacement: 'left',
  showCenterScaleRuler: false,
  centerScaleRulerAnchorMode: 'screen-center',
}

export const DEFAULT_SETTING_LOCKS: Record<SettingLockKey, boolean> = {
  lockAnimationLevel: false,
  lockTrackMode: false,
  lockTrackTailLength: false,
  lockTrackColor: false,
  lockTrackStyle: false,
  lockGpsMarkerVisible: false,
  lockGpsMarkerStyle: false,
  lockGpsMarkerSize: false,
  lockGpsMarkerColor: false,
  lockSideButtonPlacement: false,
  lockAutoRotate: false,
  lockCompassTuning: false,
  lockScaleRulerVisible: false,
  lockScaleRulerAnchor: false,
  lockNorthReference: false,
  lockHeartRateDevice: false,
}

export const SETTING_LOCK_VALUE_MAP: Record<SettingLockKey, keyof StoredUserSettings | null> = {
  lockAnimationLevel: 'animationLevel',
  lockTrackMode: 'trackDisplayMode',
  lockTrackTailLength: 'trackTailLength',
  lockTrackColor: 'trackColorPreset',
  lockTrackStyle: 'trackStyleProfile',
  lockGpsMarkerVisible: 'gpsMarkerVisible',
  lockGpsMarkerStyle: 'gpsMarkerStyle',
  lockGpsMarkerSize: 'gpsMarkerSize',
  lockGpsMarkerColor: 'gpsMarkerColorPreset',
  lockSideButtonPlacement: 'sideButtonPlacement',
  lockAutoRotate: 'autoRotateEnabled',
  lockCompassTuning: 'compassTuningProfile',
  lockScaleRulerVisible: 'showCenterScaleRuler',
  lockScaleRulerAnchor: 'centerScaleRulerAnchorMode',
  lockNorthReference: 'northReferenceMode',
  lockHeartRateDevice: null,
}

function normalizeStoredUserSettings(raw: unknown): StoredUserSettings {
  if (!raw || typeof raw !== 'object') {
    return {}
  }

  const normalized = raw as Record<string, unknown>
  const settings: StoredUserSettings = {}
  if (normalized.animationLevel === 'standard' || normalized.animationLevel === 'lite') {
    settings.animationLevel = normalized.animationLevel
  }
  if (normalized.trackDisplayMode === 'none' || normalized.trackDisplayMode === 'full' || normalized.trackDisplayMode === 'tail') {
    settings.trackDisplayMode = normalized.trackDisplayMode
  }
  if (normalized.trackTailLength === 'short' || normalized.trackTailLength === 'medium' || normalized.trackTailLength === 'long') {
    settings.trackTailLength = normalized.trackTailLength
  }
  if (normalized.trackStyleProfile === 'classic' || normalized.trackStyleProfile === 'neon') {
    settings.trackStyleProfile = normalized.trackStyleProfile
  }
  if (typeof normalized.gpsMarkerVisible === 'boolean') {
    settings.gpsMarkerVisible = normalized.gpsMarkerVisible
  }
  if (
    normalized.gpsMarkerStyle === 'dot'
    || normalized.gpsMarkerStyle === 'beacon'
    || normalized.gpsMarkerStyle === 'disc'
    || normalized.gpsMarkerStyle === 'badge'
  ) {
    settings.gpsMarkerStyle = normalized.gpsMarkerStyle
  }
  if (normalized.gpsMarkerSize === 'small' || normalized.gpsMarkerSize === 'medium' || normalized.gpsMarkerSize === 'large') {
    settings.gpsMarkerSize = normalized.gpsMarkerSize
  }
  if (
    normalized.gpsMarkerColorPreset === 'mint'
    || normalized.gpsMarkerColorPreset === 'cyan'
    || normalized.gpsMarkerColorPreset === 'sky'
    || normalized.gpsMarkerColorPreset === 'blue'
    || normalized.gpsMarkerColorPreset === 'violet'
    || normalized.gpsMarkerColorPreset === 'pink'
    || normalized.gpsMarkerColorPreset === 'orange'
    || normalized.gpsMarkerColorPreset === 'yellow'
  ) {
    settings.gpsMarkerColorPreset = normalized.gpsMarkerColorPreset
  }
  if (
    normalized.trackColorPreset === 'mint'
    || normalized.trackColorPreset === 'cyan'
    || normalized.trackColorPreset === 'sky'
    || normalized.trackColorPreset === 'blue'
    || normalized.trackColorPreset === 'violet'
    || normalized.trackColorPreset === 'pink'
    || normalized.trackColorPreset === 'orange'
    || normalized.trackColorPreset === 'yellow'
  ) {
    settings.trackColorPreset = normalized.trackColorPreset
  }
  if (normalized.northReferenceMode === 'magnetic' || normalized.northReferenceMode === 'true') {
    settings.northReferenceMode = normalized.northReferenceMode
  }
  if (typeof normalized.autoRotateEnabled === 'boolean') {
    settings.autoRotateEnabled = normalized.autoRotateEnabled
  }
  if (normalized.compassTuningProfile === 'smooth' || normalized.compassTuningProfile === 'balanced' || normalized.compassTuningProfile === 'responsive') {
    settings.compassTuningProfile = normalized.compassTuningProfile
  }
  if (normalized.sideButtonPlacement === 'left' || normalized.sideButtonPlacement === 'right') {
    settings.sideButtonPlacement = normalized.sideButtonPlacement
  }
  if (typeof normalized.showCenterScaleRuler === 'boolean') {
    settings.showCenterScaleRuler = normalized.showCenterScaleRuler
  }
  if (normalized.centerScaleRulerAnchorMode === 'screen-center' || normalized.centerScaleRulerAnchorMode === 'compass-center') {
    settings.centerScaleRulerAnchorMode = normalized.centerScaleRulerAnchorMode
  }

  return settings
}

export function loadStoredUserSettings(storageKey = USER_SETTINGS_STORAGE_KEY): StoredUserSettings {
  try {
    return normalizeStoredUserSettings(wx.getStorageSync(storageKey))
  } catch {
    return {}
  }
}

export function persistStoredUserSettings(
  settings: StoredUserSettings,
  storageKey = USER_SETTINGS_STORAGE_KEY,
): void {
  try {
    wx.setStorageSync(storageKey, settings)
  } catch {}
}

export function mergeStoredUserSettings(
  current: StoredUserSettings,
  patch: Partial<StoredUserSettings>,
): StoredUserSettings {
  return {
    ...current,
    ...patch,
  }
}

export function buildInitialSystemSettingsState(
  stored: StoredUserSettings,
  config?: Partial<SystemSettingsConfig>,
): ResolvedSystemSettingsState {
  const values = {
    ...DEFAULT_STORED_USER_SETTINGS,
    ...(config && config.values ? config.values : {}),
  }
  const locks = {
    ...DEFAULT_SETTING_LOCKS,
    ...(config && config.locks ? config.locks : {}),
  }

  const resolvedValues: Required<StoredUserSettings> = {
    ...values,
  }

  for (const [lockKey, isLocked] of Object.entries(locks) as Array<[SettingLockKey, boolean]>) {
    const valueKey = SETTING_LOCK_VALUE_MAP[lockKey]
    if (!valueKey) {
      continue
    }
    if (!isLocked && stored[valueKey] !== undefined) {
      ;(resolvedValues as Record<string, unknown>)[valueKey] = stored[valueKey]
    }
  }

  for (const [key, value] of Object.entries(stored) as Array<[keyof StoredUserSettings, StoredUserSettings[keyof StoredUserSettings]]>) {
    const matchingLockKey = (Object.keys(SETTING_LOCK_VALUE_MAP) as SettingLockKey[])
      .find((lockKey) => SETTING_LOCK_VALUE_MAP[lockKey] === key)
    if (matchingLockKey && locks[matchingLockKey]) {
      continue
    }
    if (value !== undefined) {
      ;(resolvedValues as Record<string, unknown>)[key] = value
    }
  }

  return {
    values: resolvedValues,
    locks,
  }
}

export function buildRuntimeSettingLocks(
  locks: Partial<Record<SettingLockKey, boolean>> | undefined,
  runtimeActive: boolean,
): Partial<Record<SettingLockKey, boolean>> {
  const sourceLocks = locks || {}
  if (runtimeActive) {
    return { ...sourceLocks }
  }

  const unlocked: Partial<Record<SettingLockKey, boolean>> = {}
  for (const key of Object.keys(sourceLocks) as SettingLockKey[]) {
    unlocked[key] = false
  }
  return unlocked
}

export function resolveSystemSettingsState(
  config?: Partial<SystemSettingsConfig>,
  storageKey = USER_SETTINGS_STORAGE_KEY,
  runtimeActive = false,
): ResolvedSystemSettingsState {
  return buildInitialSystemSettingsState(
    loadStoredUserSettings(storageKey),
    {
      values: config && config.values ? config.values : {},
      locks: buildRuntimeSettingLocks(config && config.locks ? config.locks : {}, runtimeActive),
    },
  )
}
