using System.Text;
using VideoStudy.Shared;
using YoutubeExplode;
using YoutubeExplode.Common;
using YoutubeExplode.Videos.ClosedCaptions;
using YoutubeExplode.Videos.Streams;

namespace VideoStudy.Desktop.Services;

public class YouTubeService
{
    private readonly YoutubeClient _youtube = new();
    private readonly HttpClient _httpClient;

    public YouTubeService(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }

    public async Task<VideoInfo> GetVideoInfoAsync(string url)
    {
        var video = await _youtube.Videos.GetAsync(url);
        
        return new VideoInfo
        {
            Title = video.Title,
            Duration = video.Duration ?? TimeSpan.Zero,
            Url = video.Url,
            Author = video.Author.ChannelTitle,
            ThumbnailUrl = video.Thumbnails.GetWithHighestResolution().Url
        };
    }

    public async Task<string> GetCaptionsAsync(string url, string languageCode)
    {
        var trackManifest = await _youtube.Videos.ClosedCaptions.GetManifestAsync(url);
        
        // Try to find the requested language
        var trackInfo = trackManifest.GetByLanguage(languageCode);
        
        // If not found, try generic English or the first one
        if (trackInfo == null)
        {
             trackInfo = trackManifest.Tracks.FirstOrDefault(t => t.Language.Code.StartsWith("en")) 
                         ?? trackManifest.Tracks.FirstOrDefault();
        }

        if (trackInfo == null)
            return string.Empty; // No captions found

        var track = await _youtube.Videos.ClosedCaptions.GetAsync(trackInfo);

        // Convert to text format
        var sb = new StringBuilder();
        foreach (var caption in track.Captions)
        {
            // Simple format: [00:00:00] Text
            // or just text. Let's send the raw text for now or a formatted VTT style?
            // The prompt says "Parse VTT/SRT to text" in TranscriptionService.
            // But here we get objects directly. Let's just build a clean text transcript.
            
            sb.AppendLine($"[{FormatTime(caption.Offset)}] {caption.Text}");
        }

        return sb.ToString();
    }

    public async Task<string> DownloadVideoAsync(string url, string outputDirectory, IProgress<DownloadProgress> progress)
    {
        var video = await _youtube.Videos.GetAsync(url);
        var streamManifest = await _youtube.Videos.Streams.GetManifestAsync(url);

        // Get highest quality muxed stream (Audio + Video)
        // This is usually MP4 up to 720p. 
        var streamInfo = streamManifest.GetMuxedStreams().GetWithHighestVideoQuality();

        if (streamInfo == null)
        {
            throw new Exception("No suitable video stream found.");
        }

        // Clean filename
        var safeTitle = string.Join("_", video.Title.Split(Path.GetInvalidFileNameChars()));
        var fileName = $"{safeTitle}.{streamInfo.Container}";
        var filePath = Path.Combine(outputDirectory, fileName);

        if (File.Exists(filePath))
            return filePath;

        await _youtube.Videos.Streams.DownloadAsync(streamInfo, filePath, new Progress<double>(p => 
        {
            progress.Report(new DownloadProgress 
            { 
                PercentComplete = p * 100, 
                Status = $"Downloading video: {(p * 100):F1}%" 
            });
        }));

        return filePath;
    }

    private string FormatTime(TimeSpan time)
    {
        return time.ToString(@"hh\:mm\:ss");
    }
}
