/**
 * State Adapter — maps backend ServerState + Capabilities → v2 component props.
 *
 * Pure functions, no side effects. Each function extracts exactly what
 * one v2 panel/molecule needs from the shared radio store.
 *
 * Epic #289, Phase 1.
 */

import type { ServerState, ReceiverState } from '$lib/types/state';
import type { Capabilities, FilterModeConfig } from '$lib/types/capabilities';
import type { VfoStateProps } from '../layout/layout-utils';
import { deriveIfShift, pbtRawToHz } from '../panels/filter-controls';

/* ── Helpers ─────────────────────────────────────────────────── */

/** Get the active receiver state (MAIN or SUB). */
function activeRx(state: ServerState): ReceiverState {
  return state.active === 'SUB' ? state.sub : state.main;
}

/** Check capability presence (safe for null caps). */
function hasCap(caps: Capabilities | null, name: string): boolean {
  return caps?.capabilities?.includes(name) ?? false;
}

export function resolveFilterModeConfig(
  caps: Capabilities | null,
  mode: string | undefined,
  dataMode: number | undefined,
): FilterModeConfig | null {
  const filterConfig = caps?.filterConfig;
  const normalizedMode = mode?.toUpperCase();
  const candidates: string[] = [];

  if (normalizedMode) {
    if ((dataMode ?? 0) > 0) {
      candidates.push(`${normalizedMode}-D`);
    }
    candidates.push(normalizedMode);
    if (normalizedMode === 'USB' || normalizedMode === 'LSB') {
      if ((dataMode ?? 0) > 0) {
        candidates.push('SSB-D');
      }
      candidates.push('SSB');
    }
    if (normalizedMode === 'CW-R') {
      candidates.push('CW');
    }
    if (normalizedMode === 'RTTY-R') {
      candidates.push('RTTY');
    }
  }

  for (const candidate of candidates) {
    const config = filterConfig?.[candidate];
    if (config) {
      return config;
    }
  }
  return null;
}

/* ── VFO ─────────────────────────────────────────────────────── */

export function toVfoProps(
  state: ServerState | null,
  receiver: 'main' | 'sub',
): VfoStateProps {
  if (!state) {
    return {
      receiver,
      freq: 14074000,
      mode: 'USB',
      filter: 'FIL1',
      sValue: 0,
      isActive: receiver === 'main',
      badges: {},
    };
  }

  const rx = state[receiver];
  const isActive = (state.active === 'SUB') === (receiver === 'sub');

  // Always show all possible badges, active state determines if they light up
  const badges: Record<string, boolean | string> = {
    'NB': rx.nb ?? false,
    'NR': rx.nr ?? false,
    'DIGI-SEL': rx.digisel ?? false,
    'IP+': rx.ipplus ?? false,
    'ANF': rx.autoNotch ?? false,
    'NOTCH': rx.manualNotch ?? false,
    'ATT': rx.att > 0,
    'PRE': rx.preamp > 0,
    'RFG': (rx.rfGain ?? 255) < 255,  // RF Gain reduced from max
    'SQL': (rx.squelch ?? 0) > 0,     // Squelch active
  };
  
  // Dynamic badges (only show when active)
  if (rx.dataMode) badges['DATA'] = true;
  if (state.split) badges['SPLIT'] = true;

  const filters = ['FIL1', 'FIL2', 'FIL3'];
  const filterLabel = filters[rx.filter - 1] ?? `FIL${rx.filter}`;

  return {
    receiver,
    freq: rx.freqHz,
    mode: rx.mode,
    filter: filterLabel,
    sValue: rx.sMeter,
    isActive,
    badges,
    rit: state.ritOn
      ? { active: true, offset: state.ritFreq ?? 0 }
      : undefined,
  };
}

/* ── RF Front End ────────────────────────────────────────────── */

export interface RfFrontEndProps {
  rfGain: number;
  squelch: number;
  att: number;
  pre: number;
  digiSel: boolean;
  ipPlus: boolean;
  attValues: number[];
  preValues: number[];
}

export function toRfFrontEndProps(
  state: ServerState | null,
  caps: Capabilities | null,
): RfFrontEndProps {
  const rx = state ? activeRx(state) : null;
  return {
    rfGain: rx?.rfGain ?? 255,
    squelch: rx?.squelch ?? 0,
    att: rx?.att ?? 0,
    digiSel: rx?.digisel ?? false,
    ipPlus: rx?.ipplus ?? false,
    pre: rx?.preamp ?? 0,
    attValues: caps?.attValues ?? [0, 6, 12, 18],
    preValues: caps?.preValues ?? [0, 1, 2],
  };
}

/* ── Filter ──────────────────────────────────────────────────── */

export interface FilterProps {
  currentMode: string;
  currentFilter: number;
  filterShape: number;
  filterLabels: string[];
  filterWidth: number;
  filterWidthMin: number;
  filterWidthMax: number;
  filterConfig: FilterModeConfig | null;
  ifShift: number;
  hasPbt: boolean;
  pbtInner: number;
  pbtOuter: number;
}

export function toFilterProps(
  state: ServerState | null,
  caps: Capabilities | null,
): FilterProps {
  const rx = state ? activeRx(state) : null;
  const pbtInner = pbtRawToHz(rx?.pbtInner ?? 128);
  const pbtOuter = pbtRawToHz(rx?.pbtOuter ?? 128);
  const filterConfig = resolveFilterModeConfig(caps, rx?.mode, rx?.dataMode);
  return {
    currentMode: rx?.mode ?? 'USB',
    currentFilter: rx?.filter ?? 1,
    filterShape: rx?.filterShape ?? 0,
    filterLabels: caps?.filters ?? ['FIL1', 'FIL2', 'FIL3'],
    filterWidth: rx?.filterWidth ?? 2400,
    filterWidthMin: filterConfig?.minHz ?? filterConfig?.table?.[0] ?? caps?.filterWidthMin ?? 50,
    filterWidthMax: filterConfig?.maxHz ?? (filterConfig?.table?.length ? filterConfig.table[filterConfig.table.length - 1] : undefined) ?? caps?.filterWidthMax ?? 9999,
    filterConfig,
    ifShift: hasCap(caps, 'if_shift') ? (rx?.ifShift ?? 0) : deriveIfShift(pbtInner, pbtOuter),
    hasPbt: hasCap(caps, 'pbt'),
    pbtInner,
    pbtOuter,
  };
}

/* ── AGC ─────────────────────────────────────────────────────── */

export interface AgcProps {
  agcMode: number;
  agcModes: number[];
  agcLabels: Record<string, string>;
}

export function toAgcProps(
  state: ServerState | null,
  caps: Capabilities | null,
): AgcProps {
  const rx = state ? activeRx(state) : null;
  return {
    agcMode: rx?.agc ?? 2,
    agcModes: caps?.agcModes ?? [1, 2, 3],
    agcLabels: caps?.agcLabels ?? { '1': 'FAST', '2': 'MID', '3': 'SLOW' },
  };
}

/* ── RIT / XIT ───────────────────────────────────────────────── */

export interface RitXitProps {
  ritActive: boolean;
  ritOffset: number;
  xitActive: boolean;
  xitOffset: number;
  hasRit: boolean;
  hasXit: boolean;
}

export function toRitXitProps(
  state: ServerState | null,
  caps: Capabilities | null,
): RitXitProps {
  return {
    ritActive: state?.ritOn ?? false,
    ritOffset: state?.ritFreq ?? 0,
    xitActive: state?.ritTx ?? false,
    xitOffset: state?.ritFreq ?? 0, // RIT and ∂TX share the frequency offset
    hasRit: hasCap(caps, 'rit'),
    hasXit: hasCap(caps, 'xit'),
  };
}

/* ── Mode Panel ──────────────────────────────────────────────── */

export interface ModeProps {
  currentMode: string;
  modes: string[];
  dataMode: number;
  hasDataMode: boolean;
  dataModeCount: number;
  dataModeLabels: Record<string, string>;
}

export function toModeProps(
  state: ServerState | null,
  caps: Capabilities | null,
): ModeProps {
  const rx = state ? activeRx(state) : null;
  return {
    currentMode: rx?.mode ?? 'USB',
    modes: caps?.modes ?? ['USB', 'LSB', 'CW', 'CW-R', 'AM', 'FM', 'RTTY', 'RTTY-R', 'PSK', 'PSK-R'],
    dataMode: rx?.dataMode ?? 0,
    hasDataMode: hasCap(caps, 'data_mode'),
    dataModeCount: caps?.dataModeCount ?? 0,
    dataModeLabels: caps?.dataModeLabels ?? { '0': 'OFF', '1': 'D1', '2': 'D2', '3': 'D3' },
  };
}

/* ── DSP Panel ───────────────────────────────────────────────── */

export interface DspProps {
  nrMode: number;
  nrLevel: number;
  nbActive: boolean;
  nbLevel: number;
  notchMode: 'off' | 'auto' | 'manual';
  notchFreq: number;
}

export function toDspProps(
  state: ServerState | null,
  _caps: Capabilities | null,
): DspProps {
  const rx = state ? activeRx(state) : null;

  // Notch mode: off / auto / manual
  let notchMode: 'off' | 'auto' | 'manual' = 'off';
  if (rx?.autoNotch) notchMode = 'auto';
  else if (rx?.manualNotch) notchMode = 'manual';

  return {
    nrMode: rx?.nr ? 1 : 0,
    nrLevel: rx?.nrLevel ?? 0,
    nbActive: rx?.nb ?? false,
    nbLevel: rx?.nbLevel ?? 0,
    notchMode,
    notchFreq: state?.notchFilter ?? 0,
  };
}

/* ── TX Panel ────────────────────────────────────────────────── */

export interface TxProps {
  txActive: boolean;
  rfPower: number;
  micGain: number;
  atuActive: boolean;
  atuTuning: boolean;
  voxActive: boolean;
  compActive: boolean;
  compLevel: number;
  monActive: boolean;
  monLevel: number;
  driveGain: number;
}

export function toTxProps(
  state: ServerState | null,
  _caps: Capabilities | null,
): TxProps {
  return {
    txActive: state?.ptt ?? false,
    rfPower: state?.powerLevel ?? 128,
    micGain: state?.micGain ?? 128,
    atuActive: (state?.tunerStatus ?? 0) > 0,
    atuTuning: (state?.tunerStatus ?? 0) === 2,
    voxActive: state?.voxOn ?? false,
    compActive: state?.compressorOn ?? false,
    compLevel: state?.compressorLevel ?? 0,
    monActive: state?.monitorOn ?? false,
    monLevel: state?.monitorGain ?? 128,
    driveGain: state?.driveGain ?? 128,
  };
}

/* ── CW Panel ────────────────────────────────────────────────── */

export interface CwProps {
  cwPitch: number;
  keySpeed: number;
  breakIn: number;
  apfMode: number;
  twinPeak: boolean;
  currentMode: string;
}

export function toCwProps(
  state: ServerState | null,
  _caps: Capabilities | null,
): CwProps {
  const rx = state ? activeRx(state) : null;
  return {
    cwPitch: state?.cwPitch ?? 600,
    keySpeed: state?.keySpeed ?? 12,
    breakIn: state?.breakIn ?? 0,
    apfMode: rx?.apfTypeLevel ?? 0,
    twinPeak: rx?.twinPeakFilter ?? false,
    currentMode: rx?.mode ?? 'USB',
  };
}

/* ── Meter Panel ─────────────────────────────────────────────── */

export interface MeterProps {
  sValue: number;
  rfPower: number;
  swr: number;
  alc: number;
  comp: number;
  vd: number;
  id: number;
  txActive: boolean;
  meterSource: string;
}

export function toMeterProps(state: ServerState | null): MeterProps {
  const mainRx = state?.main;
  const txMeters = (state as (ServerState & {
    tx?: { rfPower?: number; swr?: number; alc?: number };
    meterSource?: string;
  }) | null)?.tx;
  return {
    sValue: mainRx?.sMeter ?? 0,
    rfPower: txMeters?.rfPower ?? state?.powerLevel ?? 0,
    swr: txMeters?.swr ?? 0,
    alc: txMeters?.alc ?? 0,
    comp: state?.compMeter ?? 0,
    vd: state?.vdMeter ?? 0,
    id: state?.idMeter ?? 0,
    txActive: state?.ptt ?? false,
    meterSource: (state as { meterSource?: string } | null)?.meterSource ?? 'S',
  };
}

/* ── RX Audio Panel ──────────────────────────────────────────── */

export interface RxAudioProps {
  monitorMode: 'local' | 'live' | 'mute';
  afLevel: number;
  hasLiveAudio: boolean;
}

export interface AudioUiState {
  muted: boolean;
  rxEnabled: boolean;
  volume: number;
}

export function toRxAudioProps(
  state: ServerState | null,
  caps: Capabilities | null,
  audioState: AudioUiState,
): RxAudioProps {
  const rx = state ? activeRx(state) : null;
  const hasLiveAudio = hasCap(caps, 'audio');
  const monitorMode = audioState.muted
    ? 'mute'
    : audioState.rxEnabled && hasLiveAudio
      ? 'live'
      : 'local';
  // In live mode, show browser volume; in radio mode, show radio AF level
  const afLevel = monitorMode === 'live'
    ? Math.round(audioState.volume / 100 * 255)
    : (rx?.afLevel ?? 128);
  return {
    monitorMode,
    afLevel,
    hasLiveAudio,
  };
}

/* ── Band Selector ───────────────────────────────────────────── */

export interface BandSelectorProps {
  currentFreq: number;
}

export function toBandSelectorProps(
  state: ServerState | null,
): BandSelectorProps {
  return {
    currentFreq: state?.main?.freqHz ?? 14074000,
  };
}

/* ── VFO Ops (split / swap / etc.) ───────────────────────────── */

export interface VfoOpsProps {
  splitActive: boolean;
  txVfo: 'main' | 'sub';
  dualWatch: boolean;
  mainSubTracking: boolean;
}

export function toVfoOpsProps(
  state: ServerState | null,
  caps: Capabilities | null,
): VfoOpsProps {
  const activeVfo = state?.active === 'SUB' ? 'sub' : 'main';
  const txVfo = state?.split
    ? activeVfo === 'main'
      ? 'sub'
      : 'main'
    : activeVfo;

  return {
    splitActive: state?.split ?? false,
    txVfo,
    dualWatch: state?.dualWatch ?? false,
    mainSubTracking: state?.mainSubTracking ?? false,
  };
}
