
from tqdm import tqdm
import src.lyrics.lyrics as Lyrics

from Env import client_id, client_secret, local_library_path
from Env import work_dir

from src.Library import *
from src.LibrarySerializer import LibrarySaver, LibraryLoader

from src.backends.spotify.SpotifyWebAPI import fetch_all
from src.backends.spotify.ParseSpotify import Parser

from src.backends.local.LocalLibraryIndexer import update_local_library
from src.backends.local.ParseLocal import LocalParser
from src.backends.itunes.ParseItunesXml import ParseItunesXml


from src.mappers.RemoteLibraryResolver import resolve_remote_tracks
from src.StatGenerator import log_stats


class Flow:
    spotify_library : Library = None
    local_library : Library = None
    itunes_library : Library = None

    @staticmethod
    def fetch_spotify():
        fetch_all(client_id, client_secret, work_dir)

    @staticmethod
    def fetch_local():
        update_local_library(local_library_path, work_dir)

    @staticmethod
    def parse_spotify_library():
        parser = Parser()

        library_parsed = parser.parse(
            work_dir / "spotify" / "playlistTracks.json",
            work_dir / "spotify" / "tracks.json",
            work_dir / "spotify" / "top_tracks.json",
            work_dir / "spotify" / "top_artists.json",
        )

        LibrarySaver(library_parsed).save(work_dir / "spotify_library.json")

    @staticmethod
    def parse_itunes_library():
        parser = ParseItunesXml()

        library_parsed = parser.parse(
            work_dir / "itunes" / "Library.xml",
            work_dir / "itunes" / "Library.json"
        )

        LibrarySaver(library_parsed).save(work_dir / "itunes_library.json")

    @staticmethod
    def parse_local_library():
        parser = LocalParser()
        library_parsed = parser.parse(work_dir / "local" / "local_library.json")
        LibrarySaver(library_parsed).save(work_dir / "local_library.json")


    def fetch_and_save_lyrics(self):
        """
        Fetches and writes lyrics for tracks that don't have lyrics yet.
        Displays stats and uses a progress bar.
        """

        # ---------- Step 1: Collect tracks without lyrics ----------
        tracks_missing_lyrics = [
            track for track in self.local_library.tracks
            if len(track.artists) > 0 and not track.has_lyrics
        ]

        total_tracks = len(self.local_library.tracks)
        missing_count = len(tracks_missing_lyrics)

        print(f"[INFO] Total tracks in library: {total_tracks}")
        print(f"[INFO] Tracks missing lyrics: {missing_count}")

        if missing_count == 0:
            print("[INFO] No tracks need lyrics. Exiting.")
            return

        # ---------- Step 2: Fetch and write lyrics with progress bar ----------
        for track in tqdm(tracks_missing_lyrics, desc="Fetching lyrics", unit="track"):
            artist_name = track.artists[0].title
            album_title = track.album.title if track.album else "Unknown Album"
            print(f"\n[INFO] Processing: '{track.title}' by '{artist_name}' on '{album_title}'")

            lyrics_text = Lyrics.fetch_lyrics(artist_name, album_title, track.title, track.duration_ms)

            if lyrics_text:
                print("[SUCCESS] Lyrics found, writing to file...")
                file_path = local_library_path / track.local_path
                try:
                    Lyrics.write_lyrics(file_path, lyrics_text)
                    print(f"[SUCCESS] Lyrics written for '{track.title}'")
                except Exception as e:
                    print(f"[ERROR] Failed to write lyrics for '{track.title}': {e}")
            else:
                print(f"[WARNING] Lyrics not found for '{track.title}'")


    def load_libraries(self):
        self.spotify_library = LibraryLoader().load(work_dir / "spotify_library.json")
        self.itunes_library = LibraryLoader().load(work_dir / "itunes_library.json")
        self.local_library = LibraryLoader().load(work_dir / "local_library.json")

    def save_libraries(self):
        LibrarySaver(self.spotify_library).save(work_dir / "spotify_library.json")
        LibrarySaver(self.local_library).save(work_dir / "local_library.json")

    def map_local_to_spotify(self):
        resolve_remote_tracks(client_id, client_secret, self.local_library, self.spotify_library, work_dir)

    def log_stats(self):
        log_stats(work_dir / "remote_to_local_map.json", work_dir / "stats", self.local_library, self.spotify_library)


    def run(self, arg):
        self.fetch_local()
        # self.do_fetch_spotify()

        self.parse_local_library()
        self.parse_spotify_library()

        self.load_libraries()

        # self.map_local_to_spotify()

        return True