"use client";

import { useCallback, useEffect, useRef, useState } from "react";
import type { AudioTrack } from "@/types";
import { api } from "@/lib/api";

interface Props {
  pdfId: number;
  tracks: AudioTrack[];
  /** Called by parent after a successful upload so the track list refreshes */
  onTracksChange: (tracks: AudioTrack[]) => void;
  userRole: "admin" | "teacher" | "student";
}

function fmt(sec: number): string {
  if (!isFinite(sec)) return "0:00";
  const m = Math.floor(sec / 60);
  const s = Math.floor(sec % 60);
  return `${m}:${s.toString().padStart(2, "0")}`;
}

export default function FloatingAudioPlayer({ pdfId, tracks, onTracksChange, userRole }: Props) {
  const audioRef = useRef<HTMLAudioElement>(null);
  const [currentIdx, setCurrentIdx] = useState(0);
  const [isPlaying, setIsPlaying] = useState(false);
  const [currentTime, setCurrentTime] = useState(0);
  const [duration, setDuration] = useState(0);
  const [showPlaylist, setShowPlaylist] = useState(false);
  const [uploading, setUploading] = useState(false);
  const [deleting, setDeleting] = useState<number | null>(null);
  const fileInputRef = useRef<HTMLInputElement>(null);

  const canManage = userRole === "admin" || userRole === "teacher";
  const multiTrack = tracks.length > 1;
  const currentTrack = tracks[currentIdx] ?? null;
  const srcUrl = currentTrack ? api.audioFileUrl(pdfId, currentTrack.id) : null;

  // Sync audio element src when track changes
  useEffect(() => {
    const audio = audioRef.current;
    if (!audio || !srcUrl) return;
    audio.pause();
    audio.load();
    setIsPlaying(false);
    setCurrentTime(0);
    setDuration(0);
  }, [srcUrl]);

  const togglePlay = useCallback(async () => {
    const audio = audioRef.current;
    if (!audio) return;
    if (isPlaying) {
      audio.pause();
    } else {
      await audio.play().catch(() => {});
    }
  }, [isPlaying]);

  const rewind5 = useCallback(() => {
    const audio = audioRef.current;
    if (!audio) return;
    audio.currentTime = Math.max(0, audio.currentTime - 5);
  }, []);

  const handleSeek = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
    const audio = audioRef.current;
    if (!audio) return;
    audio.currentTime = Number(e.target.value);
  }, []);

  const handleTimeUpdate = useCallback(() => {
    setCurrentTime(audioRef.current?.currentTime ?? 0);
  }, []);

  const handleLoadedMetadata = useCallback(() => {
    setDuration(audioRef.current?.duration ?? 0);
  }, []);

  const handleEnded = useCallback(() => {
    if (multiTrack && currentIdx < tracks.length - 1) {
      setCurrentIdx((i) => i + 1);
    } else {
      setIsPlaying(false);
    }
  }, [multiTrack, currentIdx, tracks.length]);

  // Auto-play next track when index changes
  useEffect(() => {
    if (isPlaying) {
      audioRef.current?.play().catch(() => {});
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [currentIdx]);

  // File upload handler
  const handleFileUpload = useCallback(
    async (e: React.ChangeEvent<HTMLInputElement>) => {
      const files = Array.from(e.target.files ?? []);
      if (!files.length) return;
      setUploading(true);
      try {
        const meta = files.map((f, i) => ({
          trackName: f.name.replace(/\.[^.]+$/, ""),
          sortOrder: tracks.length + i + 1,
        }));
        const results = await api.uploadAudio(pdfId, files, meta);
        const newTracks = results.filter((r) => r.success && r.audio).map((r) => r.audio!);
        if (newTracks.length) {
          const updated = await api.listAudio(pdfId);
          onTracksChange(updated);
        }
        const errors = results.filter((r) => !r.success);
        if (errors.length) {
          alert(errors.map((r) => `${r.filename}: ${r.error}`).join("\n"));
        }
      } catch (err) {
        alert(err instanceof Error ? err.message : "Upload failed.");
      } finally {
        setUploading(false);
        if (fileInputRef.current) fileInputRef.current.value = "";
      }
    },
    [pdfId, tracks.length, onTracksChange],
  );

  const handleDelete = useCallback(
    async (trackId: number) => {
      if (!confirm("Xóa track này?")) return;
      setDeleting(trackId);
      try {
        await api.deleteAudio(pdfId, trackId);
        const updated = await api.listAudio(pdfId);
        onTracksChange(updated);
        if (currentTrack?.id === trackId) setCurrentIdx(0);
      } catch (err) {
        alert(err instanceof Error ? err.message : "Delete failed.");
      } finally {
        setDeleting(null);
      }
    },
    [pdfId, currentTrack, onTracksChange],
  );

  if (!tracks.length && !canManage) return null;

  return (
    <div
      style={{
        position: "fixed",
        bottom: 24,
        right: 24,
        zIndex: 1000,
        width: 340,
        background: "rgba(15, 23, 42, 0.96)",
        color: "#e2e8f0",
        borderRadius: 14,
        boxShadow: "0 8px 32px rgba(0,0,0,0.5)",
        padding: "12px 14px 10px",
        backdropFilter: "blur(8px)",
        userSelect: "none",
      }}
    >
      {/* Hidden native audio element */}
      {srcUrl && (
        <audio
          ref={audioRef}
          src={srcUrl}
          onPlay={() => setIsPlaying(true)}
          onPause={() => setIsPlaying(false)}
          onTimeUpdate={handleTimeUpdate}
          onLoadedMetadata={handleLoadedMetadata}
          onEnded={handleEnded}
          preload="metadata"
        />
      )}

      {/* Track name row */}
      <div style={{ display: "flex", alignItems: "center", gap: 6, marginBottom: 8 }}>
        <span style={{ fontSize: 13, fontWeight: 600, flex: 1, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
          {currentTrack ? currentTrack.track_name : "Chưa có audio"}
        </span>
        {multiTrack && (
          <button
            title="Playlist"
            onClick={() => setShowPlaylist((v) => !v)}
            style={iconBtn(showPlaylist ? "#3b82f6" : "#64748b")}
          >
            ☰
          </button>
        )}
        {canManage && (
          <>
            <button
              title="Tải lên audio"
              onClick={() => fileInputRef.current?.click()}
              disabled={uploading}
              style={iconBtn("#22c55e")}
            >
              {uploading ? "…" : "+"}
            </button>
            <input
              ref={fileInputRef}
              type="file"
              accept="audio/*"
              multiple
              style={{ display: "none" }}
              onChange={handleFileUpload}
            />
          </>
        )}
      </div>

      {/* Timeline */}
      <div style={{ display: "flex", alignItems: "center", gap: 6, marginBottom: 8 }}>
        <span style={{ fontSize: 10, minWidth: 32, textAlign: "right", color: "#94a3b8" }}>{fmt(currentTime)}</span>
        <input
          type="range"
          min={0}
          max={duration || 0}
          step={0.1}
          value={currentTime}
          onChange={handleSeek}
          disabled={!srcUrl}
          style={{ flex: 1, accentColor: "#3b82f6", cursor: srcUrl ? "pointer" : "not-allowed" }}
        />
        <span style={{ fontSize: 10, minWidth: 32, color: "#94a3b8" }}>{fmt(duration)}</span>
      </div>

      {/* Controls */}
      <div style={{ display: "flex", alignItems: "center", justifyContent: "center", gap: 10 }}>
        {multiTrack && (
          <button
            title="Bài trước"
            onClick={() => setCurrentIdx((i) => Math.max(0, i - 1))}
            disabled={currentIdx === 0}
            style={ctrlBtn(currentIdx === 0)}
          >
            ⏮
          </button>
        )}
        <button title="Tua lại 5 giây" onClick={rewind5} disabled={!srcUrl} style={ctrlBtn(!srcUrl)}>
          ⟲5
        </button>
        <button
          title={isPlaying ? "Tạm dừng" : "Phát"}
          onClick={togglePlay}
          disabled={!srcUrl}
          style={{
            ...ctrlBtn(!srcUrl),
            width: 40,
            height: 40,
            borderRadius: "50%",
            background: srcUrl ? "#3b82f6" : "#475569",
            fontSize: 18,
          }}
        >
          {isPlaying ? "⏸" : "▶"}
        </button>
        {multiTrack && (
          <button
            title="Bài tiếp"
            onClick={() => setCurrentIdx((i) => Math.min(tracks.length - 1, i + 1))}
            disabled={currentIdx === tracks.length - 1}
            style={ctrlBtn(currentIdx === tracks.length - 1)}
          >
            ⏭
          </button>
        )}
      </div>

      {/* Playlist drawer */}
      {showPlaylist && multiTrack && (
        <div
          style={{
            marginTop: 10,
            maxHeight: 200,
            overflowY: "auto",
            borderTop: "1px solid #1e293b",
            paddingTop: 8,
          }}
        >
          {tracks.map((t, i) => (
            <div
              key={t.id}
              style={{
                display: "flex",
                alignItems: "center",
                gap: 6,
                padding: "4px 2px",
                borderRadius: 6,
                background: i === currentIdx ? "rgba(59,130,246,0.18)" : "transparent",
                cursor: "pointer",
              }}
              onClick={() => {
                setCurrentIdx(i);
                setShowPlaylist(false);
              }}
            >
              <span style={{ fontSize: 11, color: i === currentIdx ? "#93c5fd" : "#94a3b8", minWidth: 16 }}>
                {i === currentIdx ? "▶" : `${i + 1}.`}
              </span>
              <span style={{ fontSize: 12, flex: 1, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
                {t.track_name}
                {t.page_number ? (
                  <span style={{ marginLeft: 4, fontSize: 10, color: "#64748b" }}>tr.{t.page_number}</span>
                ) : null}
              </span>
              {canManage && (
                <button
                  title="Xóa"
                  onClick={(e) => { e.stopPropagation(); handleDelete(t.id); }}
                  disabled={deleting === t.id}
                  style={{ background: "none", border: "none", color: "#f87171", cursor: "pointer", fontSize: 13, padding: "0 2px" }}
                >
                  ✕
                </button>
              )}
            </div>
          ))}
        </div>
      )}

      {/* Single track delete for admins/teachers */}
      {!multiTrack && currentTrack && canManage && (
        <div style={{ marginTop: 8, textAlign: "right" }}>
          <button
            onClick={() => handleDelete(currentTrack.id)}
            disabled={deleting === currentTrack.id}
            style={{ background: "none", border: "none", color: "#f87171", cursor: "pointer", fontSize: 11 }}
          >
            Xóa track
          </button>
        </div>
      )}
    </div>
  );
}

// ── Style helpers ─────────────────────────────────────────────────────────────

function iconBtn(color: string): React.CSSProperties {
  return {
    background: "none",
    border: "none",
    color,
    cursor: "pointer",
    fontSize: 16,
    padding: "2px 4px",
    lineHeight: 1,
  };
}

function ctrlBtn(disabled: boolean): React.CSSProperties {
  return {
    background: "none",
    border: "none",
    color: disabled ? "#475569" : "#e2e8f0",
    cursor: disabled ? "not-allowed" : "pointer",
    fontSize: 20,
    padding: "2px 4px",
    lineHeight: 1,
    width: 32,
    height: 32,
    borderRadius: 6,
  };
}
