import { useEffect } from "react";

import { SettingsItem } from "@components/SettingsItem";
import { SettingsPageHeader } from "@components/SettingsPageheader";
import { useSettingsStore } from "@/hooks/stores";
import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc";
import { SelectMenuBasic } from "@components/SelectMenuBasic";
import Checkbox from "@components/Checkbox";
import { m } from "@localizations/messages.js";

import notifications from "../notifications";

interface AudioConfigResult {
  bitrate: number;
  complexity: number;
  dtx_enabled: boolean;
  fec_enabled: boolean;
  buffer_periods: number;
  packet_loss_perc: number;
}

const AUDIO_DEFAULTS = {
  bitrate: 192,
  complexity: 8,
  packetLossPerc: 20,
} as const;

export default function SettingsAudioRoute() {
  const { send } = useJsonRpc();

  const handleRpcError = (resp: JsonRpcResponse, defaultMsg?: string) => {
    if ("error" in resp) {
      notifications.error(String(resp.error.data || defaultMsg || m.unknown_error()));
      return true;
    }
    return false;
  };

  const {
    setAudioOutputEnabled,
    setAudioInputAutoEnable,
    setAudioOutputSource,
    audioOutputEnabled,
    audioInputAutoEnable,
    audioOutputSource,
    audioBitrate,
    setAudioBitrate,
    audioComplexity,
    setAudioComplexity,
    audioDTXEnabled,
    setAudioDTXEnabled,
    audioFECEnabled,
    setAudioFECEnabled,
    audioBufferPeriods,
    setAudioBufferPeriods,
    audioPacketLossPerc,
    setAudioPacketLossPerc,
  } = useSettingsStore();

  useEffect(() => {
    send("getAudioOutputEnabled", {}, (resp: JsonRpcResponse) => {
      if ("error" in resp) return;
      setAudioOutputEnabled(resp.result as boolean);
    });

    send("getAudioInputAutoEnable", {}, (resp: JsonRpcResponse) => {
      if ("error" in resp) return;
      setAudioInputAutoEnable(resp.result as boolean);
    });

    send("getAudioOutputSource", {}, (resp: JsonRpcResponse) => {
      if ("error" in resp) return;
      setAudioOutputSource(resp.result as string);
    });

    send("getAudioConfig", {}, (resp: JsonRpcResponse) => {
      if ("error" in resp) return;
      const config = resp.result as AudioConfigResult;
      setAudioBitrate(config.bitrate);
      setAudioComplexity(config.complexity);
      setAudioDTXEnabled(config.dtx_enabled);
      setAudioFECEnabled(config.fec_enabled);
      setAudioBufferPeriods(config.buffer_periods);
      setAudioPacketLossPerc(config.packet_loss_perc);
    });
  }, [send, setAudioOutputEnabled, setAudioInputAutoEnable, setAudioOutputSource, setAudioBitrate, setAudioComplexity, setAudioDTXEnabled, setAudioFECEnabled, setAudioBufferPeriods, setAudioPacketLossPerc]);

  const handleAudioOutputEnabledChange = (enabled: boolean) => {
    send("setAudioOutputEnabled", { enabled }, (resp: JsonRpcResponse) => {
      if ("error" in resp) {
        const errorMsg = enabled
          ? m.audio_output_failed_enable({ error: String(resp.error.data || m.unknown_error()) })
          : m.audio_output_failed_disable({ error: String(resp.error.data || m.unknown_error()) });
        notifications.error(errorMsg);
        return;
      }

      setAudioOutputEnabled(enabled);
      const successMsg = enabled ? m.audio_output_enabled() : m.audio_output_disabled();
      notifications.success(successMsg);
    });
  };

  const handleAudioOutputSourceChange = (source: string) => {
    send("setAudioOutputSource", { source }, (resp: JsonRpcResponse) => {
      if ("error" in resp) {
        const errorMsg = m.audio_settings_output_source_failed({
          error: String(resp.error.data || m.unknown_error())
        });
        notifications.error(errorMsg);
        return;
      }

      setAudioOutputSource(source);
      notifications.success(m.audio_settings_output_source_success());
    });
  };

  const handleAudioInputAutoEnableChange = (enabled: boolean) => {
    send("setAudioInputAutoEnable", { enabled }, (resp: JsonRpcResponse) => {
      if (handleRpcError(resp)) return;

      setAudioInputAutoEnable(enabled);
      const successMsg = enabled
        ? m.audio_input_auto_enable_enabled()
        : m.audio_input_auto_enable_disabled();
      notifications.success(successMsg);
    });
  };

  const getCurrentConfig = () => ({
    bitrate: audioBitrate,
    complexity: audioComplexity,
    dtxEnabled: audioDTXEnabled,
    fecEnabled: audioFECEnabled,
    bufferPeriods: audioBufferPeriods,
    packetLossPerc: audioPacketLossPerc,
  });

  const handleAudioConfigChange = (updates: Partial<ReturnType<typeof getCurrentConfig>>) => {
    const config = { ...getCurrentConfig(), ...updates };

    send("setAudioConfig", config, (resp: JsonRpcResponse) => {
      if (handleRpcError(resp)) return;

      setAudioBitrate(config.bitrate);
      setAudioComplexity(config.complexity);
      setAudioDTXEnabled(config.dtxEnabled);
      setAudioFECEnabled(config.fecEnabled);
      setAudioBufferPeriods(config.bufferPeriods);
      setAudioPacketLossPerc(config.packetLossPerc);
      notifications.success(m.audio_settings_config_updated());
    });
  };

  const handleRestartAudio = () => {
    send("restartAudioOutput", {}, (resp: JsonRpcResponse) => {
      if (handleRpcError(resp)) return;
      notifications.success(m.audio_settings_applied());
    });
  };

  return (
    <div className="space-y-4">
      <SettingsPageHeader
        title={m.audio_settings_title()}
        description={m.audio_settings_description()}
      />
      <div className="space-y-4">
        <SettingsItem
          title={m.audio_settings_output_title()}
          description={m.audio_settings_output_description()}
        >
          <Checkbox
            checked={audioOutputEnabled || false}
            onChange={(e) => handleAudioOutputEnabledChange(e.target.checked)}
          />
        </SettingsItem>

        <SettingsItem
          title={m.audio_settings_output_source_title()}
          description={m.audio_settings_output_source_description()}
        >
          <SelectMenuBasic
            size="SM"
            value={audioOutputSource || "usb"}
            options={[
              { value: "usb", label: m.audio_settings_usb_label() },
              { value: "hdmi", label: m.audio_settings_hdmi_label() },
            ]}
            onChange={(e) => handleAudioOutputSourceChange(e.target.value)}
          />
        </SettingsItem>

        <SettingsItem
          title={m.audio_settings_auto_enable_microphone_title()}
          description={m.audio_settings_auto_enable_microphone_description()}
        >
          <Checkbox
            checked={audioInputAutoEnable || false}
            onChange={(e) => handleAudioInputAutoEnableChange(e.target.checked)}
          />
        </SettingsItem>

        <SettingsItem
          title={m.audio_settings_bitrate_title()}
          description={m.audio_settings_bitrate_description()}
        >
          <SelectMenuBasic
            size="SM"
            value={String(audioBitrate)}
            options={[
              { value: "64", label: "64 kbps" },
              { value: "96", label: "96 kbps" },
              { value: "128", label: "128 kbps" },
              { value: "160", label: "160 kbps" },
              { value: "192", label: `192 kbps${192 === AUDIO_DEFAULTS.bitrate ? m.audio_settings_default_suffix() : ''}` },
              { value: "256", label: "256 kbps" },
            ]}
            onChange={(e) => handleAudioConfigChange({ bitrate: parseInt(e.target.value) })}
          />
        </SettingsItem>

        <SettingsItem
          title={m.audio_settings_complexity_title()}
          description={m.audio_settings_complexity_description()}
        >
          <SelectMenuBasic
            size="SM"
            value={String(audioComplexity)}
            options={[
              { value: "0", label: "0 (fastest)" },
              { value: "2", label: "2" },
              { value: "5", label: "5" },
              { value: "8", label: `8${8 === AUDIO_DEFAULTS.complexity ? m.audio_settings_default_suffix() : ''}` },
              { value: "10", label: "10 (best quality)" },
            ]}
            onChange={(e) => handleAudioConfigChange({ complexity: parseInt(e.target.value) })}
          />
        </SettingsItem>

        <SettingsItem
          title={m.audio_settings_dtx_title()}
          description={m.audio_settings_dtx_description()}
        >
          <Checkbox
            checked={audioDTXEnabled}
            onChange={(e) => handleAudioConfigChange({ dtxEnabled: e.target.checked })}
          />
        </SettingsItem>

        <SettingsItem
          title={m.audio_settings_fec_title()}
          description={m.audio_settings_fec_description()}
        >
          <Checkbox
            checked={audioFECEnabled}
            onChange={(e) => handleAudioConfigChange({ fecEnabled: e.target.checked })}
          />
        </SettingsItem>

        <SettingsItem
          title={m.audio_settings_buffer_title()}
          description={m.audio_settings_buffer_description()}
        >
          <SelectMenuBasic
            size="SM"
            value={String(audioBufferPeriods)}
            options={[
              { value: "4", label: "4 (80ms)" },
              { value: "8", label: "8 (160ms)" },
              { value: "12", label: "12 (240ms)" },
              { value: "16", label: "16 (320ms)" },
              { value: "24", label: "24 (480ms)" },
            ]}
            onChange={(e) => handleAudioConfigChange({ bufferPeriods: parseInt(e.target.value) })}
          />
        </SettingsItem>

        <SettingsItem
          title={m.audio_settings_packet_loss_title()}
          description={m.audio_settings_packet_loss_description()}
        >
          <SelectMenuBasic
            size="SM"
            value={String(audioPacketLossPerc)}
            options={[
              { value: "0", label: `0%${m.audio_settings_no_compensation_suffix()}` },
              { value: "5", label: "5%" },
              { value: "10", label: "10%" },
              { value: "15", label: "15%" },
              { value: "20", label: `20%${20 === AUDIO_DEFAULTS.packetLossPerc ? m.audio_settings_default_suffix() : ''}` },
              { value: "25", label: "25%" },
              { value: "30", label: "30%" },
            ]}
            onChange={(e) => handleAudioConfigChange({ packetLossPerc: parseInt(e.target.value) })}
          />
        </SettingsItem>

        <div className="pt-4">
          <button
            onClick={handleRestartAudio}
            className="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
          >
            {m.audio_settings_apply_button()}
          </button>
        </div>
      </div>
    </div>
  );
}
