using System.Text;
using VideoStudy.Shared;
using Whisper.net;
using Whisper.net.Ggml;

namespace VideoStudy.Desktop.Services;

public class TranscriptionService
{
    private readonly FFmpegService _ffmpegService;
    private readonly HttpClient _httpClient;
    private readonly string _modelsPath;

    public TranscriptionService(FFmpegService ffmpegService, HttpClient httpClient)
    {
        _ffmpegService = ffmpegService;
        _httpClient = httpClient;
        _modelsPath = Path.Combine(AppContext.BaseDirectory, "models");
        Directory.CreateDirectory(_modelsPath);
    }

    public async Task EnsureModelExistsAsync(GgmlType modelType = GgmlType.Base, IProgress<DownloadProgress>? progress = null)
    {
        var modelFileName = $"ggml-{modelType.ToString().ToLower()}.bin";
        var modelPath = Path.Combine(_modelsPath, modelFileName);

        if (File.Exists(modelPath)) return;

        var downloader = new WhisperGgmlDownloader(_httpClient);
        using var modelStream = await downloader.GetGgmlModelAsync(modelType);
        using var fileStream = File.Create(modelPath);
        
        // Simple copy without progress for now as the stream might not support length
        await modelStream.CopyToAsync(fileStream);
    }

    public async Task<string> TranscribeVideoAsync(string videoPath, IProgress<ProgressUpdate> progress)
    {
        var modelPath = Path.Combine(_modelsPath, "ggml-base.bin");
        if (!File.Exists(modelPath))
        {
            await EnsureModelExistsAsync();
        }

        // 1. Convert Audio
        progress.Report(new ProgressUpdate { Message = "Converting audio for Whisper...", Stage = "Preprocessing" });
        var tempWavPath = Path.ChangeExtension(videoPath, ".temp.wav");
        await _ffmpegService.ExtractAudioForWhisperAsync(videoPath, tempWavPath);

        // 2. Transcribe
        progress.Report(new ProgressUpdate { Message = "Loading Whisper model...", Stage = "Transcription" });
        using var whisperFactory = WhisperFactory.FromPath(modelPath);
        using var processor = whisperFactory.CreateBuilder()
            .WithLanguage("auto")
            .Build();

        using var fileStream = File.OpenRead(tempWavPath);
        
        var sb = new StringBuilder();
        progress.Report(new ProgressUpdate { Message = "Transcribing audio...", Stage = "Transcription", PercentComplete = 10 });

        // Iterate through segments
        int segmentCount = 0;
        await foreach (var segment in processor.ProcessAsync(fileStream))
        {
            sb.AppendLine($"[{segment.Start} --> {segment.End}] {segment.Text}");
            
            segmentCount++;
            if (segmentCount % 5 == 0)
            {
                progress.Report(new ProgressUpdate 
                { 
                    Message = $"Transcribing... ({segment.Start.ToString(@"hh\:mm\:ss")})", 
                    Stage = "Transcription"
                    // Percent estimation is hard without knowing duration, but we can update message
                });
            }
        }

        // Cleanup
        try { File.Delete(tempWavPath); } catch { }

        return sb.ToString();
    }
}
