using System.Text;
using System.Text.RegularExpressions;
using Microsoft.Extensions.Logging;

namespace YTExtractor.Services
{
    public class VttFixerService
    {
        private readonly ILogger<VttFixerService> _logger;

        public VttFixerService(ILogger<VttFixerService> logger)
        {
            _logger = logger;
        }

        /// <summary>
        /// Fixes YouTube's autogenerated VTT subtitles with HTML tags and returns an SRT-formatted string
        /// </summary>
        /// <param name="vttContent">The VTT content as a string</param>
        /// <returns>The fixed subtitles in SRT format</returns>
        public string FixYoutubeVtt(string vttContent)
        {
            try
            {
                _logger.LogInformation("Starting to fix YouTube VTT content with HTML tags");

                // Define regex patterns to extract timing and text
                var timeRegex = new Regex(@"(\d{2}:\d{2}:\d{2}\.\d{3}) --> (\d{2}:\d{2}:\d{2}\.\d{3})");
                var htmlTagRegex = new Regex(@"<[^>]+>");

                // Split the content by WEBVTT header and timestamps
                var lines = vttContent.Split('\n');
                var resultBuilder = new StringBuilder();

                List<Caption> captions = new List<Caption>();
                Caption currentCaption = null;
                bool isHeader = true;
                StringBuilder textBuilder = new StringBuilder();

                // First pass: Parse the VTT file and extract captions
                foreach (var line in lines)
                {
                    // Skip header lines
                    if (isHeader)
                    {
                        if (line.Trim().StartsWith("00:"))
                            isHeader = false;
                        else
                            continue;
                    }

                    // Check if this is a timing line
                    var timeMatch = timeRegex.Match(line);
                    if (timeMatch.Success)
                    {
                        // If we already have a caption in progress, save it
                        if (currentCaption != null && textBuilder.Length > 0)
                        {
                            currentCaption.Text = textBuilder.ToString().Trim();
                            captions.Add(currentCaption);
                            textBuilder.Clear();
                        }

                        // Create a new caption
                        currentCaption = new Caption
                        {
                            Start = timeMatch.Groups[1].Value.Replace(".", ","),
                            End = timeMatch.Groups[2].Value.Replace(".", ",")
                        };
                    }
                    // Otherwise, this is caption text
                    else if (currentCaption != null && !string.IsNullOrWhiteSpace(line))
                    {
                        // Remove HTML tags and add the cleaned text
                        string cleanText = htmlTagRegex.Replace(line, "");
                        if (!string.IsNullOrWhiteSpace(cleanText))
                        {
                            textBuilder.AppendLine(cleanText);
                        }
                    }
                }

                // Add the last caption if there is one
                if (currentCaption != null && textBuilder.Length > 0)
                {
                    currentCaption.Text = textBuilder.ToString().Trim();
                    captions.Add(currentCaption);
                }

                // Second pass: Process captions to remove duplicates
                Caption previousCaption = null;
                int counter = 1;

                foreach (var caption in captions)
                {
                    // Clean the text
                    string cleanText = CleanText(caption.Text);

                    if (previousCaption != null)
                    {
                        string prevCleanText = CleanText(previousCaption.Text);

                        // Check if this caption is a duplicate of the previous one
                        if (prevCleanText.Equals(cleanText, StringComparison.OrdinalIgnoreCase))
                        {
                            // Update the end time of the previous caption and skip this one
                            previousCaption.End = caption.End;
                            continue;
                        }

                        // Check if the previous caption text appears at the start of this caption
                        if (cleanText.StartsWith(prevCleanText, StringComparison.OrdinalIgnoreCase))
                        {
                            // Extract only the new part
                            string newText = cleanText.Substring(prevCleanText.Length).Trim();
                            if (!string.IsNullOrWhiteSpace(newText))
                            {
                                caption.Text = newText;
                            }
                            else
                            {
                                // If there's no new text, skip this caption
                                continue;
                            }
                        }

                        // Write the previous caption
                        resultBuilder.AppendLine(counter.ToString());
                        resultBuilder.AppendLine($"{previousCaption.Start} --> {previousCaption.End}");
                        resultBuilder.AppendLine(prevCleanText);
                        resultBuilder.AppendLine();
                        counter++;
                    }

                    previousCaption = new Caption
                    {
                        Start = caption.Start,
                        End = caption.End,
                        Text = caption.Text
                    };
                }

                // Write the last caption
                if (previousCaption != null)
                {
                    string prevCleanText = CleanText(previousCaption.Text);
                    resultBuilder.AppendLine(counter.ToString());
                    resultBuilder.AppendLine($"{previousCaption.Start} --> {previousCaption.End}");
                    resultBuilder.AppendLine(prevCleanText);
                    resultBuilder.AppendLine();
                }

                _logger.LogInformation("Successfully fixed YouTube VTT content with HTML tags");
                return resultBuilder.ToString();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error fixing YouTube VTT content with HTML tags");
                throw;
            }
        }

        /// <summary>
        /// Cleans VTT text by removing HTML tags, position markers, and other formatting
        /// </summary>
        private string CleanText(string text)
        {
            if (string.IsNullOrEmpty(text))
                return string.Empty;

            // Remove HTML tags
            text = Regex.Replace(text, @"<[^>]+>", "");

            // Remove position markers like "align:start position:0%"
            text = Regex.Replace(text, @"align:[a-z]+ position:\d+%", "");

            // Remove timestamps in format <00:00:00.000>
            text = Regex.Replace(text, @"<\d{2}:\d{2}:\d{2}\.\d{3}>", "");

            // Clean up whitespace
            text = Regex.Replace(text, @"\s+", " ").Trim();

            return text;
        }

        private string LimpaTexto(string texto)
        {
            var textoLimpo = Regex.Replace(texto, @"<\d{2}:\d{2}:\d{2}\.\d{3}>", "");
            textoLimpo = Regex.Replace(textoLimpo, @"<\/?c>", "");

            return textoLimpo;
        }

        /// <summary>
        /// Fixes YouTube's autogenerated VTT subtitles file and returns an SRT-formatted string
        /// </summary>
        /// <param name="vttFilePath">Path to the VTT file</param>
        /// <returns>The fixed subtitles in SRT format</returns>
        public string FixYoutubeVttFile(string vttFilePath)
        {
            _logger.LogInformation("Reading VTT file: {VttFilePath}", vttFilePath);
            var vttContent = File.ReadAllText(vttFilePath);
            return FixYoutubeVtt(vttContent);
        }

        private List<Caption> ParseVtt(string vttContent)
        {
            var captions = new List<Caption>();
            
            // Skip the WEBVTT header
            var lines = vttContent.Split('\n')
                .Skip(1) // Skip WEBVTT line
                .Select(l => l.Trim())
                .Where(l => !string.IsNullOrWhiteSpace(l))
                .ToList();
            
            // Pattern to match timestamp lines like "00:00:00.000 --> 00:00:05.000"
            var timestampPattern = new Regex(@"(\d{2}:\d{2}:\d{2}\.\d{3})\s-->\s(\d{2}:\d{2}:\d{2}\.\d{3})");
            
            Caption? currentCaption = null;
            StringBuilder textBuilder = new StringBuilder();
            
            foreach (var line in lines)
            {
                var match = timestampPattern.Match(line);
                
                if (match.Success)
                {
                    // If we were building a caption, add it to the list
                    if (currentCaption != null && textBuilder.Length > 0)
                    {
                        currentCaption.Text = textBuilder.ToString().Trim();
                        captions.Add(currentCaption);
                        textBuilder.Clear();
                    }
                    
                    // Start a new caption
                    currentCaption = new Caption
                    {
                        Start = match.Groups[1].Value,
                        End = match.Groups[2].Value
                    };
                }
                else if (currentCaption != null && !line.Contains("-->") && !string.IsNullOrWhiteSpace(line))
                {
                    // Add text to the current caption
                    if (textBuilder.Length > 0)
                    {
                        textBuilder.AppendLine();
                    }
                    textBuilder.Append(line);
                }
            }
            
            // Add the last caption if there is one
            if (currentCaption != null && textBuilder.Length > 0)
            {
                currentCaption.Text = textBuilder.ToString().Trim();
                captions.Add(currentCaption);
            }
            
            return captions;
        }
        
        private class Caption
        {
            public string Start { get; set; } = string.Empty;
            public string End { get; set; } = string.Empty;
            public string Text { get; set; } = string.Empty;
        }
    }
}