/* ============================================================
   AUDIO PAGE — Audio Settings
   Design: Reference luxsin_x8_音频设置.png
   Sections:
     - 平衡与灵敏度: 左右平衡, VU灵敏度, 模拟输入增益 sliders
     - 输出特性: 滤波特性, 耳机增益, 音量幅度
     - 系统与接口: 开机音量, XLR极性
   All list rows → navigate to /select page
   ============================================================ */
import { useDevice } from "@/contexts/DeviceContext";
import { ChevronLeft, ChevronRight } from "lucide-react";
import { useLocation } from "wouter";
import { useState, useEffect, useRef } from "react";
import BottomNav from "@/components/BottomNav";
import { navigateToSelect } from "./SelectPage";
import {
  getBootSoundMaxIndex,
  normalizeBootSound,
  parseFirmwareVersion,
  readBootSoundFromState,
} from "@/lib/luxsinApi";
import localeEn from "@/locales/data-en.json";
import { resolveLocalePack } from "@/locales/resolveLocale";
import { usePageTitleWithConnection } from "@/hooks/usePageTitleWithConnection";

function CyanSlider({ value, min, max, step = 1, onChange, onRelease }: {
  value: number;
  min: number;
  max: number;
  step?: number;
  onChange: (v: number) => void;
  /** Commit to device once when the user releases the thumb (pointer / keyboard). */
  onRelease?: (v: number) => void;
}) {
  const fillPct = ((value - min) / (max - min)) * 100;
  const emitRelease = (el: EventTarget | null) => {
    if (!(el instanceof HTMLInputElement)) return;
    onRelease?.(Number(el.value));
  };
  return (
    <div className="relative flex items-center w-full mt-2">
      <div className="absolute left-0 h-[4px] rounded-full pointer-events-none"
        style={{ width: `${fillPct}%`, background: "#00FFF6", boxShadow: "0 0 6px rgba(0,255,246,0.5)" }} />
      <input
        type="range"
        min={min}
        max={max}
        step={step}
        value={value}
        className="cyan-slider relative z-10"
        onChange={(e) => onChange(Number(e.target.value))}
        onPointerUp={(e) => emitRelease(e.currentTarget)}
        onPointerCancel={(e) => emitRelease(e.currentTarget)}
        onKeyUp={(e) => {
          if (["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", "Home", "End", "PageUp", "PageDown"].includes(e.key)) {
            emitRelease(e.currentTarget);
          }
        }}
      />
    </div>
  );
}

function SectionHeader({ title }: { title: string }) {
  return (
    <div className="px-1 pt-5 pb-2">
      <span className="text-[14px] font-semibold" style={{ color: "#00FFF6" }}>{title}</span>
    </div>
  );
}

function IOSToggle({ checked, onChange }: { checked: boolean; onChange: (v: boolean) => void }) {
  return (
    <label className="ios-toggle" onClick={(e) => e.stopPropagation()}>
      <input type="checkbox" checked={checked} onChange={(e) => onChange(e.target.checked)} />
      <span className="ios-toggle-track"><span className="ios-toggle-thumb" /></span>
    </label>
  );
}

function ListRow({ label, value, onClick, toggle, checked, onToggle }: {
  label: string;
  value?: string;
  onClick?: () => void;
  toggle?: boolean;
  checked?: boolean;
  onToggle?: (v: boolean) => void;
}) {
  if (toggle) {
    return (
      <div className="ios-list-row">
        <span className="flex-1 text-[16px] text-white">{label}</span>
        <IOSToggle checked={!!checked} onChange={onToggle ?? (() => {})} />
      </div>
    );
  }
  return (
    <button className="ios-list-row w-full text-left active:bg-white/5 transition-colors" onClick={onClick}>
      <span className="flex-1 text-[16px] text-white">{label}</span>
      <span className="ios-row-value">{value}</span>
      <ChevronRight size={16} className="ios-chevron ml-1" />
    </button>
  );
}

type LocaleDac = {
  dac?: {
    sectionBalanceSensitivity?: string;
    sectionOutput?: string;
    sectionSystemInterface?: string;
    balance?: string;
    sensitivity?: string;
    analogInputGain?: string;
    autoImpedanceDetection?: string;
    filters?: { label?: string; options?: Array<{ index: number; label: string }> };
    dacGain?: { label?: string; options?: Array<{ index: number; label: string }> };
    dacVolumeDirect?: { label?: string; options?: Array<{ index: number; label: string }> };
    dacArc?: { label?: string; options?: Array<{ index: number; label: string }> };
    volumeStep?: string;
    bootVolume?: string | { label?: string; options?: Array<{ index: number; label: string }> };
    xlr?: { label?: string; options?: Array<{ index: number; label: string }> };
  };
  home?: { audioSet?: string };
};

function optionLabels(items: Array<{ index: number; label: string }> | undefined, fallback: string[]) {
  if (!items || items.length === 0) return fallback;
  const sorted = [...items].sort((a, b) => a.index - b.index);
  return sorted.map((item) => item.label);
}

const STEP_OPTIONS = ["0.5dB", "1dB", "2dB", "3dB"];

const BOOT_VOLUME_FALLBACK = [
  "Default",
  "-5dB",
  "-10dB",
  "-15dB",
  "-20dB",
  "-25dB",
  "-30dB",
  "-35dB",
  "-40dB",
  "-45dB",
  "-50dB",
];

function bootVolumeLabel(dacText: LocaleDac["dac"], index: number): string {
  const boot = dacText?.bootVolume;
  if (boot && typeof boot === "object" && boot.options?.length) {
    const hit = boot.options.find((o) => o.index === index);
    if (hit) return hit.label;
    const sorted = [...boot.options].sort((a, b) => a.index - b.index);
    if (index >= 0 && index < sorted.length) return sorted[index]?.label ?? BOOT_VOLUME_FALLBACK[index] ?? "—";
  }
  return BOOT_VOLUME_FALLBACK[index] ?? "—";
}

function bootVolumeOptions(dacText: LocaleDac["dac"], maxIndex: number): string[] {
  const labels: string[] = [];
  for (let i = 0; i <= maxIndex; i += 1) {
    labels.push(bootVolumeLabel(dacText, i));
  }
  return labels;
}

function bootVolumeRowLabel(dacText: LocaleDac["dac"]): string {
  const boot = dacText?.bootVolume;
  if (boot && typeof boot === "object" && boot.label) return boot.label;
  if (typeof boot === "string") return boot;
  return "Boot volume";
}

export default function AudioPage() {
  const [location, setLocation] = useLocation();
  const { deviceState, updateSetting, refresh, isConnected, api } = useDevice();
  const ds = deviceState;
  const vuSensor = (ds as ({ vuSensor?: number } | null))?.vuSensor;
  const localeData = resolveLocalePack(ds?.language) as LocaleDac;
  const dacText = localeData.dac ?? {};

  // balance 从接口获取的是乘以 10 后的值，需要除以 10 显示（例如：-130 → -13.0）
  const balanceVal = ds?.balance !== undefined ? ds.balance / 10 : 0;
  // vuSensor 从接口获取的是放大 2 倍的值，需要除以 2 显示（例如：20 → +10dB）
  const vuSensVal = vuSensor !== undefined ? vuSensor / 2 : 0;
  // analogGain 从接口获取的是放大 2 倍的值，需要除以 2 显示（例如：-6 → -3dB）
  const analogGainVal = ds?.analogGain !== undefined ? ds.analogGain / 2 : 0;
  const bootSoundFromApi = readBootSoundFromState(ds);
  const [localBootSound, setLocalBootSound] = useState(bootSoundFromApi);
  const [localBalance, setLocalBalance] = useState(balanceVal);
  const [localVuSens, setLocalVuSens] = useState(0);
  const [localAnalogGain, setLocalAnalogGain] = useState(analogGainVal);
  const isBalanceDragging = useRef(false);
  const isVuDragging = useRef(false);
  const isAnalogGainDragging = useRef(false);

  useEffect(() => { if (!isBalanceDragging.current) setLocalBalance(balanceVal); }, [balanceVal]);
  useEffect(() => { if (!isVuDragging.current) setLocalVuSens(vuSensVal); }, [vuSensVal]);
  useEffect(() => {
    if (!isAnalogGainDragging.current) setLocalAnalogGain(analogGainVal);
  }, [analogGainVal]);
  useEffect(() => {
    setLocalBootSound(readBootSoundFromState(ds));
  }, [ds?.bootSound]);

  useEffect(() => {
    if (location !== "/audio") return;
    setLocalBootSound(readBootSoundFromState(ds));
  }, [location, ds?.bootSound, ds]);

  useEffect(() => {
    if (location !== "/audio") return;
    if (isConnected || api) {
      void refresh();
    }
  }, [location, isConnected, api, refresh]);

  const gainIdx = ds?.dacGain ?? 0;
  const autoImpedanceOn = (ds?.dacImpedance ?? 0) === 1;
  const dacVolumeDirectIdx = ds?.dacVolumeDirect ?? 0;
  const dacArcIdx = ds?.dacArc ?? 0;
  const stepIdx = ds?.soundStep ?? 1;
  const filterIdx = ds?.pcm ?? 0;
  const xlrIdx = ds?.xlr ?? 0;
  const bootSoundVal = normalizeBootSound(localBootSound);
  const firmwareVersion = parseFirmwareVersion(ds?.version);
  const bootSoundMaxIdx = getBootSoundMaxIndex(firmwareVersion);
  const bootSoundSelectIdx = Math.min(bootSoundVal, bootSoundMaxIdx);
  const BOOT_VOLUME_OPTIONS = bootVolumeOptions(dacText, bootSoundMaxIdx);

  const FILTER_OPTIONS = optionLabels(dacText.filters?.options, ["快速滚降", "慢速滚降", "短延迟快速滚降", "短延迟慢速滚降", "超慢速滚降", "低离散短延迟"]);
  const GAIN_OPTIONS = optionLabels(dacText.dacGain?.options, ["低", "中", "高"]);
  const DAC_VOLUME_DIRECT_OPTIONS = optionLabels(dacText.dacVolumeDirect?.options, ["关闭", "0dB", "-12dB"]);
  const DAC_ARC_OPTIONS = optionLabels(dacText.dacArc?.options, ["ARC", "EARC"]);
  const XLR_OPTIONS = optionLabels(dacText.xlr?.options, ["正常", "反转"]);

  const pageTitle = usePageTitleWithConnection(localeData.home?.audioSet ?? "Audio");

  const goSelect = (title: string, options: string[], selected: number, key: string) => {
    navigateToSelect(title, options, selected, "/audio", key);
    setLocation("/select");
  };

  return (
    <div className="min-h-screen bg-black">
      <div className="page-header">
        <button onClick={() => setLocation("/")} className="mr-4 text-white/60 active:text-white transition-colors">
          <ChevronLeft size={24} />
        </button>
        <h1 className="flex-1 text-center text-[17px] font-semibold text-white">
          {pageTitle}
        </h1>
        <div className="w-8" />
      </div>

      <div className="px-4 pb-32">
        {/* ── 平衡与灵敏度 ── */}
        <SectionHeader title={dacText.sectionBalanceSensitivity ?? "平衡与灵敏度"} />
        <div className="ios-list-group px-4 py-3 space-y-4">
          <div>
            <div className="flex items-center justify-between">
              <span className="text-[16px] text-white">{dacText.balance ?? "左右平衡"}</span>
              <span className="text-[16px] font-semibold" style={{ color: "#00FFF6" }}>
                {localBalance >= 0 ? `+${localBalance.toFixed(1)}` : localBalance.toFixed(1)} dB
              </span>
            </div>
            <CyanSlider
              value={localBalance}
              min={-15}
              max={15}
              step={0.1}
              onChange={(v) => {
                isBalanceDragging.current = true;
                setLocalBalance(v);
              }}
              onRelease={(v) => {
                isBalanceDragging.current = false;
                setLocalBalance(v);
                updateSetting({ balance: Math.round(v * 10) });
              }}
            />
          </div>
          <div className="border-t border-white/[0.06]" />
          <div>
            <div className="flex items-center justify-between">
              <span className="text-[16px] text-white">{dacText.sensitivity ?? "VU 表灵敏度"}</span>
              <span className="text-[16px] font-semibold" style={{ color: "#00FFF6" }}>
                {localVuSens >= 0 ? `+${localVuSens}` : localVuSens} dB
              </span>
            </div>
            <CyanSlider
              value={localVuSens}
              min={-20}
              max={20}
              step={1}
              onChange={(v) => {
                isVuDragging.current = true;
                setLocalVuSens(v);
              }}
              onRelease={(v) => {
                isVuDragging.current = false;
                setLocalVuSens(v);
                updateSetting({ vuSensor: Math.round(v * 2) });
              }}
            />
          </div>
          <div className="border-t border-white/[0.06]" />
          <div>
            <div className="flex items-center justify-between">
              <span className="text-[16px] text-white">{dacText.analogInputGain ?? "模拟输入增益"}</span>
              <span className="text-[16px] font-semibold" style={{ color: "#00FFF6" }}>
                {localAnalogGain >= 0 ? `+${localAnalogGain.toFixed(1)}` : localAnalogGain.toFixed(1)} dB
              </span>
            </div>
            <CyanSlider
              value={localAnalogGain}
              min={-12}
              max={12}
              step={0.5}
              onChange={(v) => {
                isAnalogGainDragging.current = true;
                setLocalAnalogGain(v);
              }}
              onRelease={(v) => {
                isAnalogGainDragging.current = false;
                setLocalAnalogGain(v);
                updateSetting({ analogGain: Math.round(v * 2) });
              }}
            />
          </div>
        </div>

        {/* ── 输出特性 ── */}
        <SectionHeader title={dacText.sectionOutput ?? "输出特性"} />
        <div className="ios-list-group">
          <ListRow
            label={dacText.filters?.label ?? "滤波特性"}
            value={FILTER_OPTIONS[filterIdx] ?? FILTER_OPTIONS[0] ?? "—"}
            onClick={() => goSelect(dacText.filters?.label ?? "选择滤波特性", FILTER_OPTIONS, filterIdx, "filterCharacteristic")}
          />
          <ListRow
            label={dacText.dacGain?.label ?? "耳机增益"}
            value={GAIN_OPTIONS[gainIdx] ?? GAIN_OPTIONS[0] ?? "—"}
            onClick={() => goSelect(dacText.dacGain?.label ?? "选择耳机增益", GAIN_OPTIONS, gainIdx, "dacGain")}
          />
          <ListRow
            label={dacText.autoImpedanceDetection ?? "自动检测耳机阻抗"}
            toggle
            checked={autoImpedanceOn}
            onToggle={(v) => updateSetting({ dacImpedance: v ? 1 : 0 })}
          />
          <ListRow
            label={dacText.dacVolumeDirect?.label ?? "前级输出音量直通模式"}
            value={DAC_VOLUME_DIRECT_OPTIONS[dacVolumeDirectIdx] ?? DAC_VOLUME_DIRECT_OPTIONS[0] ?? "—"}
            onClick={() =>
              goSelect(
                dacText.dacVolumeDirect?.label ?? "前级输出音量直通模式",
                DAC_VOLUME_DIRECT_OPTIONS,
                dacVolumeDirectIdx,
                "dacVolumeDirect",
              )
            }
          />
          <ListRow
            label={dacText.dacArc?.label ?? "ARC模式"}
            value={DAC_ARC_OPTIONS[dacArcIdx] ?? DAC_ARC_OPTIONS[0] ?? "—"}
            onClick={() =>
              goSelect(
                dacText.dacArc?.label ?? "ARC模式",
                DAC_ARC_OPTIONS,
                dacArcIdx,
                "dacArc",
              )
            }
          />
          <ListRow
            label={dacText.volumeStep ?? "音量幅度"}
            value={STEP_OPTIONS[stepIdx] ?? STEP_OPTIONS[0]}
            onClick={() => goSelect(dacText.volumeStep ?? "选择音量幅度", STEP_OPTIONS, stepIdx, "soundStep")}
          />
        </div>

        {/* ── 系统与接口 ── */}
        <SectionHeader title={dacText.sectionSystemInterface ?? "系统与接口"} />
        <div className="ios-list-group">
          <ListRow
            label={bootVolumeRowLabel(dacText)}
            value={bootVolumeLabel(dacText, bootSoundVal)}
            onClick={() =>
              goSelect(
                bootVolumeRowLabel(dacText),
                BOOT_VOLUME_OPTIONS,
                bootSoundSelectIdx,
                "bootSound",
              )
            }
          />
          <ListRow
            label={dacText.xlr?.label ?? "XLR 端口极性"}
            value={XLR_OPTIONS[xlrIdx] ?? XLR_OPTIONS[0] ?? "—"}
            onClick={() => goSelect(dacText.xlr?.label ?? "选择 XLR 极性", XLR_OPTIONS, xlrIdx, "xlr")}
          />
        </div>
      </div>

      <BottomNav />
    </div>
  );
}
