using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
using ClaudeDo.Installer.Core;

namespace ClaudeDo.Installer.Steps;

public sealed class CreateShortcutsStep : IInstallStep
{
    public string Name => "Create Shortcuts";

    public Task<StepResult> ExecuteAsync(InstallContext ctx, IProgress<string> progress, CancellationToken ct)
    {
        try
        {
            var appExe = Path.Combine(ctx.InstallDirectory, "app", "ClaudeDo.App.exe");
            var workingDir = Path.Combine(ctx.InstallDirectory, "app");

            // Start Menu shortcut
            var startMenuDir = Path.Combine(
                Environment.GetFolderPath(Environment.SpecialFolder.CommonStartMenu),
                "Programs");
            Directory.CreateDirectory(startMenuDir);
            var startMenuPath = Path.Combine(startMenuDir, "ClaudeDo.lnk");
            CreateShortcut(startMenuPath, appExe, workingDir, "ClaudeDo Task Manager");
            progress.Report($"Created Start Menu shortcut: {startMenuPath}");

            // Desktop shortcut (optional)
            if (ctx.CreateDesktopShortcut)
            {
                var desktopPath = Path.Combine(
                    Environment.GetFolderPath(Environment.SpecialFolder.CommonDesktopDirectory),
                    "ClaudeDo.lnk");
                CreateShortcut(desktopPath, appExe, workingDir, "ClaudeDo Task Manager");
                progress.Report($"Created Desktop shortcut: {desktopPath}");
            }

            return Task.FromResult(StepResult.Ok());
        }
        catch (Exception ex)
        {
            return Task.FromResult(StepResult.Fail(ex.Message));
        }
    }

    private static void CreateShortcut(string shortcutPath, string targetPath, string workingDir, string description)
    {
        var link = (IShellLink)new ShellLink();
        link.SetPath(targetPath);
        link.SetWorkingDirectory(workingDir);
        link.SetDescription(description);
        link.SetIconLocation(targetPath, 0);

        var file = (IPersistFile)link;
        file.Save(shortcutPath, false);
    }

    #region COM Interop for IShellLink

    [ComImport]
    [Guid("00021401-0000-0000-C000-000000000046")]
    private class ShellLink { }

    [ComImport]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [Guid("000214F9-0000-0000-C000-000000000046")]
    private interface IShellLink
    {
        void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, IntPtr pfd, int fFlags);
        void GetIDList(out IntPtr ppidl);
        void SetIDList(IntPtr pidl);
        void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName);
        void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
        void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath);
        void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
        void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath);
        void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
        void GetHotkey(out short pwHotkey);
        void SetHotkey(short wHotkey);
        void GetShowCmd(out int piShowCmd);
        void SetShowCmd(int iShowCmd);
        void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon);
        void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
        void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, int dwReserved);
        void Resolve(IntPtr hwnd, int fFlags);
        void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
    }

    #endregion
}
