// ── Built-in tracks bundled with the app ───────────────────────────────────
const BUILT_IN_TRACKS = [
  {
    id: "builtin-story-ambience",
    name: "Story Ambience",
    filename: "story_ambience.mp3",
    description: "Soft, dreamy background — currently the default",
    url: "/dashboard/audio/story_ambience.mp3",
    isBuiltIn: true,
    enabled: true,
    size: 4506624,
  },
  {
    id: "builtin-background-loop",
    name: "Background Loop",
    filename: "background_loop.mp3",
    description: "Gentle loop track, alternates with Story Ambience when randomized",
    url: "/dashboard/audio/background_loop.mp3",
    isBuiltIn: true,
    enabled: true,
    size: 1153024,
  },
];

function PageMusic() {
  const [tracks, setTracks]             = React.useState([]);
  const [loading, setLoading]           = React.useState(true);
  const [uploading, setUploading]       = React.useState(false);
  const [uploadProgress, setUploadProgress] = React.useState(0);
  const [playingId, setPlayingId]       = React.useState(null);
  const [durations, setDurations]       = React.useState({}); // id → seconds
  const [dragOver, setDragOver]         = React.useState(false);
  const audioRef   = React.useRef(null);
  const fileInputRef = React.useRef(null);

  // ── Load uploaded tracks from Firestore ─────────────────────────────────
  React.useEffect(() => {
    const db = window.__db;
    const fs = window.__fs;
    if (!db || !fs) { setLoading(false); return; }
    const q = fs.query(
      fs.collection(db, "music_tracks"),
      fs.orderBy("uploadedAt", "desc")
    );
    const unsub = fs.onSnapshot(q, snap => {
      setTracks(snap.docs.map(d => ({ id: d.id, ...d.data() })));
      setLoading(false);
    }, () => setLoading(false));
    return unsub;
  }, []);

  // Pre-load durations for all tracks that have a URL
  React.useEffect(() => {
    [...BUILT_IN_TRACKS, ...tracks].forEach(track => {
      if (!track.url || durations[track.id] != null) return;
      const a = new Audio();
      a.preload = "metadata";
      a.onloadedmetadata = () => {
        if (isFinite(a.duration)) {
          setDurations(d => ({ ...d, [track.id]: Math.round(a.duration) }));
        }
      };
      a.src = track.url;
    });
  }, [tracks]); // eslint-disable-line

  // ── Audio preview ────────────────────────────────────────────────────────
  function togglePlay(track) {
    if (!track.url) return;
    if (playingId === track.id) {
      audioRef.current?.pause();
      setPlayingId(null);
      return;
    }
    if (!audioRef.current) {
      audioRef.current = new Audio();
      audioRef.current.onended = () => setPlayingId(null);
    }
    audioRef.current.pause();
    audioRef.current.src = track.url;
    audioRef.current.play().catch(() => {});
    setPlayingId(track.id);
  }

  // Stop audio when component unmounts
  React.useEffect(() => () => audioRef.current?.pause(), []);

  // ── Upload ───────────────────────────────────────────────────────────────
  async function handleUpload(file) {
    if (!file) return;
    if (!file.name.match(/\.mp3$/i) && file.type !== "audio/mpeg") {
      alert("Only MP3 files are supported.");
      return;
    }
    if (file.size > 50 * 1024 * 1024) {
      alert("File is too large. Maximum size is 50 MB.");
      return;
    }

    setUploading(true);
    setUploadProgress(0);

    try {
      const { ref, uploadBytesResumable, getDownloadURL } = window.__storageUtils;
      const storage = window.__storage;
      const sanitized = file.name.replace(/[^a-zA-Z0-9._-]/g, "_");
      const filename  = `${Date.now()}_${sanitized}`;
      const storageRef = ref(storage, `music/${filename}`);
      const uploadTask = uploadBytesResumable(storageRef, file, { contentType: "audio/mpeg" });

      await new Promise((resolve, reject) => {
        uploadTask.on(
          "state_changed",
          snap => setUploadProgress(Math.round((snap.bytesTransferred / snap.totalBytes) * 100)),
          reject,
          resolve
        );
      });

      const url = await getDownloadURL(uploadTask.snapshot.ref);

      const db = window.__db;
      const fs = window.__fs;
      const trackName = file.name
        .replace(/\.mp3$/i, "")
        .replace(/[_-]/g, " ")
        .replace(/\b\w/g, c => c.toUpperCase());

      try {
        await fs.addDoc(fs.collection(db, "music_tracks"), {
          name: trackName,
          filename,
          url,
          enabled: true,
          isBuiltIn: false,
          size: file.size,
          uploadedAt: fs.serverTimestamp(),
          uploadedBy: window.__auth?.currentUser?.email || "admin",
        });
      } catch (e) {
        alert("File uploaded to Storage but failed to save metadata: " + (e.message || String(e)));
        return;
      }

      if (fileInputRef.current) fileInputRef.current.value = "";
    } catch (e) {
      alert("Upload failed: " + (e.message || String(e)));
    } finally {
      setUploading(false);
      setUploadProgress(0);
    }
  }

  // ── Enable / disable ─────────────────────────────────────────────────────
  async function toggleEnabled(track) {
    const db = window.__db;
    const fs = window.__fs;
    await fs.updateDoc(fs.doc(db, "music_tracks", track.id), { enabled: !track.enabled });
  }

  // ── Delete ───────────────────────────────────────────────────────────────
  async function deleteTrack(track) {
    if (!confirm(`Delete "${track.name}"? This cannot be undone.`)) return;
    const db = window.__db;
    const fs = window.__fs;
    try {
      const { ref, deleteObject } = window.__storageUtils;
      await deleteObject(ref(window.__storage, `music/${track.filename}`));
    } catch (_) { /* storage file may already be gone */ }
    await fs.deleteDoc(fs.doc(db, "music_tracks", track.id));
    if (playingId === track.id) { audioRef.current?.pause(); setPlayingId(null); }
  }

  const allTracks    = [...BUILT_IN_TRACKS, ...tracks];
  const enabledCount = BUILT_IN_TRACKS.length + tracks.filter(t => t.enabled).length;

  return (
    <>
      <div className="page-header">
        <div>
          <h1>Background Music</h1>
          <div className="sub">{enabledCount} track{enabledCount !== 1 ? "s" : ""} active · randomly picked for each story session</div>
        </div>
        <div className="actions">
          <input
            ref={fileInputRef}
            type="file"
            accept=".mp3,audio/mpeg"
            style={{ display: "none" }}
            onChange={e => e.target.files[0] && handleUpload(e.target.files[0])}
          />
          <button
            className="btn primary sm"
            onClick={() => fileInputRef.current?.click()}
            disabled={uploading}
          >
            <Icon.upload size={12}/>
            {uploading ? `Uploading ${uploadProgress}%…` : "Upload MP3"}
          </button>
        </div>
      </div>

      {/* How it works */}
      <div style={{
        display: "flex", alignItems: "flex-start", gap: 12,
        padding: "14px 16px", marginBottom: 20,
        background: "var(--accent-soft)", border: "1px solid var(--accent)",
        borderRadius: 10, fontSize: 13, color: "var(--ink-2)",
      }}>
        <Icon.music size={16} style={{ color: "var(--accent)", flexShrink: 0, marginTop: 1 }}/>
        <span>
          Every time a child opens a story, the app randomly picks one of the enabled tracks.
          Built-in tracks are always included. Uploaded tracks extend the pool — the more you add,
          the more variety kids experience.
        </span>
      </div>

      {/* Upload progress bar */}
      {uploading && (
        <div style={{ marginBottom: 16 }}>
          <div style={{ height: 6, background: "var(--border)", borderRadius: 3, overflow: "hidden" }}>
            <div style={{
              height: "100%", width: `${uploadProgress}%`,
              background: "var(--accent)", borderRadius: 3,
              transition: "width .25s ease",
            }}/>
          </div>
          <div style={{ fontSize: 11, color: "var(--ink-3)", marginTop: 5 }}>
            Uploading to Firebase Storage… {uploadProgress}%
          </div>
        </div>
      )}

      {/* Track list */}
      <div className="card" style={{ marginBottom: 16 }}>
        <div style={{
          padding: "10px 14px",
          borderBottom: "1px solid var(--border)",
          fontSize: 11, fontWeight: 700,
          color: "var(--ink-3)",
          textTransform: "uppercase",
          letterSpacing: ".06em",
          display: "flex", alignItems: "center", gap: 8,
        }}>
          <Icon.music size={12}/> All Tracks ({allTracks.length})
        </div>

        {loading ? (
          <div style={{ padding: 32, textAlign: "center", color: "var(--ink-3)", fontSize: 13 }}>
            <span className="pulse" style={{ width: 8, height: 8, borderRadius: "50%", background: "var(--accent)", display: "inline-block", marginRight: 8 }}/>
            Loading tracks…
          </div>
        ) : (
          allTracks.map(track => (
            <TrackRow
              key={track.id}
              track={track}
              isPlaying={playingId === track.id}
              duration={durations[track.id]}
              onPlay={() => togglePlay(track)}
              onToggle={() => toggleEnabled(track)}
              onDelete={() => deleteTrack(track)}
            />
          ))
        )}
      </div>

      {/* Drag-and-drop zone */}
      <MusicDropZone
        dragging={dragOver}
        onDragOver={() => setDragOver(true)}
        onDragLeave={() => setDragOver(false)}
        onDrop={file => { setDragOver(false); handleUpload(file); }}
        onClick={() => fileInputRef.current?.click()}
        uploading={uploading}
      />
    </>
  );
}

// ── Track row ──────────────────────────────────────────────────────────────
function TrackRow({ track, isPlaying, duration, onPlay, onToggle, onDelete }) {
  const fmtSize = b => {
    if (b == null) return null;
    return b > 1_000_000 ? `${(b / 1_000_000).toFixed(1)} MB` : `${Math.round(b / 1024)} KB`;
  };
  const fmtDuration = s => {
    if (s == null) return null;
    const m = Math.floor(s / 60);
    const sec = String(s % 60).padStart(2, "0");
    return `${m}:${sec}`;
  };

  const size = fmtSize(track.size);
  const dur  = fmtDuration(duration);

  return (
    <div style={{
      display: "flex", alignItems: "center", gap: 12,
      padding: "12px 14px",
      borderBottom: "1px solid var(--border)",
    }}
      onMouseEnter={e => e.currentTarget.style.background = "var(--bg-soft)"}
      onMouseLeave={e => e.currentTarget.style.background = ""}
    >
      {/* Play / preview button */}
      <button
        className="btn ghost icon sm"
        onClick={onPlay}
        title={isPlaying ? "Pause preview" : "Play preview"}
        style={{ flexShrink: 0, color: isPlaying ? "var(--accent)" : undefined }}
      >
        {isPlaying ? <Icon.pause size={14}/> : <Icon.play size={14}/>}
      </button>

      {/* Info */}
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontWeight: 600, fontSize: 13, display: "flex", alignItems: "center", gap: 7 }}>
          {track.name}
          {track.isBuiltIn && <span className="badge">Built-in</span>}
          {!track.isBuiltIn && !track.enabled && <span className="badge" style={{ color: "var(--ink-4)" }}>Disabled</span>}
        </div>
        <div style={{ fontSize: 11, color: "var(--ink-3)", marginTop: 2 }}>
          {track.description || track.filename}
          {!track.isBuiltIn && track.uploadedBy && ` · by ${track.uploadedBy}`}
          {!track.isBuiltIn && track.uploadedAt && ` · ${fmtRelative(track.uploadedAt?.toDate?.()?.toISOString())}`}
        </div>
      </div>

      {/* Duration + size chips */}
      <div style={{ display: "flex", gap: 6, flexShrink: 0 }}>
        {dur  && <span className="badge" style={{ fontFamily: "var(--mono)", fontSize: 11 }}>⏱ {dur}</span>}
        {size && <span className="badge" style={{ fontFamily: "var(--mono)", fontSize: 11 }}>{size}</span>}
      </div>

      {/* Animated wave bars */}
      <div className={`wave-bars${isPlaying ? " active" : ""}`}>
        <span/><span/><span/><span/><span/>
      </div>

      {/* Delete — only for uploaded tracks */}
      {!track.isBuiltIn && (
        <button
          className="btn danger sm"
          onClick={onDelete}
          title="Delete track"
          style={{ flexShrink: 0 }}
        >
          <Icon.trash size={12}/> Delete
        </button>
      )}

      {/* Enabled toggle — rightmost, only for uploaded tracks */}
      {!track.isBuiltIn && (
        <label style={{ display: "flex", alignItems: "center", gap: 6, cursor: "pointer", fontSize: 12, color: "var(--ink-2)", flexShrink: 0, minWidth: 56 }}>
          <Switch on={track.enabled} onChange={onToggle}/>
          <span style={{ color: track.enabled ? "var(--green, #22c55e)" : "var(--ink-4)", fontWeight: 600 }}>
            {track.enabled ? "On" : "Off"}
          </span>
        </label>
      )}
    </div>
  );
}

// ── Drag-and-drop upload zone ──────────────────────────────────────────────
function MusicDropZone({ dragging, onDragOver, onDragLeave, onDrop, onClick, uploading }) {
  return (
    <div
      className={`music-drop${dragging ? " drag-over" : ""}`}
      onDragOver={e => { e.preventDefault(); onDragOver(); }}
      onDragLeave={onDragLeave}
      onDrop={e => { e.preventDefault(); onDrop(e.dataTransfer.files[0]); }}
      onClick={onClick}
    >
      <Icon.upload size={22} style={{ marginBottom: 10, opacity: .5, display: "block", margin: "0 auto 10px" }}/>
      <div style={{ fontWeight: 600 }}>
        {uploading ? "Upload in progress…" : "Drag & drop an MP3 here"}
      </div>
      <div style={{ fontSize: 11, marginTop: 4, opacity: .7 }}>
        or click to browse · MP3 only · max 50 MB
      </div>
    </div>
  );
}

Object.assign(window, { PageMusic });
