#!/usr/bin/env python3
import sys
import time
import requests
from io import BytesIO
from PIL import Image
from api.auth import get_spotify_client
from rich.console import Console
from rich.panel import Panel
from rich.table import Table
from rich.text import Text
from rich import box
from rich.layout import Layout
from rich.live import Live


def get_user_playlists(spotify_client):
    playlists = []
    results = spotify_client.current_user_playlists(limit=50)

    while results:
        playlists.extend(results["items"])
        if results["next"]:
            results = spotify_client.next(results)
        else:
            break

    return playlists


def format_duration(ms):
    """Convert milliseconds to MM:SS format"""
    seconds = ms // 1000
    minutes = seconds // 60
    seconds = seconds % 60
    return f"{minutes}:{seconds:02d}"


def get_current_playback(spotify):
    """Get currently playing track information"""
    try:
        playback = spotify.current_playback()
        if playback and playback.get("item"):
            track = playback["item"]
            artists = ", ".join([artist["name"] for artist in track.get("artists", [])])

            # Get album art URL (smallest size for terminal)
            album_images = track.get("album", {}).get("images", [])
            album_art_url = album_images[-1]["url"] if album_images else None  # Get smallest image

            return {
                "name": track.get("name", "Unknown"),
                "artists": artists,
                "album": track.get("album", {}).get("name", "Unknown"),
                "progress": playback.get("progress_ms", 0),
                "duration": track.get("duration_ms", 0),
                "is_playing": playback.get("is_playing", False),
                "album_art_url": album_art_url,
                "track_id": track.get("id", ""),  # To check if track changed
            }
    except:
        pass
    return None


def get_image_as_ascii_art(image_url, max_width=25, max_height=12):
    """Convert image to simple ASCII art"""
    if not image_url:
        return []
        
    try:
        # ASCII characters from dark to light
        ascii_chars = " .:-=+*#%@"

        # Download and load image
        response = requests.get(image_url, timeout=5)
        img = Image.open(BytesIO(response.content))

        # Convert to grayscale
        img = img.convert("L")

        # Resize image
        img = img.resize((max_width, max_height), Image.Resampling.LANCZOS)
        pixels = img.load()

        # Process image
        output = []
        for y in range(max_height):
            row = ""
            for x in range(max_width):
                brightness = pixels[x, y]
                # Map brightness to ASCII character
                char_index = int((brightness / 255) * (len(ascii_chars) - 1))
                row += ascii_chars[char_index]
            output.append(row)

        return output
    except:
        return []


def run_app():
    console = Console()
    
    # Authenticate
    try:
        spotify = get_spotify_client()
        user = spotify.current_user()
        username = user["display_name"]
    except Exception as e:
        console.print(f"Authentication failed: {str(e)}", style="red")
        console.print("Press any key to exit...")
        input()
        return

    # Load playlists
    try:
        playlists = get_user_playlists(spotify)
    except Exception as e:
        console.print(f"Failed to load playlists: {str(e)}", style="red")
        console.print("Press any key to exit...")
        input()
        return

    if not playlists:
        console.print("No playlists found!", style="red")
        console.print("Press any key to exit...")
        input()
        return

    return spotify, username, playlists


def main():
    # Use alternative screen like curses does
    console = Console()
    
    # Get data first
    result = run_app()
    if not result:
        return
        
    spotify, username, playlists = result

    # Now run in alternative screen
    with console.screen(hide_cursor=True) as screen:
        # Main navigation variables
        current_row = 0
        scroll_offset = 0
        mode = "playlists"  # Can be "playlists" or "tracks"
        selected_playlist = None
        tracks = []

        # Playback caching
        cached_playback = None
        last_playback_fetch = 0
        playback_fetch_interval = 5  # Fetch every 5 seconds
        cached_album_art = []  # Cache rendered album art
        last_track_id = None

        def create_now_playing_panel():
        """Create now playing panel"""
        nonlocal cached_playback, last_playback_fetch, cached_album_art, last_track_id

        # Only fetch new data if cache is expired
        current_time = time.time()
        if current_time - last_playback_fetch > playback_fetch_interval:
            cached_playback = get_current_playback(spotify)
            last_playback_fetch = current_time

            # Check if track changed to reload album art
            if cached_playback and cached_playback.get("track_id") != last_track_id:
                last_track_id = cached_playback.get("track_id")
                # Load album art
                if cached_playback.get("album_art_url"):
                    try:
                        cached_album_art = get_image_as_ascii_art(
                            cached_playback["album_art_url"],
                            max_width=25,
                            max_height=12
                        )
                    except Exception:
                        cached_album_art = []

        current = cached_playback
        if not current:
            return Panel(
                Text("No track playing", style="dim italic", justify="center"),
                title="[bold magenta]🎵 Now Playing[/bold magenta]",
                border_style="magenta"
            )

        # Create content with album art and track info
        content_parts = []
        
        # Album art if available
        if cached_album_art:
            art_text = Text("\n".join(cached_album_art), style="white", justify="center")
            content_parts.append(art_text)
            content_parts.append(Text())  # Empty line

        # Track info
        info_table = Table(show_header=False, box=None, padding=(0, 1))
        info_table.add_column("", style="dim", width=8)
        info_table.add_column("", style="white")

        # Status (Playing/Paused)
        status = "▶ Playing" if current["is_playing"] else "⏸ Paused"
        info_table.add_row("Status:", status)
        
        # Track details
        info_table.add_row("Track:", current["name"][:30])
        info_table.add_row("Artist:", current["artists"][:30])
        info_table.add_row("Album:", current["album"][:30])

        # Progress bar with estimated progress
        time_elapsed = (time.time() - last_playback_fetch) * 1000  # Convert to ms
        estimated_progress = current["progress"] + (time_elapsed if current["is_playing"] else 0)
        estimated_progress = min(estimated_progress, current["duration"])  # Don't exceed duration

        progress_pct = estimated_progress / current["duration"] if current["duration"] > 0 else 0
        bar_width = 20
        filled = int(bar_width * progress_pct)
        empty = bar_width - filled
        progress_bar = "█" * filled + "░" * empty
        info_table.add_row("Progress:", progress_bar)

        # Time
        time_str = f"{format_duration(int(estimated_progress))} / {format_duration(current['duration'])}"
        info_table.add_row("Time:", time_str)

        if cached_album_art:
            from rich.console import Group
            content = Group(*content_parts, info_table)
        else:
            content = info_table

        return Panel(
            content,
            title="[bold magenta]🎵 Now Playing[/bold magenta]",
            border_style="magenta"
        )

    def print_playlists(selected_row_idx, scroll_offset):
        console.clear()

        # Create layout
        layout = Layout()
        layout.split_row(
            Layout(name="main", ratio=3),
            Layout(name="now_playing", ratio=1, minimum_size=30)
        )

        # Calculate visible range
        visible_height = 15

        # Adjust scroll offset if needed
        if selected_row_idx < scroll_offset:
            scroll_offset = selected_row_idx
        elif selected_row_idx >= scroll_offset + visible_height:
            scroll_offset = selected_row_idx - visible_height + 1

        # Create playlist table
        playlist_table = Table(show_header=True, box=box.ROUNDED)
        playlist_table.add_column("", width=3)
        playlist_table.add_column("Playlist", style="white", overflow="ellipsis")
        playlist_table.add_column("Tracks", style="green", justify="center", width=8)

        # Display playlists
        for i in range(visible_height):
            idx = scroll_offset + i
            if idx >= len(playlists):
                playlist_table.add_row(" ", " ", " ")
                continue

            playlist = playlists[idx]
            name = playlist["name"]
            track_count = playlist.get("tracks", {}).get("total", 0)

            # Add '>' indicator for selected item
            indicator = "►" if idx == selected_row_idx else " "
            
            style = "bold cyan" if idx == selected_row_idx else "white"
            playlist_table.add_row(indicator, name, str(track_count), style=style)

        # Main content panel
        main_panel = Panel(
            playlist_table,
            title=f"[bold green]SPOTIFY PLAYLISTS ({len(playlists)} total)[/bold green]",
            subtitle=f"[dim]↑↓: Navigate | Enter: View Tracks | Q: Quit | [{selected_row_idx + 1}/{len(playlists)}][/dim]",
            border_style="green"
        )

        layout["main"].update(main_panel)
        layout["now_playing"].update(create_now_playing_panel())

        console.print(layout)
        return scroll_offset

    def print_tracks(selected_row_idx, scroll_offset):
        console.clear()

        # Create layout
        layout = Layout()
        layout.split_row(
            Layout(name="main", ratio=3),
            Layout(name="now_playing", ratio=1, minimum_size=30)
        )

        # Calculate visible range
        visible_height = 15

        # Adjust scroll offset if needed
        if selected_row_idx < scroll_offset:
            scroll_offset = selected_row_idx
        elif selected_row_idx >= scroll_offset + visible_height:
            scroll_offset = selected_row_idx - visible_height + 1

        # Create tracks table
        tracks_table = Table(show_header=True, box=box.ROUNDED)
        tracks_table.add_column("", width=3)
        tracks_table.add_column("#", width=4, justify="right")
        tracks_table.add_column("Track", style="white", overflow="ellipsis")
        tracks_table.add_column("Artist", style="cyan", overflow="ellipsis")
        tracks_table.add_column("Duration", style="green", justify="center", width=8)

        # Display tracks
        for i in range(visible_height):
            idx = scroll_offset + i
            if idx >= len(tracks):
                tracks_table.add_row(" ", " ", " ", " ", " ")
                continue

            track = tracks[idx]
            name = track["name"]
            artists = track["artists"]
            duration = track["duration"]

            # Add '>' indicator for selected item
            indicator = "►" if idx == selected_row_idx else " "
            
            style = "bold cyan" if idx == selected_row_idx else "white"
            tracks_table.add_row(indicator, str(idx + 1), name, artists, duration, style=style)

        # Main content panel
        playlist_name = selected_playlist["name"] if selected_playlist else "Unknown"
        main_panel = Panel(
            tracks_table,
            title=f"[bold green]TRACKS: {playlist_name} ({len(tracks)} tracks)[/bold green]",
            subtitle=f"[dim]↑↓: Navigate | Backspace: Back to Playlists | Q: Quit | [{selected_row_idx + 1}/{len(tracks)}][/dim]",
            border_style="green"
        )

        layout["main"].update(main_panel)
        layout["now_playing"].update(create_now_playing_panel())

        console.print(layout)
        return scroll_offset

    # Initial display
    scroll_offset = print_playlists(current_row, scroll_offset)

    def get_key():
        """Get a single keypress"""
        import termios, tty, sys
        fd = sys.stdin.fileno()
        old = termios.tcgetattr(fd)
        try:
            tty.setcbreak(fd)
            ch = sys.stdin.read(1)
            if ch == '\x1b':  # Arrow key
                ch += sys.stdin.read(2)
            return ch
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old)

    # Main loop with single-key navigation
    while True:
        try:
            key = get_key()

            if key in ['q', 'Q', '\x03']:  # q or Ctrl+C
                break

            if mode == "playlists":
                if key == '\x1b[A':  # Up arrow
                    if current_row > 0:
                        current_row -= 1
                        scroll_offset = print_playlists(current_row, scroll_offset)
                elif key == '\x1b[B':  # Down arrow
                    if current_row < len(playlists) - 1:
                        current_row += 1
                        scroll_offset = print_playlists(current_row, scroll_offset)
                elif key in ['\r', '\n']:  # Enter
                    # Load tracks for selected playlist
                    selected_playlist = playlists[current_row]

                    console.clear()
                    console.print(f"Loading tracks for '{selected_playlist['name']}'...", style="yellow")

                    try:
                        # Get all tracks from the playlist
                        results = spotify.playlist_tracks(selected_playlist["id"])
                        raw_tracks = results["items"]

                        # Handle pagination
                        while results["next"]:
                            results = spotify.next(results)
                            raw_tracks.extend(results["items"])

                        # Extract track information
                        tracks = []
                        for item in raw_tracks:
                            track_info = item.get("track")
                            if track_info:
                                artists = ", ".join(
                                    [artist["name"] for artist in track_info.get("artists", [])]
                                )
                                tracks.append(
                                    {
                                        "name": track_info.get("name", "Unknown"),
                                        "artists": artists,
                                        "album": track_info.get("album", {}).get("name", "Unknown"),
                                        "duration": format_duration(track_info.get("duration_ms", 0)),
                                    }
                                )

                        if tracks:
                            mode = "tracks"
                            current_row = 0
                            scroll_offset = 0
                            scroll_offset = print_tracks(current_row, scroll_offset)
                        else:
                            console.print("No tracks found in this playlist!", style="red")
                            console.print("Press any key to go back...")
                            get_key()
                            scroll_offset = print_playlists(current_row, scroll_offset)

                    except Exception as e:
                        console.print(f"Error loading tracks: {str(e)}", style="red")
                        console.print("Press any key to go back...")
                        get_key()
                        scroll_offset = print_playlists(current_row, scroll_offset)

            elif mode == "tracks":
                if key == '\x1b[A':  # Up arrow
                    if current_row > 0:
                        current_row -= 1
                        scroll_offset = print_tracks(current_row, scroll_offset)
                elif key == '\x1b[B':  # Down arrow
                    if current_row < len(tracks) - 1:
                        current_row += 1
                        scroll_offset = print_tracks(current_row, scroll_offset)
                elif key in ['\x7f', '\x08']:  # Backspace
                    # Go back to playlists
                    mode = "playlists"
                    current_row = 0
                    scroll_offset = 0
                    scroll_offset = print_playlists(current_row, scroll_offset)

        except KeyboardInterrupt:
            break
        except:
            continue

    console.print("\n[yellow]👋 Thanks for using Spotify Rich Browser![/yellow]")


if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\n\nInterrupted by user")
    except Exception as e:
        print(f"\n\nError: {str(e)}")
        print("Note: Make sure you have the required dependencies.")