using System;
using System.Diagnostics;
using System.IO;
using UnityEngine;

namespace CG.Utils
{
    public sealed class OpenCCExternalProcessNormalizer : ITextNormalizer
    {
        private readonly string _openccExePath;
        private readonly string _config; // e.g., "s2twp.json" or "s2tw.json"
        private bool _warned;

        public OpenCCExternalProcessNormalizer(string openccExePath, string config)
        {
            _openccExePath = openccExePath;
            _config = string.IsNullOrWhiteSpace(config) ? "s2twp.json" : config.Trim();
        }

        public string Normalize(string input)
        {
            input ??= string.Empty;
            if (string.IsNullOrWhiteSpace(input)) return string.Empty;

            if (string.IsNullOrWhiteSpace(_openccExePath) || !File.Exists(_openccExePath))
            {
                WarnOnce($"OpenCC exe not found. Returning original text. Path='{_openccExePath}'");
                return input;
            }

            try
            {
                // Use stdin/stdout to avoid temp files
                var psi = new ProcessStartInfo
                {
                    FileName = _openccExePath,
                    Arguments = $"-c {_config}",
                    RedirectStandardInput = true,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    UseShellExecute = false,
                    CreateNoWindow = true,
                };

                using var p = new Process { StartInfo = psi };
                p.Start();

                // Write input then close stdin
                p.StandardInput.Write(input);
                p.StandardInput.Close();

                var output = p.StandardOutput.ReadToEnd();
                var err = p.StandardError.ReadToEnd();

                p.WaitForExit(1500);

                if (p.ExitCode != 0)
                {
                    WarnOnce($"OpenCC exitcode={p.ExitCode}. stderr='{err}' (return original)");
                    return input;
                }

                return string.IsNullOrWhiteSpace(output) ? input : output.TrimEnd('\r','\n');
            }
            catch (Exception ex)
            {
                WarnOnce($"OpenCC failed: {ex.Message} (return original)");
                return input;
            }
        }

        private void WarnOnce(string msg)
        {
            if (_warned) return;
            _warned = true;
            UnityEngine.Debug.LogWarning(msg);
        }
    }
}
