using System.Runtime.InteropServices;
using UnityEngine; // For Debug.LogWarning, Color
using System;     // For IntPtr

// Define C# equivalent of your custom enum from C++ header
// Place this outside the static class if other scripts need it directly
public enum CoVinceOverlayTextAlignment
{
    LEFT = 0x01,
    CENTER = 0x02,
    RIGHT = 0x04,
    TOP = 0x08,
    VCENTER = 0x10,
    BOTTOM = 0x20
}

// Define C# equivalent of your HRESULTs from C++ header
// Place this outside the static class if other scripts need it directly
public enum OverlayHResult : int
{
    // Standard Success
    S_OK = 0,

    // Standard Errors (Use unchecked cast for negative hex literals)
    E_FAIL = unchecked((int)0x80004005),
    E_POINTER = unchecked((int)0x80004003),
    E_INVALIDARG = unchecked((int)0x80070057),
    E_OUTOFMEMORY = unchecked((int)0x8007000E),
    E_NOTIMPL = unchecked((int)0x80004001), // Not Implemented

    // Custom Errors (Calculated from MAKE_HRESULT(1, 19, code))
    COVINCE_E_WINDOW_CREATION_FAILED = unchecked((int)0x80130001), // Code 1
    COVINCE_E_ALREADY_INITIALIZED = unchecked((int)0x80130002), // Code 2 (Maybe unused)
    COVINCE_E_NOT_INITIALIZED = unchecked((int)0x80130003), // Code 3
    COVINCE_E_INVALID_MONITOR_INDEX = unchecked((int)0x80130004), // Code 4
    COVINCE_E_STRING_COPY_FAILED = unchecked((int)0x80130005), // Code 5
    COVINCE_E_TEXT_TOO_LONG = unchecked((int)0x80130006), // Code 6
    COVINCE_E_CLASS_REGISTRATION_FAILED = unchecked((int)0x80130007), // Code 7
    COVINCE_E_GENERIC_ERROR = unchecked((int)0x80130064)  // Code 100
}


/// <summary>
/// Static wrapper class for interacting with the native CoVince Windows Overlay DLL.
/// Handles platform checks and provides safe methods.
/// Only functional on Windows Editor (x64) and Windows Standalone (x64).
/// </summary>
public static class NativeOverlayInterface
{
    // --- Determine Platform Support and DLL Name ---
#if UNITY_EDITOR_WIN && UNITY_64
    // Windows Editor 64-bit: Use Debug 64-bit DLL
    private const string DllName = "CoVinceWindowsOverlay_DB_x64";
    private const bool _IsSupported = true;

#elif UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64
     // Standalone Windows 64-bit ONLY: Use Release 64-bit DLL
     private const string DllName = "CoVinceWindowsOverlay_RL_x64";
     private const bool _IsSupported = true;

#else
     // All other platforms OR unsupported Windows architectures (e.g., x86 Standalone)
     private const string DllName = "BuildTargetNotSupported"; // Dummy name
     private const bool _IsSupported = false;
#endif

    // Public property to check support from other scripts
    public static bool IsSupportedPlatform => _IsSupported;

    // --- Actual DLL Imports (Only declared on supported targets) ---
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64)

    [DllImport(DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ShowOverlay")]
    private static extern int ShowOverlay_Internal([MarshalAs(UnmanagedType.LPWStr)] string text, bool showText, int borderWidth, int r, int g, int b, int fontSize, int alignment);

    [DllImport(DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ShowOverlayOnMonitor")]
    private static extern int ShowOverlayOnMonitor_Internal(int monitorIndex, [MarshalAs(UnmanagedType.LPWStr)] string text, bool showText, int borderWidth, int r, int g, int b, int fontSize, int alignment);

    [DllImport(DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "HideOverlay")]
    private static extern int HideOverlay_Internal();

    [DllImport(DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ShowOverlayText")]
    private static extern int ShowOverlayText_Internal(bool show);

    [DllImport(DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "UpdateOverlayText")]
    private static extern int UpdateOverlayText_Internal([MarshalAs(UnmanagedType.LPWStr)] string text);

    [DllImport(DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "UpdateOverlayFontSize")]
    private static extern int UpdateOverlayFontSize_Internal(int fontSize);

    [DllImport(DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "UpdateOverlayWidth")]
    private static extern int UpdateOverlayWidth_Internal(int borderWidth);

    [DllImport(DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "UpdateOverlayColor")]
    private static extern int UpdateOverlayColor_Internal(int r, int g, int b);

    [DllImport(DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "UpdateOverlayAlignment")]
    private static extern int UpdateOverlayAlignment_Internal(int alignment); // Pass enum as int

    [DllImport(DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "AddOrUpdatePointer")]
    private static extern int AddOrUpdatePointer_Internal([MarshalAs(UnmanagedType.LPWStr)] string userId, [MarshalAs(UnmanagedType.LPWStr)] string userName, int x, int y, [MarshalAs(UnmanagedType.LPWStr)] string imagePath, int desiredWidth, int desiredHeight);

    [DllImport(DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "RemovePointer")]
    private static extern int RemovePointer_Internal([MarshalAs(UnmanagedType.LPWStr)] string userId);

    [DllImport(DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClearAllPointers")]
    private static extern int ClearAllPointers_Internal();

    // Add any other necessary DllImports here...

#endif // End of Windows x64 / Editor specific DllImports


    // --- Public Static Wrapper Methods (Defined for ALL platforms) ---
    // These provide a consistent API for other scripts to call.

    public static OverlayHResult ShowOverlay(string text, bool showText, int borderWidth, Color color, int fontSize, CoVinceOverlayTextAlignment alignment)
    {
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64)
        int r = (int)(color.r * 255); int g = (int)(color.g * 255); int b = (int)(color.b * 255);
        int result = ShowOverlay_Internal(text ?? "", showText, borderWidth, r, g, b, fontSize, (int)alignment);
        if (result != 0) Debug.LogWarning($"ShowOverlay failed. HRESULT: 0x{result:X}");
        return (OverlayHResult)result;
#else
        Debug.LogWarning("NativeOverlayInterface.ShowOverlay not supported on this build target.");
        return OverlayHResult.E_NOTIMPL;
#endif
    }

    public static OverlayHResult ShowOverlayOnMonitor(int monitorIndex, string text, bool showText, int borderWidth, Color color, int fontSize, CoVinceOverlayTextAlignment alignment)
    {
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64)
        int r = (int)(color.r * 255); int g = (int)(color.g * 255); int b = (int)(color.b * 255);
        int result = ShowOverlayOnMonitor_Internal(monitorIndex, text ?? "", showText, borderWidth, r, g, b, fontSize, (int)alignment);
        if (result != 0) Debug.LogWarning($"ShowOverlayOnMonitor failed for index {monitorIndex}. HRESULT: 0x{result:X}");
        return (OverlayHResult)result;
#else
        Debug.LogWarning("NativeOverlayInterface.ShowOverlayOnMonitor not supported on this build target.");
        return OverlayHResult.E_NOTIMPL;
#endif
    }

    public static OverlayHResult HideOverlay()
    {
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64)
        int result = HideOverlay_Internal();
        if (result != 0) Debug.LogWarning($"HideOverlay failed. HRESULT: 0x{result:X}");
        return (OverlayHResult)result;
#else
        return OverlayHResult.S_OK; // Hiding non-existent overlay is fine
#endif
    }

    public static OverlayHResult ShowOverlayText(bool show)
    {
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64)
        int result = ShowOverlayText_Internal(show);
        if (result != 0) Debug.LogWarning($"ShowOverlayText failed. HRESULT: 0x{result:X}");
        return (OverlayHResult)result;
#else
        return OverlayHResult.E_NOTIMPL;
#endif
    }

    public static OverlayHResult UpdateOverlayText(string text)
    {
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64)
        int result = UpdateOverlayText_Internal(text ?? "");
        if (result != 0) Debug.LogWarning($"UpdateOverlayText failed. HRESULT: 0x{result:X}");
        return (OverlayHResult)result;
#else
        return OverlayHResult.E_NOTIMPL;
#endif
    }

    public static OverlayHResult UpdateOverlayFontSize(int fontSize)
    {
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64)
        int result = UpdateOverlayFontSize_Internal(fontSize);
        if (result != 0) Debug.LogWarning($"UpdateOverlayFontSize failed. HRESULT: 0x{result:X}");
        return (OverlayHResult)result;
#else
        return OverlayHResult.E_NOTIMPL;
#endif
    }

    public static OverlayHResult UpdateOverlayWidth(int borderWidth)
    {
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64)
        int result = UpdateOverlayWidth_Internal(borderWidth);
        if (result != 0) Debug.LogWarning($"UpdateOverlayWidth failed. HRESULT: 0x{result:X}");
        return (OverlayHResult)result;
#else
        return OverlayHResult.E_NOTIMPL;
#endif
    }

    public static OverlayHResult UpdateOverlayColor(Color color)
    {
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64)
        int r = (int)(color.r * 255); int g = (int)(color.g * 255); int b = (int)(color.b * 255);
        int result = UpdateOverlayColor_Internal(r, g, b);
        if (result != 0) Debug.LogWarning($"UpdateOverlayColor failed. HRESULT: 0x{result:X}");
        return (OverlayHResult)result;
#else
        return OverlayHResult.E_NOTIMPL;
#endif
    }

    public static OverlayHResult UpdateOverlayAlignment(CoVinceOverlayTextAlignment alignment)
    {
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64)
        int result = UpdateOverlayAlignment_Internal((int)alignment);
        if (result != 0) Debug.LogWarning($"UpdateOverlayAlignment failed. HRESULT: 0x{result:X}");
        return (OverlayHResult)result;
#else
        return OverlayHResult.E_NOTIMPL;
#endif
    }

    public static OverlayHResult AddOrUpdatePointer(string userId, string userName, int x, int y, string imagePath, int desiredWidth, int desiredHeight)
    {
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64)
        int result = AddOrUpdatePointer_Internal(userId, userName ?? "Unknown", x, y, imagePath, desiredWidth, desiredHeight);
        // Don't log warning here by default, as E_FAIL from image load is expected if file missing
        // if (result != 0 && result != (int)OverlayHResult.E_FAIL) Debug.LogWarning($"AddOrUpdatePointer returned non-success HRESULT for {userId}: 0x{result:X}");
        return (OverlayHResult)result;
#else
        Debug.LogWarning("NativeOverlayInterface.AddOrUpdatePointer not supported on this build target.");
        return OverlayHResult.E_NOTIMPL;
#endif
    }

    public static OverlayHResult RemovePointer(string userId)
    {
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64)
        int result = RemovePointer_Internal(userId);
        if (result != 0) Debug.LogWarning($"RemovePointer failed for {userId}. HRESULT: 0x{result:X}"); // S_OK expected even if not found
        return (OverlayHResult)result;
#else
         return OverlayHResult.E_NOTIMPL; // Or S_OK? E_NOTIMPL seems better.
#endif
    }

    public static OverlayHResult ClearAllPointers()
    {
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64)
        int result = ClearAllPointers_Internal();
        if (result != 0) Debug.LogWarning($"ClearAllPointers failed. HRESULT: 0x{result:X}"); // Should likely return S_OK
        return (OverlayHResult)result;
#else
        return OverlayHResult.S_OK; // Clearing non-existent pointers is fine
#endif
    }

} // End Class