using Sbroenne.ExcelMcp.ComInterop;
using Sbroenne.ExcelMcp.ComInterop.Session;
using Sbroenne.ExcelMcp.Core.Models;
using Excel = Microsoft.Office.Interop.Excel;


namespace Sbroenne.ExcelMcp.Core.Commands.Range;

/// <summary>
/// Range hyperlink operations (add, remove, list, get)
/// </summary>
public partial class RangeCommands
{
    /// <inheritdoc />
    public OperationResult AddHyperlink(IExcelBatch batch, string sheetName, string cellAddress, string url, string? displayText = null, string? tooltip = null)
    {
        var result = new OperationResult { FilePath = batch.WorkbookPath, Action = "add-hyperlink" };

        return batch.Execute((ctx, ct) =>
        {
            Excel.Worksheet? sheet = null;
            dynamic? range = null;
            dynamic? hyperlinks = null;
            dynamic? hyperlink = null;
            try
            {
                sheet = ComUtilities.FindSheet(ctx.Book, sheetName);
                if (sheet == null)
                {
                    throw new InvalidOperationException($"Sheet '{sheetName}' not found.");
                }

                range = sheet.Range[cellAddress];
                hyperlinks = sheet.Hyperlinks;

                // Resolve URL - full path for file links
                string address = url.StartsWith("http://", StringComparison.OrdinalIgnoreCase) ||
                               url.StartsWith("https://", StringComparison.OrdinalIgnoreCase) ||
                               url.StartsWith("ftp://", StringComparison.OrdinalIgnoreCase) ||
                               url.StartsWith("mailto:", StringComparison.OrdinalIgnoreCase)
                    ? url
                    : Path.GetFullPath(url);

                hyperlink = hyperlinks.Add(
                    Anchor: range,
                    Address: address,
                    SubAddress: Type.Missing,
                    ScreenTip: tooltip ?? Type.Missing,
                    TextToDisplay: displayText ?? Type.Missing
                );

                result.Success = true;
                return result;
            }
            finally
            {
                ComUtilities.Release(ref hyperlink);
                ComUtilities.Release(ref hyperlinks);
                ComUtilities.Release(ref range);
                ComUtilities.Release(ref sheet);
            }
        });
    }

    /// <inheritdoc />
    public OperationResult RemoveHyperlink(IExcelBatch batch, string sheetName, string rangeAddress)
    {
        var result = new OperationResult { FilePath = batch.WorkbookPath, Action = "remove-hyperlink" };

        return batch.Execute((ctx, ct) =>
        {
            dynamic? range = null;
            dynamic? hyperlinks = null;
            try
            {
                range = RangeHelpers.ResolveRange(ctx.Book, sheetName, rangeAddress, out string? specificError);
                if (range == null)
                {
                    throw new InvalidOperationException(specificError ?? RangeHelpers.GetResolveError(sheetName, rangeAddress));
                }

                hyperlinks = range.Hyperlinks;
                int count = hyperlinks.Count;

                // Delete all hyperlinks in the range
                for (int i = count; i >= 1; i--)
                {
                    dynamic? hl = null;
                    try
                    {
                        hl = hyperlinks.Item(i);
                        hl.Delete();
                    }
                    finally
                    {
                        ComUtilities.Release(ref hl);
                    }
                }

                result.Success = true;
                return result;
            }
            finally
            {
                ComUtilities.Release(ref hyperlinks);
                ComUtilities.Release(ref range);
            }
        });
    }

    /// <inheritdoc />
    public RangeHyperlinkResult ListHyperlinks(IExcelBatch batch, string sheetName)
    {
        var result = new RangeHyperlinkResult
        {
            FilePath = batch.WorkbookPath,
            SheetName = sheetName
        };

        return batch.Execute((ctx, ct) =>
        {
            Excel.Worksheet? sheet = null;
            dynamic? hyperlinks = null;
            try
            {
                sheet = ComUtilities.FindSheet(ctx.Book, sheetName);
                if (sheet == null)
                {
                    throw new InvalidOperationException($"Sheet '{sheetName}' not found.");
                }

                hyperlinks = sheet.Hyperlinks;
                int count = hyperlinks.Count;

                for (int i = 1; i <= count; i++)
                {
                    dynamic? hyperlink = null;
                    dynamic? range = null;
                    try
                    {
                        hyperlink = hyperlinks.Item(i);
                        range = hyperlink.Range;

                        result.Hyperlinks.Add(new HyperlinkInfo
                        {
                            CellAddress = range.Address[false, false],
                            Address = hyperlink.Address ?? string.Empty,
                            DisplayText = hyperlink.TextToDisplay ?? string.Empty,
                            ScreenTip = hyperlink.ScreenTip
                        });
                    }
                    finally
                    {
                        ComUtilities.Release(ref range);
                        ComUtilities.Release(ref hyperlink);
                    }
                }

                result.Success = true;
                return result;
            }
            finally
            {
                ComUtilities.Release(ref hyperlinks);
                ComUtilities.Release(ref sheet);
            }
        });
    }

    /// <inheritdoc />
    public RangeHyperlinkResult GetHyperlink(IExcelBatch batch, string sheetName, string cellAddress)
    {
        var result = new RangeHyperlinkResult
        {
            FilePath = batch.WorkbookPath,
            SheetName = sheetName,
            RangeAddress = cellAddress
        };

        return batch.Execute((ctx, ct) =>
        {
            Excel.Worksheet? sheet = null;
            dynamic? range = null;
            dynamic? hyperlinks = null;
            try
            {
                sheet = ComUtilities.FindSheet(ctx.Book, sheetName);
                if (sheet == null)
                {
                    throw new InvalidOperationException($"Sheet '{sheetName}' not found.");
                }

                range = sheet.Range[cellAddress];
                hyperlinks = range.Hyperlinks;

                int count = hyperlinks.Count;
                if (count > 0)
                {
                    dynamic? hyperlink = null;
                    try
                    {
                        hyperlink = hyperlinks.Item(1); // Get first hyperlink in cell

                        result.Hyperlinks.Add(new HyperlinkInfo
                        {
                            CellAddress = cellAddress,
                            Address = hyperlink.Address ?? string.Empty,
                            SubAddress = hyperlink.SubAddress,
                            DisplayText = hyperlink.TextToDisplay ?? string.Empty,
                            ScreenTip = hyperlink.ScreenTip,
                            IsInternal = string.IsNullOrEmpty(hyperlink.Address)
                        });
                    }
                    finally
                    {
                        ComUtilities.Release(ref hyperlink);
                    }
                }

                result.Success = true;
                return result;
            }
            finally
            {
                ComUtilities.Release(ref hyperlinks);
                ComUtilities.Release(ref range);
                ComUtilities.Release(ref sheet);
            }
        });
    }

}



