import { useCallback, useEffect, useRef, useState } from "react";
import {
  FaDiscord,
  FaPause,
  FaPlay,
  FaStop,
  FaForwardStep,
} from "react-icons/fa6";
import { audioApi } from "../api";
import type { AudioStatus, DiscordGuild, UserInfo } from "../types";
import "./DiscordPanel.css";

interface Props {
  user: UserInfo;
}

const POLL_INTERVAL_MS = 5000;

export default function DiscordPanel({ user }: Props) {
  const discordConnection = user.connections.find(
    (c) => c.provider === "discord",
  );

  // ── Guild selection ──
  const [guilds, setGuilds] = useState<DiscordGuild[]>([]);
  const [selectedGuildId, setSelectedGuildId] = useState<string | null>(null);
  const [guildsLoading, setGuildsLoading] = useState(true);
  const [guildsError, setGuildsError] = useState<string | null>(null);

  // ── Audio status ──
  const [status, setStatus] = useState<AudioStatus | null>(null);
  const [statusError, setStatusError] = useState<string | null>(null);
  const pollRef = useRef<ReturnType<typeof setInterval> | null>(null);

  // ── Play input ──
  const [playUrl, setPlayUrl] = useState("");
  const [playLoading, setPlayLoading] = useState(false);
  const [playError, setPlayError] = useState<string | null>(null);

  // ── Action feedback ──
  const [actionError, setActionError] = useState<string | null>(null);

  // ── Load guilds on mount ──
  useEffect(() => {
    if (!discordConnection) return;
    setGuildsLoading(true);
    audioApi
      .listGuilds()
      .then((list) => {
        setGuilds(list);
        if (list.length === 1) setSelectedGuildId(list[0].id);
      })
      .catch((err) => {
        const msg = err instanceof Error ? err.message : String(err);
        setGuildsError(msg.replace(/^\d+:\s*/, "").trim());
      })
      .finally(() => setGuildsLoading(false));
  }, [discordConnection]);

  // ── Poll status whenever a guild is selected ──
  const fetchStatus = useCallback(async (guildId: string) => {
    try {
      const s = await audioApi.getStatus(guildId);
      setStatus(s);
      setStatusError(null);
    } catch (err) {
      const msg = err instanceof Error ? err.message : String(err);
      setStatusError(msg.replace(/^\d+:\s*/, "").trim());
    }
  }, []);

  useEffect(() => {
    if (pollRef.current) clearInterval(pollRef.current);
    if (!selectedGuildId) {
      setStatus(null);
      return;
    }
    fetchStatus(selectedGuildId);
    pollRef.current = setInterval(
      () => fetchStatus(selectedGuildId),
      POLL_INTERVAL_MS,
    );
    return () => {
      if (pollRef.current) clearInterval(pollRef.current);
    };
  }, [selectedGuildId, fetchStatus]);

  // ── Helpers ──
  function errMsg(err: unknown) {
    const msg = err instanceof Error ? err.message : String(err);
    return msg.replace(/^\d+:\s*/, "").trim();
  }

  async function runAction(fn: () => Promise<void>) {
    setActionError(null);
    try {
      await fn();
      // Immediate status refresh after any action
      if (selectedGuildId) await fetchStatus(selectedGuildId);
    } catch (err) {
      setActionError(errMsg(err));
    }
  }

  async function handlePlay(e: React.FormEvent) {
    e.preventDefault();
    if (!selectedGuildId || !playUrl.trim()) return;
    setPlayLoading(true);
    setPlayError(null);
    try {
      await audioApi.play(selectedGuildId, playUrl.trim());
      setPlayUrl("");
      if (selectedGuildId) await fetchStatus(selectedGuildId);
    } catch (err) {
      setPlayError(errMsg(err));
    } finally {
      setPlayLoading(false);
    }
  }

  // ── Don't render if no Discord connection ──
  if (!discordConnection) return null;

  const selectedGuild = guilds.find((g) => g.id === selectedGuildId);
  const isPlaying = !!status?.current_track && !status?.is_paused;

  return (
    <div className="discord-panel">
      {/* Header */}
      <div className="discord-header">
        <FaDiscord className="discord-header-icon" />
        <h2>Discord</h2>
      </div>

      {/* Guild selector */}
      <section className="discord-section">
        <h3>Server</h3>
        {guildsLoading ? (
          <p className="discord-muted">Loading servers…</p>
        ) : guildsError ? (
          <p className="discord-error">{guildsError}</p>
        ) : guilds.length === 0 ? (
          <p className="discord-muted">
            The bot isn't in any servers yet.
          </p>
        ) : guilds.length === 1 ? (
          <p className="discord-guild-name">{guilds[0].name}</p>
        ) : (
          <select
            className="discord-select"
            value={selectedGuildId ?? ""}
            onChange={(e) => setSelectedGuildId(e.target.value || null)}
          >
            <option value="">— Select a server —</option>
            {guilds.map((g) => (
              <option key={g.id} value={g.id}>
                {g.name}
              </option>
            ))}
          </select>
        )}
      </section>

      {/* Voice channel */}
      {selectedGuild && (
        <section className="discord-section">
          <h3>Voice Channel</h3>
          {statusError ? (
            <p className="discord-error">{statusError}</p>
          ) : status?.voice_channel ? (
            <p className="discord-channel-name">
              <span className="discord-channel-hash">#</span>
              {status.voice_channel}
            </p>
          ) : (
            <p className="discord-muted">Not connected to a voice channel</p>
          )}
        </section>
      )}

      {/* Now Playing */}
      {selectedGuild && (
        <section className="discord-section">
          <h3>Now Playing</h3>
          {status?.current_track ? (
            <div className="discord-now-playing">
              <p
                className="discord-track-title"
                title={status.current_track.title}
              >
                {status.current_track.title}
              </p>
              <p className="discord-track-status">
                {status.is_paused ? "⏸ Paused" : "▶ Playing"}
              </p>
            </div>
          ) : (
            <p className="discord-muted">Nothing is playing</p>
          )}

          {/* Controls */}
          <div className="discord-controls">
            {status?.is_paused ? (
              <button
                className="discord-btn discord-btn-play"
                title="Resume"
                onClick={() =>
                  runAction(() => audioApi.resume(selectedGuildId!))
                }
                disabled={!status?.current_track}
              >
                <FaPlay />
              </button>
            ) : (
              <button
                className="discord-btn discord-btn-pause"
                title="Pause"
                onClick={() =>
                  runAction(() => audioApi.pause(selectedGuildId!))
                }
                disabled={!status?.current_track}
              >
                <FaPause />
              </button>
            )}
            <button
              className="discord-btn discord-btn-skip"
              title="Skip"
              onClick={() => runAction(() => audioApi.skip(selectedGuildId!))}
              disabled={!status?.current_track}
            >
              <FaForwardStep />
            </button>
            <button
              className="discord-btn discord-btn-stop"
              title="Stop"
              onClick={() => runAction(() => audioApi.stop(selectedGuildId!))}
              disabled={!status?.current_track}
            >
              <FaStop />
            </button>
          </div>

          {actionError && <p className="discord-error">{actionError}</p>}
        </section>
      )}

      {/* Queue */}
      {selectedGuild && (
        <section className="discord-section">
          <h3>Queue {status && status.queue.length > 0 && <span className="discord-queue-count">({status.queue.length})</span>}</h3>
          {!status || status.queue.length === 0 ? (
            <p className="discord-muted">Queue is empty</p>
          ) : (
            <ul className="discord-queue-list">
              {status.queue.map((track, i) => (
                <li key={i} className="discord-queue-item" title={track.title}>
                  <span className="discord-queue-index">{i + 1}</span>
                  <span className="discord-queue-title">{track.title}</span>
                </li>
              ))}
            </ul>
          )}
        </section>
      )}

      {/* Add to queue */}
      {selectedGuild && (
        <section className="discord-section">
          <h3>Add to Queue</h3>
          <form onSubmit={handlePlay} className="discord-play-form">
            <input
              type="url"
              className="discord-url-input"
              placeholder="YouTube / SoundCloud URL…"
              value={playUrl}
              onChange={(e) => {
                setPlayUrl(e.target.value);
                setPlayError(null);
              }}
            />
            <button
              type="submit"
              className="discord-btn-add"
              disabled={playLoading || !playUrl.trim()}
            >
              {playLoading ? "Adding…" : "Add"}
            </button>
          </form>
          {playError && <p className="discord-error">{playError}</p>}
        </section>
      )}
    </div>
  );
}
