using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;
using ZXing;
using ZXing.QrCode.Internal;

namespace TableMagic.Skills
{
    public class ExcelQRSkill : ISkill
    {
        public string Name => "ExcelQR";
        public string Description => "二维码技能,支持生成二维码、条形码以及扫描识别二维码";

        public List<SkillTool> GetTools()
        {
            return new List<SkillTool>
            {
                new SkillTool
                {
                    Name = "generate_qr_code",
                    Description = "为指定列的数据生成二维码。当用户要求生成二维码时使用此工具。",
                    Parameters = new Dictionary<string, object>
                    {
                        { "type", "object" },
                        { "properties", new Dictionary<string, object>
                            {
                                { "columnNames", new { type = "string", description = "要生成二维码的列名列表(JSON数组格式)" } },
                                { "sheetName", new { type = "string", description = "工作表名称(可选)" } },
                                { "size", new { type = "integer", description = "二维码尺寸(像素,默认100)" } },
                                { "foregroundColor", new { type = "string", description = "前景色(十六进制,默认黑色000000)" } },
                                { "backgroundColor", new { type = "string", description = "背景色(十六进制,默认白色FFFFFF)" } },
                                { "logoPath", new { type = "string", description = "Logo图片路径(可选)" } }
                            }
                        }
                    },
                    RequiredParameters = new List<string> { "columnNames" }
                },
                new SkillTool
                {
                    Name = "generate_barcode",
                    Description = "为指定列的数据生成条形码(Code128格式)。当用户要求生成条形码时使用此工具。",
                    Parameters = new Dictionary<string, object>
                    {
                        { "type", "object" },
                        { "properties", new Dictionary<string, object>
                            {
                                { "columnName", new { type = "string", description = "要生成条形码的列名" } },
                                { "sheetName", new { type = "string", description = "工作表名称(可选)" } },
                                { "width", new { type = "integer", description = "条形码宽度(默认150)" } },
                                { "height", new { type = "integer", description = "条形码高度(默认50)" } }
                            }
                        }
                    },
                    RequiredParameters = new List<string> { "columnName" }
                },
                new SkillTool
                {
                    Name = "scan_qr_code",
                    Description = "扫描图片文件中的二维码并返回内容。当用户要求识别二维码时使用此工具。",
                    Parameters = new Dictionary<string, object>
                    {
                        { "type", "object" },
                        { "properties", new Dictionary<string, object>
                            {
                                { "imagePaths", new { type = "string", description = "图片文件路径列表(JSON数组格式)" } },
                                { "outputSheetName", new { type = "string", description = "输出工作表名称(可选)" } }
                            }
                        }
                    },
                    RequiredParameters = new List<string> { "imagePaths" }
                },
                new SkillTool
                {
                    Name = "scan_qr_code_folder",
                    Description = "批量扫描文件夹中所有图片的二维码。当用户要求批量识别二维码时使用此工具。",
                    Parameters = new Dictionary<string, object>
                    {
                        { "type", "object" },
                        { "properties", new Dictionary<string, object>
                            {
                                { "folderPath", new { type = "string", description = "图片文件夹路径" } },
                                { "includeSubfolders", new { type = "boolean", description = "是否包含子目录(默认true)" } },
                                { "outputSheetName", new { type = "string", description = "输出工作表名称(可选)" } }
                            }
                        }
                    },
                    RequiredParameters = new List<string> { "folderPath" }
                },
                new SkillTool
                {
                    Name = "decode_qr_code_from_range",
                    Description = "从Excel中嵌入的二维码图片解码内容。当用户要求读取Excel中的二维码图片时使用此工具。",
                    Parameters = new Dictionary<string, object>
                    {
                        { "type", "object" },
                        { "properties", new Dictionary<string, object>
                            {
                                { "sheetName", new { type = "string", description = "工作表名称(可选)" } }
                            }
                        }
                    },
                    RequiredParameters = new List<string>()
                }
            };
        }

        public async Task<SkillResult> ExecuteToolAsync(string toolName, Dictionary<string, object> arguments)
        {
            try
            {
                switch (toolName)
                {
                    case "generate_qr_code":
                        return await GenerateQrCodeAsync(arguments);
                    case "generate_barcode":
                        return await GenerateBarcodeAsync(arguments);
                    case "scan_qr_code":
                        return await ScanQrCodeAsync(arguments);
                    case "scan_qr_code_folder":
                        return await ScanQrCodeFolderAsync(arguments);
                    case "decode_qr_code_from_range":
                        return await DecodeQrCodeFromRangeAsync(arguments);
                    default:
                        return new SkillResult { Success = false, Error = $"Tool {toolName} not implemented in ExcelQRSkill" };
                }
            }
            catch (Exception ex)
            {
                return new SkillResult { Success = false, Error = ex.Message };
            }
        }

        private async Task<SkillResult> GenerateQrCodeAsync(Dictionary<string, object> arguments)
        {
            return await Task.Run(() =>
            {
                var columnNames = Newtonsoft.Json.JsonConvert.DeserializeObject<List<string>>(arguments["columnNames"].ToString());
                var sheetName = arguments.ContainsKey("sheetName") ? arguments["sheetName"].ToString() : null;
                var size = arguments.ContainsKey("size") ? Convert.ToInt32(arguments["size"]) : 100;
                var foregroundColor = arguments.ContainsKey("foregroundColor") 
                    ? ColorTranslator.FromHtml("#" + arguments["foregroundColor"].ToString()) 
                    : Color.Black;
                var backgroundColor = arguments.ContainsKey("backgroundColor") 
                    ? ColorTranslator.FromHtml("#" + arguments["backgroundColor"].ToString()) 
                    : Color.White;
                var logoPath = arguments.ContainsKey("logoPath") ? arguments["logoPath"].ToString() : null;

                var workbook = ThisAddIn.app.ActiveWorkbook;
                var sheet = string.IsNullOrEmpty(sheetName) ? workbook.ActiveSheet : workbook.Worksheets[sheetName];

                var usedRange = sheet.UsedRange;
                int lastRow = usedRange.Rows.Count;
                int lastCol = usedRange.Columns.Count;

                var colIndices = new List<int>();
                foreach (var colName in columnNames)
                {
                    int idx = GetColumnIndex(sheet, colName);
                    if (idx > 0) colIndices.Add(idx);
                }

                if (colIndices.Count == 0)
                    return new SkillResult { Success = false, Error = "未找到指定的列" };

                ThisAddIn.app.ScreenUpdating = false;

                int qrCol = lastCol + 1;
                sheet.Cells[1, qrCol].Value = "二维码";

                var writer = new BarcodeWriter
                {
                    Format = BarcodeFormat.QR_CODE,
                    Options = new ZXing.QrCode.QrCodeEncodingOptions
                    {
                        Height = size,
                        Width = size,
                        CharacterSet = "UTF-8",
                        ErrorCorrection = ErrorCorrectionLevel.H,
                        Margin = 0
                    }
                };

                int generatedCount = 0;
                for (int r = 2; r <= lastRow; r++)
                {
                    string data = "";
                    if (colIndices.Count > 1)
                    {
                        foreach (var idx in colIndices)
                        {
                            var key = sheet.Cells[1, idx].Text?.ToString();
                            var value = sheet.Cells[r, idx].Text?.ToString();
                            data += $"{key}:{value};";
                        }
                    }
                    else
                    {
                        data = sheet.Cells[r, colIndices[0]].Text?.ToString() ?? "";
                    }

                    if (string.IsNullOrEmpty(data)) continue;

                    try
                    {
                        var qrBitmap = writer.Write(data);

                        if (!string.IsNullOrEmpty(logoPath) && File.Exists(logoPath))
                        {
                            using (var logo = new Bitmap(logoPath))
                            {
                                int logoSize = size / 5;
                                using (var resizedLogo = new Bitmap(logo, new Size(logoSize, logoSize)))
                                using (var g = Graphics.FromImage(qrBitmap))
                                {
                                    float x = (size - logoSize) / 2f;
                                    float y = (size - logoSize) / 2f;
                                    g.DrawImage(resizedLogo, x, y);
                                }
                            }
                        }

                        var tempPath = Path.Combine(Path.GetTempPath(), $"qr_{Guid.NewGuid()}.png");
                        qrBitmap.Save(tempPath, ImageFormat.Png);

                        var cell = sheet.Cells[r, qrCol];
                        cell.RowHeight = size;
                        cell.ColumnWidth = size / 7;

                        sheet.Shapes.AddPicture(tempPath, 
                            Microsoft.Office.Core.MsoTriState.msoFalse, 
                            Microsoft.Office.Core.MsoTriState.msoTrue,
                            cell.Left, cell.Top, size, size);

                        File.Delete(tempPath);
                        generatedCount++;
                    }
                    catch { }
                }

                ThisAddIn.app.ScreenUpdating = true;

                return new SkillResult { Success = true, Content = $"二维码生成完成,共生成 {generatedCount} 个二维码" };
            });
        }

        private async Task<SkillResult> GenerateBarcodeAsync(Dictionary<string, object> arguments)
        {
            return await Task.Run(() =>
            {
                var columnName = arguments["columnName"].ToString();
                var sheetName = arguments.ContainsKey("sheetName") ? arguments["sheetName"].ToString() : null;
                var width = arguments.ContainsKey("width") ? Convert.ToInt32(arguments["width"]) : 150;
                var height = arguments.ContainsKey("height") ? Convert.ToInt32(arguments["height"]) : 50;

                var workbook = ThisAddIn.app.ActiveWorkbook;
                var sheet = string.IsNullOrEmpty(sheetName) ? workbook.ActiveSheet : workbook.Worksheets[sheetName];

                int colIndex = GetColumnIndex(sheet, columnName);
                if (colIndex == 0)
                    return new SkillResult { Success = false, Error = $"未找到列: {columnName}" };

                var usedRange = sheet.UsedRange;
                int lastRow = usedRange.Rows.Count;
                int lastCol = usedRange.Columns.Count;

                ThisAddIn.app.ScreenUpdating = false;

                int barcodeCol = lastCol + 1;
                sheet.Cells[1, barcodeCol].Value = "条形码";

                var writer = new BarcodeWriter
                {
                    Format = BarcodeFormat.CODE_128,
                    Options = new ZXing.QrCode.QrCodeEncodingOptions
                    {
                        Height = height,
                        Width = width,
                        Margin = 1,
                        PureBarcode = true
                    }
                };

                int generatedCount = 0;
                var asciiPattern = new System.Text.RegularExpressions.Regex(@"^[\x00-\x7F]*$");

                for (int r = 2; r <= lastRow; r++)
                {
                    var value = sheet.Cells[r, colIndex].Text?.ToString();
                    if (string.IsNullOrEmpty(value)) continue;
                    if (!asciiPattern.IsMatch(value)) continue;

                    try
                    {
                        var barcodeBitmap = writer.Write(value);
                        var tempPath = Path.Combine(Path.GetTempPath(), $"bc_{Guid.NewGuid()}.png");
                        barcodeBitmap.Save(tempPath, ImageFormat.Png);

                        var cell = sheet.Cells[r, barcodeCol];
                        cell.RowHeight = height;
                        cell.ColumnWidth = width / 7;

                        sheet.Shapes.AddPicture(tempPath,
                            Microsoft.Office.Core.MsoTriState.msoFalse,
                            Microsoft.Office.Core.MsoTriState.msoTrue,
                            cell.Left, cell.Top, width, height);

                        File.Delete(tempPath);
                        generatedCount++;
                    }
                    catch { }
                }

                ThisAddIn.app.ScreenUpdating = true;

                return new SkillResult { Success = true, Content = $"条形码生成完成,共生成 {generatedCount} 个条形码" };
            });
        }

        private async Task<SkillResult> ScanQrCodeAsync(Dictionary<string, object> arguments)
        {
            return await Task.Run(() =>
            {
                var imagePaths = Newtonsoft.Json.JsonConvert.DeserializeObject<List<string>>(arguments["imagePaths"].ToString());
                var outputSheetName = arguments.ContainsKey("outputSheetName") 
                    ? arguments["outputSheetName"].ToString() 
                    : "二维码识别结果";

                var results = new List<(string Path, string Content)>();
                var reader = new BarcodeReader();

                foreach (var path in imagePaths)
                {
                    if (!File.Exists(path)) continue;

                    try
                    {
                        using (var bitmap = new Bitmap(path))
                        {
                            var result = reader.Decode(bitmap);
                            results.Add((path, result?.Text ?? "无法识别"));
                        }
                    }
                    catch (Exception ex)
                    {
                        results.Add((path, $"错误: {ex.Message}"));
                    }
                }

                WriteScanResultsToExcel(results, outputSheetName);

                return new SkillResult 
                { 
                    Success = true, 
                    Content = $"二维码识别完成,共处理 {imagePaths.Count} 个文件,成功识别 {results.Count(r => r.Content != "无法识别" && !r.Content.StartsWith("错误"))} 个" 
                };
            });
        }

        private async Task<SkillResult> ScanQrCodeFolderAsync(Dictionary<string, object> arguments)
        {
            var folderPath = arguments["folderPath"].ToString();
            var includeSubfolders = !arguments.ContainsKey("includeSubfolders") || Convert.ToBoolean(arguments["includeSubfolders"]);
            var outputSheetName = arguments.ContainsKey("outputSheetName") 
                ? arguments["outputSheetName"].ToString() 
                : "二维码识别结果";

            var searchOption = includeSubfolders ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
            var extensions = new[] { "*.jpg", "*.jpeg", "*.png", "*.bmp" };
            var imagePaths = new List<string>();

            foreach (var ext in extensions)
            {
                imagePaths.AddRange(Directory.GetFiles(folderPath, ext, searchOption));
            }

            return await ScanQrCodeAsync(new Dictionary<string, object>
            {
                { "imagePaths", Newtonsoft.Json.JsonConvert.SerializeObject(imagePaths) },
                { "outputSheetName", outputSheetName }
            });
        }

        private async Task<SkillResult> DecodeQrCodeFromRangeAsync(Dictionary<string, object> arguments)
        {
            return await Task.Run(() =>
            {
                var sheetName = arguments.ContainsKey("sheetName") ? arguments["sheetName"].ToString() : null;

                var workbook = ThisAddIn.app.ActiveWorkbook;
                var sheet = string.IsNullOrEmpty(sheetName) ? workbook.ActiveSheet : workbook.Worksheets[sheetName];

                var results = new List<(string Name, string Content)>();
                var reader = new BarcodeReader();

                foreach (Excel.Shape shape in sheet.Shapes)
                {
                    try
                    {
                        if (shape.Type == Microsoft.Office.Core.MsoShapeType.msoPicture)
                        {
                            shape.Copy();
                            using (var img = (Bitmap)Clipboard.GetImage())
                            {
                                if (img != null)
                                {
                                    var result = reader.Decode(img);
                                    results.Add((shape.Name, result?.Text ?? "无法识别"));
                                }
                            }
                        }
                    }
                    catch { }
                }

                return new SkillResult 
                { 
                    Success = true, 
                    Content = results.Count > 0 
                        ? $"识别结果:\n{string.Join("\n", results.Select(r => $"{r.Name}: {r.Content}"))}" 
                        : "未找到可识别的二维码图片" 
                };
            });
        }

        private int GetColumnIndex(Excel.Worksheet sheet, string columnName)
        {
            if (int.TryParse(columnName, out int colNum))
                return colNum;

            var usedRange = sheet.UsedRange;
            for (int c = 1; c <= usedRange.Columns.Count; c++)
            {
                if (sheet.Cells[1, c].Text?.ToString() == columnName)
                    return c;
            }
            return 0;
        }

        private void WriteScanResultsToExcel(List<(string Path, string Content)> results, string sheetName)
        {
            var workbook = ThisAddIn.app.ActiveWorkbook;

            ThisAddIn.app.ScreenUpdating = false;
            ThisAddIn.app.DisplayAlerts = false;

            Excel.Worksheet sheet;
            
            var existingNames = new List<string>();
            foreach (Excel.Worksheet ws in workbook.Worksheets) existingNames.Add(ws.Name);
            
            string actualSheetName = sheetName;
            if (existingNames.Any(n => string.Equals(n, sheetName, StringComparison.OrdinalIgnoreCase)))
            {
                int suffix = 2;
                while (existingNames.Any(n => string.Equals(n, $"{sheetName}_{suffix}", StringComparison.OrdinalIgnoreCase)))
                {
                    suffix++;
                }
                actualSheetName = $"{sheetName}_{suffix}";
            }
            
            sheet = workbook.Worksheets.Add(After: workbook.Worksheets[workbook.Worksheets.Count]);
            sheet.Name = actualSheetName;

            sheet.Cells[1, 1].Value = "文件路径";
            sheet.Cells[1, 2].Value = "识别内容";
            sheet.Cells[1, 1].Font.Bold = true;
            sheet.Cells[1, 2].Font.Bold = true;

            for (int i = 0; i < results.Count; i++)
            {
                sheet.Cells[i + 2, 1].Value = results[i].Path;
                sheet.Cells[i + 2, 2].Value = results[i].Content;
            }

            sheet.UsedRange.Columns.AutoFit();
            sheet.Activate();

            ThisAddIn.app.ScreenUpdating = true;
            ThisAddIn.app.DisplayAlerts = true;
        }
    }
}