using MBN_STOCK_WEBVIEW.Core.Playout;
using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml.Controls;
using WinRT.Interop;

namespace MBN_STOCK_WEBVIEW.LegacyParityApp;

public sealed partial class MainWindow
{
    private AppWindow? _closeConfirmationAppWindow;
    private int _closeConfirmationPending;
    private int _closeConfirmed;

    private void EnsureCloseConfirmationAttached()
    {
        if (_closeConfirmationAppWindow is not null)
        {
            return;
        }

        try
        {
            var windowHandle = WindowNative.GetWindowHandle(this);
            var windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(windowHandle);
            var appWindow = AppWindow.GetFromWindowId(windowId);
            appWindow.Closing += OnAppWindowClosing;
            _closeConfirmationAppWindow = appWindow;
        }
        catch
        {
            // The constructor can run before the native window exists. Root.Loaded
            // retries the attachment after WinUI has created it.
        }
    }

    private async void OnAppWindowClosing(AppWindow sender, AppWindowClosingEventArgs args)
    {
        if (Volatile.Read(ref _closeConfirmed) != 0)
        {
            return;
        }

        // AppWindow.Closing has no deferral. Cancel synchronously and close a second
        // time only after the operator explicitly confirms. The default is Cancel,
        // matching MainForm_FormClosing's default No choice.
        args.Cancel = true;
        if (Interlocked.CompareExchange(ref _closeConfirmationPending, 1, 0) != 0)
        {
            return;
        }

        try
        {
            if (Root.XamlRoot is null)
            {
                return;
            }

            var dialog = new ContentDialog
            {
                XamlRoot = Root.XamlRoot,
                Title = "매일경제TV",
                Content = BuildCloseConfirmationMessage(),
                PrimaryButtonText = "예",
                CloseButtonText = "아니요",
                DefaultButton = ContentDialogButton.Close
            };

            var result = await dialog.ShowAsync();
            if (result != ContentDialogResult.Primary)
            {
                return;
            }

            Interlocked.Exchange(ref _closeConfirmed, 1);
            Close();
        }
        catch
        {
            // If the confirmation surface cannot be shown, keep the application open.
        }
        finally
        {
            Interlocked.Exchange(ref _closeConfirmationPending, 0);
        }
    }

    private string BuildCloseConfirmationMessage()
    {
        var status = _playoutEngine?.Status;
        var workflow = _playoutWorkflow?.State;
        var hasPreparedScene = !string.IsNullOrWhiteSpace(status?.PreparedSceneName) ||
            !string.IsNullOrWhiteSpace(workflow?.PreparedCutCode);
        var hasOnAirScene = !string.IsNullOrWhiteSpace(status?.OnAirSceneName) ||
            !string.IsNullOrWhiteSpace(workflow?.OnAirCutCode);
        var commandPending = Volatile.Read(ref _playoutBusy) != 0 ||
            status?.IsPlayCompletionPending == true ||
            status?.IsTakeOutCompletionPending == true;
        var outcomeUnknown = Volatile.Read(ref _playoutQuarantined) != 0 ||
            status?.State == PlayoutConnectionState.OutcomeUnknown;

        if (outcomeUnknown)
        {
            return "송출 결과를 확정할 수 없는 상태입니다. PGM과 Network Monitoring을 확인한 뒤 종료하세요. " +
                "종료 과정에서는 TAKE OUT을 자동 실행하지 않습니다. 그래도 종료하시겠습니까?";
        }

        if (commandPending)
        {
            return "송출 명령 또는 callback 처리가 진행 중입니다. 결과를 확인한 뒤 종료하는 것이 안전합니다. " +
                "그래도 종료하시겠습니까?";
        }

        if (hasOnAirScene || hasPreparedScene)
        {
            return "PREPARED 또는 PROGRAM 장면이 남아 있습니다. 필요한 경우 먼저 TAKE OUT을 실행하고 " +
                "PGM을 확인하세요. 종료 과정에서는 TAKE OUT을 자동 실행하지 않습니다. 그래도 종료하시겠습니까?";
        }

        return "프로그램을 종료하겠습니까?";
    }

    private void DetachCloseConfirmation()
    {
        var appWindow = Interlocked.Exchange(ref _closeConfirmationAppWindow, null);
        if (appWindow is not null)
        {
            appWindow.Closing -= OnAppWindowClosing;
        }
    }
}
