import { useEffect, useState } from "react";
import { Link, useParams, useLocation } from "react-router-dom";
import { api } from "../services/api";

export default function AlbumTracksPage() {
  const { albumId } = useParams();
  const location = useLocation();
  const defaultArtistId = location.state?.artistId || null;
  const defaultGenreIds = location.state?.genreIds || [];

  const [album, setAlbum] = useState(null);
  const [loading, setLoading] = useState(true);

  const [artists, setArtists] = useState([]);
  const [genres, setGenres] = useState([]);

  const [albumForm, setAlbumForm] = useState({
    title: "",
    type: "album",
    releaseDate: "",
    artistId: "",
    newArtist: "",
    genreIds: [],
    newGenre: "",
  });
  const [albumDirty, setAlbumDirty] = useState(false);
  const [savingAlbum, setSavingAlbum] = useState(false);

  const [selectedFile, setSelectedFile] = useState(null);
  const [newTrackName, setNewTrackName] = useState("");
  const [newTrackDuration, setNewTrackDuration] = useState(null);
  const [submitting, setSubmitting] = useState(false);

  async function loadAlbum() {
    setLoading(true);
    try {
      const data = await api.getAlbumById(albumId);
      setAlbum(data);

      const albumArtist = data.artist;
      const albumGenres = data.genres || [];

      setAlbumForm({
        title: data.title || "",
        type: data.type || "album",
        releaseDate: data.release_date ? data.release_date.slice(0, 10) : "",
        artistId: albumArtist ? String(albumArtist.id) : "",
        newArtist: "",
        genreIds: albumGenres.map((g) => String(g.id)),
        newGenre: "",
      });
      setAlbumDirty(false);
    } catch (err) {
      console.error("Failed to load album:", err);
    }
    setLoading(false);
  }

  async function loadArtists() {
    try {
      const data = await api.getArtists();
      setArtists(data);
    } catch (err) {
      console.error("Failed to load artists:", err);
    }
  }

  async function loadGenres() {
    try {
      const data = await api.getGenres();
      setGenres(data);
    } catch (err) {
      console.error("Failed to load genres:", err);
    }
  }

  useEffect(() => {
    loadAlbum();
    loadArtists();
    loadGenres();
  }, [albumId]);

  function onPickFile(e) {
    const file = e.target.files?.[0] || null;
    setSelectedFile(file);
    setNewTrackDuration(null);
    if (file) {
      setNewTrackName(file.name.replace(/\.[^/.]+$/, ""));
      const url = URL.createObjectURL(file);
      const audio = new Audio(url);
      audio.addEventListener("loadedmetadata", () => {
        setNewTrackDuration(Math.round(audio.duration));
        URL.revokeObjectURL(url);
      });
    }
  }

  async function onSaveAlbum(e) {
    e.preventDefault();
    setSavingAlbum(true);
    try {
      let artistId = albumForm.artistId ? Number(albumForm.artistId) : null;

      if (!artistId && albumForm.newArtist.trim()) {
        const created = await api.addArtist({ name: albumForm.newArtist.trim() });
        artistId = created.id;
        await loadArtists();
      }

      let genreIds = albumForm.genreIds.map(Number);

      if (albumForm.newGenre.trim()) {
        const created = await api.addGenre({ name: albumForm.newGenre.trim() });
        genreIds.push(created.id);
        await loadGenres();
      }

      const payload = {
        title: albumForm.title,
        type: albumForm.type,
        release_date: albumForm.releaseDate || null,
        genre_ids: genreIds,
      };
      if (artistId) payload.artist_id = artistId;

      await api.updateAlbum(albumId, payload);

      setAlbumDirty(false);
      setAlbumForm((prev) => ({ ...prev, newArtist: "", newGenre: "" }));
      await loadAlbum();
    } catch (err) {
      console.error("Failed to save album:", err);
    }
    setSavingAlbum(false);
  }

  async function onAddTrack(e) {
    e.preventDefault();
    if (!selectedFile || !newTrackName.trim()) return;

    setSubmitting(true);
    try {
      const uploaded = await api.uploadAudio(selectedFile);
      const tracks = album.tracks || [];

      const artistId = albumForm.artistId ? Number(albumForm.artistId) : defaultArtistId;
      const genreIds = albumForm.genreIds.length > 0
        ? albumForm.genreIds.map(Number)
        : defaultGenreIds.map(Number);

      const payload = {
        title: newTrackName.trim(),
        file_path: uploaded.path,
        album_id: Number(albumId),
        position: tracks.length,
        duration_seconds: newTrackDuration,
      };

      if (artistId) payload.artist_ids = [artistId];
      if (genreIds.length > 0) payload.genre_ids = genreIds;

      await api.addTrack(payload);

      setSelectedFile(null);
      setNewTrackName("");
      setNewTrackDuration(null);
      await loadAlbum();
    } catch (err) {
      console.error("Failed to add track:", err);
    }
    setSubmitting(false);
  }

  async function onEditTrack(trackId, title) {
    if (!title.trim()) return;
    try {
      await api.updateTrack(trackId, { title: title.trim() });
      await loadAlbum();
    } catch (err) {
      console.error("Failed to update track:", err);
    }
  }

  async function onDeleteTrack(trackId) {
    if (!confirm("Delete this track?")) return;
    try {
      await api.deleteTrack(trackId);
      await loadAlbum();
    } catch (err) {
      console.error("Failed to delete track:", err);
    }
  }

  async function onMove(trackId, direction) {
    const tracks = [...(album.tracks || [])].sort((a, b) => a.position - b.position);
    const index = tracks.findIndex((t) => t.id === trackId);
    if (index === -1) return;

    const targetIndex = direction === "up" ? index - 1 : index + 1;
    if (targetIndex < 0 || targetIndex >= tracks.length) return;

    const temp = tracks[index].position;
    tracks[index].position = tracks[targetIndex].position;
    tracks[targetIndex].position = temp;

    const positions = tracks.map((t) => ({ id: t.id, position: t.position }));

    try {
      await api.reorderTracks(albumId, positions);
      await loadAlbum();
    } catch (err) {
      console.error("Failed to reorder tracks:", err);
    }
  }

  if (loading) return <p>Loading...</p>;
  if (!album) return <p>Album not found.</p>;

  const sortedTracks = [...(album.tracks || [])].sort((a, b) => a.position - b.position);

  function markDirty() {
    setAlbumDirty(true);
  }

  return (
    <section>
      <div style={{ marginBottom: 12 }}>
        <Link to="/albums" className="tab">← Back to Albums</Link>
      </div>

      <form className="card form" onSubmit={onSaveAlbum}>
        <h3>Album Details</h3>
        <div className="grid">
          <input
            placeholder="Album title"
            value={albumForm.title}
            onChange={(e) => { setAlbumForm({ ...albumForm, title: e.target.value }); markDirty(); }}
          />
          <select
            value={albumForm.type}
            onChange={(e) => { setAlbumForm({ ...albumForm, type: e.target.value }); markDirty(); }}
          >
            <option value="album">Album</option>
            <option value="single">Single</option>
            <option value="ep">EP</option>
          </select>
          <input
            type="date"
            value={albumForm.releaseDate}
            onChange={(e) => { setAlbumForm({ ...albumForm, releaseDate: e.target.value }); markDirty(); }}
          />
        </div>

        <div className="grid">
          <select
            value={albumForm.artistId}
            onChange={(e) => { setAlbumForm({ ...albumForm, artistId: e.target.value, newArtist: "" }); markDirty(); }}
          >
            <option value="">Select existing artist...</option>
            {artists.map((a) => (
              <option key={a.id} value={a.id}>{a.name}</option>
            ))}
          </select>
          <input
            placeholder="...or type a new artist name"
            value={albumForm.newArtist}
            onChange={(e) => { setAlbumForm({ ...albumForm, newArtist: e.target.value, artistId: "" }); markDirty(); }}
            disabled={!!albumForm.artistId}
          />
        </div>

        <div className="grid">
          <select
            multiple
            value={albumForm.genreIds}
            onChange={(e) => {
              setAlbumForm({
                ...albumForm,
                genreIds: Array.from(e.target.selectedOptions, (o) => o.value),
              });
              markDirty();
            }}
          >
            {genres.map((g) => (
              <option key={g.id} value={g.id}>{g.name}</option>
            ))}
          </select>
          <input
            placeholder="...or type a new genre"
            value={albumForm.newGenre}
            onChange={(e) => { setAlbumForm({ ...albumForm, newGenre: e.target.value }); markDirty(); }}
          />
        </div>

        <button className="btn primary" type="submit" disabled={!albumDirty || savingAlbum}>
          {savingAlbum ? "Saving..." : "Save Album Details"}
        </button>
      </form>

      <form className="card form" onSubmit={onAddTrack}>
        <h3>Add Track</h3>

        <label className="fileLabel">
          Select audio file
          <input
            type="file"
            accept=".mp3,.wav,.flac,audio/*"
            onChange={onPickFile}
          />
        </label>

        <input
          placeholder="Track name"
          value={newTrackName}
          onChange={(e) => setNewTrackName(e.target.value)}
        />

        <div style={{ marginTop: 10 }}>
          <button className="btn primary" type="submit" disabled={submitting || !selectedFile || !newTrackName.trim()}>
            {submitting ? "Adding..." : "Add Track"}
          </button>
        </div>
      </form>

      <div className="list">
        {sortedTracks.length === 0 ? (
          <p>No tracks yet.</p>
        ) : (
          sortedTracks.map((track, index) => (
            <TrackRow
              key={track.id}
              track={track}
              index={index}
              total={sortedTracks.length}
              onEdit={onEditTrack}
              onDelete={onDeleteTrack}
              onMove={onMove}
            />
          ))
        )}
      </div>
    </section>
  );
}

function TrackRow({ track, index, total, onEdit, onDelete, onMove }) {
  const [name, setName] = useState(track.title);

  useEffect(() => {
    setName(track.title);
  }, [track.title]);

  const artistStr = (track.artists || []).map((a) => a.name).join(", ");
  const genreStr = (track.genres || []).map((g) => g.name).join(", ");

  return (
    <div className="card row">
      <div style={{ flex: 1, textAlign: "left" }}>
        <div className="muted">#{index + 1}</div>
        <input
          value={name}
          onChange={(e) => setName(e.target.value)}
          placeholder="Track name"
        />
        {artistStr && <div className="muted">{artistStr}</div>}
        {genreStr && <div className="muted">{genreStr}</div>}
      </div>

      <div className="actions">
        <button
          type="button"
          className="btn secondary"
          onClick={() => onMove(track.id, "up")}
          disabled={index === 0}
        >
          Move up
        </button>
        <button
          type="button"
          className="btn secondary"
          onClick={() => onMove(track.id, "down")}
          disabled={index === total - 1}
        >
          Move down
        </button>
        <button type="button" className="btn primary" onClick={() => onEdit(track.id, name)}>
          Save
        </button>
        <button type="button" className="btn danger" onClick={() => onDelete(track.id)}>
          Delete
        </button>
      </div>
    </div>
  );
}
