import { useEffect, useState } from "react";
import { apiGet } from "../../api";
import { Empty, Loading, PageHead, StatCard, fmtDuration, fmtNumber } from "../../components/ui";
import { IconCalendar, IconDisc, IconMusic, IconPlay, IconRefresh, IconUser } from "../../components/icons";
import { useToast } from "../../lib/toast";

interface Album {
  id: string;
  name: string;
  artist: string;
  year?: number;
  song_count: number;
  duration: number;
  cover_url: string | null;
}

interface Song {
  id: string;
  title: string;
  artist: string;
  album: string;
  year?: number;
  duration: number;
  play_count: number;
  created?: string | null;
  cover_url?: string | null;
}

interface Genre {
  name: string;
  song_count: number;
  album_count: number;
}

interface ReportingData {
  summary: {
    artist_count: number;
    album_count: number;
    song_count: number;
    genre_count: number;
    library_tracks_scanned: number;
    tracks_with_plays: number;
    total_play_count: number;
    favorite_song_count: number;
    favorite_album_count: number;
    favorite_artist_count: number;
    now_playing_count: number;
    scan_pages: number;
    truncated: boolean;
  };
  top_tracks: Song[];
  favorite_tracks: Song[];
  recently_added_tracks: Song[];
  top_albums: Album[];
  recent_albums: Album[];
  newest_albums: Album[];
  top_genres: Genre[];
  now_playing: Song[];
}

function AlbumStrip({ title, items }: { title: string; items: Album[] }) {
  return (
    <div className="panel">
      <div className="panel-head">
        <h3>{title}</h3>
        <span className="sub">{items.length}</span>
      </div>
      {items.length === 0 ? (
        <Empty icon={<IconDisc />}>No albums available.</Empty>
      ) : (
        <div className="card-grid" style={{ gridTemplateColumns: "repeat(auto-fill, minmax(180px, 1fr))", padding: 18 }}>
          {items.map((a) => (
            <div key={a.id} className="media-card" style={{ cursor: "default" }}>
              {a.cover_url ? (
                <img className="media-cover" src={`${a.cover_url}?size=300`} loading="lazy" alt={a.name} />
              ) : (
                <div className="media-cover" style={{ display: "grid", placeItems: "center" }}>
                  <IconDisc className="dim" />
                </div>
              )}
              <div className="media-body">
                <div className="media-title">{a.name}</div>
                <div className="media-sub">
                  {a.artist}
                  {a.year ? ` · ${a.year}` : ""}
                </div>
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

function SongTable({ title, songs, secondary = "plays" }: { title: string; songs: Song[]; secondary?: "plays" | "added" }) {
  return (
    <div className="panel">
      <div className="panel-head">
        <h3>{title}</h3>
        <span className="sub">{songs.length}</span>
      </div>
      {songs.length === 0 ? (
        <Empty icon={<IconMusic />}>No tracks available.</Empty>
      ) : (
        <div style={{ overflowX: "auto" }}>
          <table className="data-table">
            <thead>
              <tr>
                <th>Track</th>
                <th>Artist</th>
                <th>Album</th>
                <th>Length</th>
                <th>{secondary === "plays" ? "Plays" : "Added"}</th>
              </tr>
            </thead>
            <tbody>
              {songs.map((song) => (
                <tr key={song.id}>
                  <td className="cell-strong">{song.title}</td>
                  <td>{song.artist || "—"}</td>
                  <td className="cell-sub">{song.album || "—"}</td>
                  <td className="mono">{fmtDuration(song.duration)}</td>
                  <td className="mono">{secondary === "plays" ? fmtNumber(song.play_count) : song.created || "—"}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
}

export default function Reporting() {
  const toast = useToast();
  const [status, setStatus] = useState<{ connected: boolean; configured: boolean; error?: string } | null>(null);
  const [data, setData] = useState<ReportingData | null>(null);
  const [loading, setLoading] = useState(true);
  const [refreshing, setRefreshing] = useState(false);

  useEffect(() => {
    apiGet("/api/navidrome/status").then(setStatus).catch(() => setStatus({ connected: false, configured: false }));
  }, []);

  async function load(refresh = false) {
    refresh ? setRefreshing(true) : setLoading(true);
    try {
      const result = await apiGet<ReportingData>(`/api/navidrome/reporting${refresh ? "?refresh=true" : ""}`);
      setData(result);
    } catch (e: any) {
      toast(e.message, "err");
      setData(null);
    } finally {
      setLoading(false);
      setRefreshing(false);
    }
  }

  useEffect(() => {
    if (status?.connected) load();
  }, [status?.connected]); // eslint-disable-line react-hooks/exhaustive-deps

  if (status && !status.configured) {
    return (
      <>
        <PageHead title="Reporting" icon={<IconDisc />} />
        <div className="panel">
          <Empty icon={<IconMusic />}>Navidrome is not configured yet.</Empty>
        </div>
      </>
    );
  }

  if (status && status.configured && !status.connected) {
    return (
      <>
        <PageHead title="Reporting" icon={<IconDisc />} />
        <div className="panel">
          <Empty icon={<IconMusic />}>Could not connect to Navidrome. {status.error}</Empty>
        </div>
      </>
    );
  }

  return (
    <>
      <div className="row between" style={{ alignItems: "flex-start" }}>
        <PageHead title="Reporting" icon={<IconDisc />} />
        <button className="btn btn-sm" onClick={() => load(true)} disabled={refreshing || loading}>
          {refreshing ? <span className="spinner" /> : <IconRefresh />} Refresh
        </button>
      </div>

      {loading && !data ? (
        <Loading label="Loading Navidrome reporting…" />
      ) : !data ? (
        <div className="panel">
          <Empty icon={<IconMusic />}>No reporting data available.</Empty>
        </div>
      ) : (
        <>
          <div className="stat-row" style={{ marginBottom: 18 }}>
            <StatCard icon={<IconPlay />} value={fmtNumber(data.summary.total_play_count)} label="Total plays" />
            <StatCard icon={<IconMusic />} value={fmtNumber(data.summary.tracks_with_plays)} label="Tracks with plays" />
            <StatCard icon={<IconDisc />} value={fmtNumber(data.summary.favorite_song_count)} label="Starred songs" />
            <StatCard icon={<IconUser />} value={fmtNumber(data.summary.now_playing_count)} label="Now playing" />
          </div>

          <div className="stat-row" style={{ marginBottom: 24 }}>
            <StatCard icon={<IconUser />} value={fmtNumber(data.summary.artist_count)} label="Artists" />
            <StatCard icon={<IconDisc />} value={fmtNumber(data.summary.album_count)} label="Albums" />
            <StatCard icon={<IconMusic />} value={fmtNumber(data.summary.song_count)} label="Tracks" />
            <StatCard icon={<IconCalendar />} value={fmtNumber(data.summary.library_tracks_scanned)} label="Tracks scanned" />
          </div>

          <div className="panel" style={{ marginBottom: 24 }}>
            <div className="panel-head">
              <h3>Scan notes</h3>
            </div>
            <div className="panel-body">
              <div className="row gap-sm wrap">
                <span className="badge">{fmtNumber(data.summary.scan_pages)} page(s) scanned</span>
                {data.summary.truncated ? <span className="badge badge-warn">results truncated by safety cap</span> : <span className="badge badge-ok">full library sampled</span>}
                <span className="badge">{fmtNumber(data.summary.favorite_album_count)} starred albums</span>
                <span className="badge">{fmtNumber(data.summary.favorite_artist_count)} starred artists</span>
              </div>
              <p className="hint" style={{ marginTop: 12, marginBottom: 0 }}>
                Play counts and starred state are specific to the authenticated Navidrome user because they come from the Subsonic-compatible API.
              </p>
            </div>
          </div>

          <div className="dash-split" style={{ marginBottom: 24 }}>
            <SongTable title="Top Tracks" songs={data.top_tracks} />
            <SongTable title="Starred Tracks" songs={data.favorite_tracks} />
          </div>

          <div className="dash-split" style={{ marginBottom: 24 }}>
            <SongTable title="Recently Added Tracks" songs={data.recently_added_tracks} secondary="added" />
            <div className="panel">
              <div className="panel-head">
                <h3>Top Genres</h3>
                <span className="sub">{data.top_genres.length}</span>
              </div>
              <div className="panel-body">
                {data.top_genres.length === 0 ? (
                  <Empty icon={<IconDisc />}>No genre data.</Empty>
                ) : (
                  data.top_genres.map((genre) => (
                    <div key={genre.name} className="genre-row">
                      <span className="genre-name">{genre.name}</span>
                      <span className="genre-bar">
                        <span
                          className="genre-bar-fill"
                          style={{
                            width: `${(genre.song_count / Math.max(...data.top_genres.map((g) => g.song_count), 1)) * 100}%`,
                          }}
                        />
                      </span>
                      <span className="genre-count">{fmtNumber(genre.song_count)}</span>
                    </div>
                  ))
                )}
              </div>
            </div>
          </div>

          <AlbumStrip title="Most Played Albums" items={data.top_albums} />
          <div style={{ height: 18 }} />
          <AlbumStrip title="Recently Played Albums" items={data.recent_albums} />
          <div style={{ height: 18 }} />
          <AlbumStrip title="Newest Albums" items={data.newest_albums} />

          <div style={{ height: 18 }} />
          <SongTable title="Now Playing" songs={data.now_playing} secondary="added" />
        </>
      )}
    </>
  );
}
