using System;
using System.Collections.Concurrent;
using System.IO;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using UniversalTagEditor.Core;

namespace UniversalTagEditor.GUI
{
    public partial class Form1 : Form
    {
        private CancellationTokenSource? _cts;

        private readonly ConcurrentQueue<string> _logQueue = new();
        private readonly System.Windows.Forms.Timer _logTimer = new();
        private StreamWriter? _logWriter;

        private const int MaxLogChars = 500_000;

        public Form1()
        {
            InitializeComponent();

            cbFormat.Items.AddRange(new object[] { "flac", "mp3", "wav", "m4a", "ogg" });
            cbFormat.SelectedIndex = 0;

            btnCancel.Enabled = false;
            chkEnhance.Enabled = false;

            // Таймер: пачками добавляем лог в RichTextBox
            _logTimer.Interval = 100; // 10 раз/сек
            _logTimer.Tick += (_, __) => FlushLogToUi();
            _logTimer.Start();
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {
            using var dialog = new FolderBrowserDialog();
            if (dialog.ShowDialog() == DialogResult.OK)
                tbFolder.Text = dialog.SelectedPath;
        }

        private void chkFixTags_CheckedChanged(object sender, EventArgs e)
        {
            chkEnhance.Enabled = chkFixTags.Checked;
            if (!chkFixTags.Checked) chkEnhance.Checked = false;
        }

        // ВАЖНО: async, потому что внутри await
        private async void btnStart_Click(object sender, EventArgs e)
        {
            if (_cts != null) return;

            var workDir = tbFolder.Text.Trim();
            if (string.IsNullOrWhiteSpace(workDir) || !Directory.Exists(workDir))
            {
                MessageBox.Show("Укажи существующую папку.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            var format = (cbFormat.SelectedItem?.ToString() ?? "flac").Trim().TrimStart('.');

            // Очистка UI лога
            logBox.Clear();
            while (_logQueue.TryDequeue(out _)) { }

            // Лог рядом с GUI.exe
            var logPath = Path.Combine(AppContext.BaseDirectory, "logs.txt");
            _logWriter = new StreamWriter(logPath, append: true, encoding: Encoding.UTF8)
            {
                AutoFlush = true
            };

            _cts = new CancellationTokenSource();

            btnStart.Enabled = false;
            btnCancel.Enabled = true;
            progressBar.Value = 0;
            progressBar.Maximum = 1;

            var opt = new UteOptions
            {
                WorkingDirectory = workDir,
                Format = format,
                FixTags = chkFixTags.Checked,
                EnhanceStructure = chkEnhance.Checked,
                MaxDegreeOfParallelism = 4
            };

            // Лог: в файл сразу + в очередь для UI
            var log = new Progress<string>(msg =>
            {
                var line = $"[{DateTime.Now:HH:mm:ss}] {msg}";
                _logWriter?.WriteLine(line);
                _logQueue.Enqueue(line);
            });

            // Прогресс
            var prog = new Progress<ProgressInfo>(p =>
            {
                progressBar.Maximum = Math.Max(1, p.Total);
                progressBar.Value = Math.Min(p.Done, progressBar.Maximum);
            });

            try
            {
                await Runner.RunAsync(opt, log, prog, _cts.Token);
                _logQueue.Enqueue($"[{DateTime.Now:HH:mm:ss}] Готово!");
            }
            catch (OperationCanceledException)
            {
                _logQueue.Enqueue($"[{DateTime.Now:HH:mm:ss}] Отменено пользователем.");
            }
            catch (Exception ex)
            {
                _logQueue.Enqueue($"[{DateTime.Now:HH:mm:ss}] ОШИБКА: {ex}");
            }
            finally
            {
                btnStart.Enabled = true;
                btnCancel.Enabled = false;

                _cts?.Dispose();
                _cts = null;

                _logWriter?.Dispose();
                _logWriter = null;
            }
        }

        // Кнопка Cancel должна отменять обработку
        private void btnCancel_Click(object sender, EventArgs e)
        {
            _cts?.Cancel();
        }

        // Таймер вызывает это: быстро добавляем лог пачками
        private void FlushLogToUi()
        {
            if (_logQueue.IsEmpty) return;

            var sb = new StringBuilder();
            int taken = 0;

            while (taken < 200 && _logQueue.TryDequeue(out var line))
            {
                sb.AppendLine(line);
                taken++;
            }

            if (sb.Length == 0) return;

            logBox.AppendText(sb.ToString());
            logBox.ScrollToCaret();

            TrimLogIfNeeded();
        }

        private void TrimLogIfNeeded()
        {
            if (logBox.TextLength <= MaxLogChars) return;

            int remove = logBox.TextLength / 3;
            logBox.Select(0, remove);
            logBox.SelectedText = "";
        }

        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            _cts?.Cancel();
            _logWriter?.Dispose();
            _logWriter = null;
            base.OnFormClosing(e);
        }

        private void exit(object sender, EventArgs e)
        {
            Application.Exit();
        }
    }
}