using System.IO;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media.Imaging;
using AxCopilot.Models;
// WinRT OCR — 별칭으로 WPF Media.Imaging 네임스페이스 충돌 방지
using WinBitmapDecoder    = Windows.Graphics.Imaging.BitmapDecoder;
using WinBitmapPixelFmt   = Windows.Graphics.Imaging.BitmapPixelFormat;
using WinSoftwareBitmap   = Windows.Graphics.Imaging.SoftwareBitmap;
using WinOcrEngine         = Windows.Media.Ocr.OcrEngine;
using WinStorageFile       = Windows.Storage.StorageFile;
using WinFileAccessMode    = Windows.Storage.FileAccessMode;

namespace AxCopilot.Services;

public partial class ClipboardHistoryService
{
    // ─── 이미지 캐시 + P/Invoke ─────────────────────────────────────────────

    /// <summary>원본 이미지를 캐시 폴더에 PNG로 저장합니다.</summary>
    private static string? SaveOriginalImage(BitmapSource src)
    {
        try
        {
            Directory.CreateDirectory(ImageCachePath);
            var fileName = $"clip_{DateTime.Now:yyyyMMdd_HHmmss_fff}.png";
            var filePath = Path.Combine(ImageCachePath, fileName);

            var encoder = new PngBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(src));
            using var fs = new FileStream(filePath, FileMode.Create);
            encoder.Save(fs);
            return filePath;
        }
        catch (Exception ex)
        {
            LogService.Warn($"원본 이미지 저장 실패: {ex.Message}");
            return null;
        }
    }

    /// <summary>원본 이미지를 파일에서 로드합니다.</summary>
    public static BitmapSource? LoadOriginalImage(string? path)
    {
        if (string.IsNullOrEmpty(path) || !File.Exists(path)) return null;
        try
        {
            var bi = new BitmapImage();
            bi.BeginInit();
            bi.CacheOption = BitmapCacheOption.OnLoad;
            bi.UriSource = new Uri(path, UriKind.Absolute);
            bi.EndInit();
            bi.Freeze();
            return bi;
        }
        catch (Exception) { return null; }
    }

    /// <summary>이미지 캐시 정리 (30일 초과 + 500MB 초과 시 오래된 파일부터 삭제).</summary>
    public static void CleanupImageCache()
    {
        try
        {
            if (!Directory.Exists(ImageCachePath)) return;
            var files = new DirectoryInfo(ImageCachePath)
                .GetFiles("clip_*.png")
                .OrderBy(f => f.LastWriteTime)
                .ToList();

            // 30일 초과 파일 삭제
            var cutoff = DateTime.Now.AddDays(-MaxCacheAgeDays);
            foreach (var f in files.Where(f => f.LastWriteTime < cutoff).ToList())
            {
                try { f.Delete(); files.Remove(f); } catch (Exception) { }
            }

            // 500MB 초과 시 오래된 파일부터 삭제
            var totalSize = files.Sum(f => f.Length);
            while (totalSize > MaxCacheSizeBytes && files.Count > 0)
            {
                var oldest = files[0];
                totalSize -= oldest.Length;
                try { oldest.Delete(); } catch (Exception) { }
                files.RemoveAt(0);
            }
        }
        catch (Exception ex)
        {
            LogService.Warn($"이미지 캐시 정리 실패: {ex.Message}");
        }
    }

    private static BitmapSource CreateThumbnail(BitmapSource src, int maxWidth)
    {
        if (src.PixelWidth <= maxWidth) return src;
        var scale = (double)maxWidth / src.PixelWidth;
        return new TransformedBitmap(src, new System.Windows.Media.ScaleTransform(scale, scale));
    }

    private static string? ImageToBase64(BitmapSource? img)
    {
        if (img == null) return null;
        try
        {
            var encoder = new PngBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(img));
            using var ms = new MemoryStream();
            encoder.Save(ms);
            return Convert.ToBase64String(ms.ToArray());
        }
        catch (Exception) { return null; }
    }

    private static BitmapSource? Base64ToImage(string? base64)
    {
        if (string.IsNullOrEmpty(base64)) return null;
        try
        {
            var bytes = Convert.FromBase64String(base64);
            using var ms = new MemoryStream(bytes);
            var decoder = BitmapDecoder.Create(ms, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
            return decoder.Frames[0];
        }
        catch (Exception) { return null; }
    }

    // ─── Phase L2-4: OCR 텍스트 추출 ─────────────────────────────────────────

    /// <summary>
    /// Windows OCR API를 사용하여 이미지 파일에서 텍스트를 추출합니다.
    /// 로컬 처리 전용 (인터넷 연결 불필요). 사용자 언어 설정에 맞는 OCR 엔진 사용.
    /// </summary>
    internal static async Task<string?> ExtractOcrTextAsync(string imagePath)
    {
        try
        {
            if (!File.Exists(imagePath)) return null;

            // 사용자 프로파일 언어 기반 OCR 엔진 생성 (한국어/영어 등 시스템 설정 따름)
            var engine = WinOcrEngine.TryCreateFromUserProfileLanguages();
            if (engine == null) return null;

            // Windows Storage API로 이미지 파일 로드
            var storageFile = await WinStorageFile.GetFileFromPathAsync(imagePath);
            using var stream  = await storageFile.OpenAsync(WinFileAccessMode.Read);
            var decoder = await WinBitmapDecoder.CreateAsync(stream);

            // OCR은 Bgra8 포맷을 요구하므로 변환
            WinSoftwareBitmap? origBitmap = null;
            WinSoftwareBitmap? ocrBitmap  = null;
            try
            {
                origBitmap = await decoder.GetSoftwareBitmapAsync();
                ocrBitmap  = origBitmap.BitmapPixelFormat == WinBitmapPixelFmt.Bgra8
                    ? origBitmap
                    : WinSoftwareBitmap.Convert(origBitmap, WinBitmapPixelFmt.Bgra8);

                var result = await engine.RecognizeAsync(ocrBitmap);
                var text   = result.Text?.Trim();

                // OCR 결과 5,000자 상한 (전체 문서 스캔 대응)
                if (text?.Length > 5_000) text = text[..5_000];
                return string.IsNullOrWhiteSpace(text) ? null : text;
            }
            finally
            {
                if (!ReferenceEquals(origBitmap, ocrBitmap)) origBitmap?.Dispose();
                ocrBitmap?.Dispose();
            }
        }
        catch (Exception ex)
        {
            LogService.Warn($"OCR 텍스트 추출 실패: {ex.Message}");
            return null;
        }
    }
}
