using MBN_STOCK_WEBVIEW.Infrastructure;
using MBN_STOCK_WEBVIEW.LegacyApplication;
using MBN_STOCK_WEBVIEW.LegacyBridge;

namespace MBN_STOCK_WEBVIEW.LegacyParityApp;

public sealed partial class MainWindow
{
    private long _operatorSettingsRevision = 1;
    private string _operatorSettingsMessage = string.Empty;
    private LegacyOperatorSettingsMessageKind _operatorSettingsMessageKind =
        LegacyOperatorSettingsMessageKind.Neutral;
    private LegacyOperatorFolderSnapshot _designFolderSnapshot = new(
        "앱 기본값",
        IsCustom: false,
        IsValid: false,
        "확인 중");
    private LegacyOperatorFolderSnapshot _resourceFolderSnapshot = new(
        "앱 기본값",
        IsCustom: false,
        IsValid: false,
        "확인 중");
    private LegacyOperatorFolderSnapshot _backgroundFolderSnapshot = new(
        "자동",
        IsCustom: false,
        IsValid: true,
        "사용 가능");

    private void InitializeOperatorSettingsStatus(string? warningMessage)
    {
        if (!string.IsNullOrWhiteSpace(warningMessage))
        {
            _operatorSettingsMessage = warningMessage;
            _operatorSettingsMessageKind = LegacyOperatorSettingsMessageKind.Warning;
        }

        RefreshOperatorFolderSnapshots();
    }

    private async Task HandleOperatorSettingsIntentAsync(
        LegacyUiIntent intent,
        CancellationToken cancellationToken)
    {
        switch (intent)
        {
            case LegacyChooseOperatorFolderIntent choose:
                await ChooseOperatorFolderAsync(choose.Kind, cancellationToken);
                break;
            case LegacyResetOperatorFolderIntent reset:
                ResetOperatorFolder(reset.Kind);
                break;
            case LegacySetOperatorNavigationExpandedIntent navigation:
                SaveOperatorSettings(
                    _operatorSettings with
                    {
                        NavigationExpanded = navigation.Expanded
                    },
                    "저장됨");
                break;
            case LegacySetOperatorAppearanceIntent appearance:
                SaveOperatorSettings(
                    _operatorSettings with
                    {
                        ColorTheme = appearance.ColorTheme,
                        ViewMode = appearance.ViewMode,
                        StartWorkspace = appearance.StartWorkspace
                    },
                    "저장됨");
                break;
            default:
                SetOperatorSettingsMessage(
                    "지원하지 않는 설정 요청입니다.",
                    LegacyOperatorSettingsMessageKind.Error);
                break;
        }
    }

    private async Task ChooseOperatorFolderAsync(
        LegacyOperatorFolderKind kind,
        CancellationToken cancellationToken)
    {
        cancellationToken.ThrowIfCancellationRequested();
        try
        {
            var initialDirectory = ResolveOperatorFolderPickerStartDirectory(kind);
            var selectedPath = await PickOperatorFolderAsync(
                initialDirectory,
                ResolveOperatorFolderPickerTitle(kind));
            if (selectedPath is null)
            {
                return;
            }

            cancellationToken.ThrowIfCancellationRequested();
            var validationKind = ToSettingsFolderKind(kind);
            if (!LegacyOperatorFolderValidator.TryValidate(
                    validationKind,
                    selectedPath,
                    out var validated,
                    out var warningMessage) ||
                validated is null)
            {
                SetOperatorSettingsMessage(
                    warningMessage ?? "선택한 폴더를 사용할 수 없습니다.",
                    LegacyOperatorSettingsMessageKind.Warning);
                return;
            }

            var next = kind switch
            {
                LegacyOperatorFolderKind.Design => _operatorSettings with
                {
                    SceneDirectory = validated.CanonicalPath
                },
                LegacyOperatorFolderKind.Resource => _operatorSettings with
                {
                    ResourceDirectory = validated.CanonicalPath
                },
                LegacyOperatorFolderKind.Background => _operatorSettings with
                {
                    BackgroundDirectory = validated.CanonicalPath
                },
                _ => throw new ArgumentOutOfRangeException(nameof(kind))
            };
            SaveOperatorSettings(next, "저장됨 · 재시작 필요");
        }
        catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
        {
            throw;
        }
        catch
        {
            SetOperatorSettingsMessage(
                "폴더 선택 창을 열거나 선택 결과를 저장하지 못했습니다.",
                LegacyOperatorSettingsMessageKind.Error);
        }
    }

    private string? ResolveOperatorFolderPickerStartDirectory(
        LegacyOperatorFolderKind kind)
    {
        var preferredPath = kind switch
        {
            LegacyOperatorFolderKind.Design =>
                _operatorSettings.SceneDirectory ??
                Path.Combine(AppContext.BaseDirectory, "Cuts"),
            LegacyOperatorFolderKind.Resource =>
                _operatorSettings.ResourceDirectory ??
                Path.Combine(AppContext.BaseDirectory, "Res"),
            LegacyOperatorFolderKind.Background =>
                _operatorSettings.BackgroundDirectory ??
                ResolveAutomaticBackgroundDirectory(),
            _ => throw new ArgumentOutOfRangeException(nameof(kind))
        };

        return FindNearestExistingDirectory(preferredPath) ??
            FindNearestExistingDirectory(AppContext.BaseDirectory);
    }

    private string ResolveAutomaticBackgroundDirectory()
    {
        var sceneDirectory = _operatorSettings.SceneDirectory ??
            Path.Combine(AppContext.BaseDirectory, "Cuts");
        var canonicalSceneDirectory = Path.TrimEndingDirectorySeparator(
            Path.GetFullPath(sceneDirectory));
        var sceneParent = Path.GetDirectoryName(canonicalSceneDirectory);
        return Path.Combine(
            sceneParent ?? AppContext.BaseDirectory,
            "배경");
    }

    private static string? FindNearestExistingDirectory(string? path)
    {
        if (string.IsNullOrWhiteSpace(path) ||
            !Path.IsPathFullyQualified(path))
        {
            return null;
        }

        try
        {
            for (var candidate = new DirectoryInfo(Path.GetFullPath(path));
                 candidate is not null;
                 candidate = candidate.Parent)
            {
                if (candidate.Exists)
                {
                    return candidate.FullName;
                }
            }
        }
        catch (Exception exception) when (
            exception is ArgumentException or
            IOException or
            NotSupportedException or
            System.Security.SecurityException or
            UnauthorizedAccessException)
        {
            return null;
        }

        return null;
    }

    private static string ResolveOperatorFolderPickerTitle(
        LegacyOperatorFolderKind kind) => kind switch
        {
            LegacyOperatorFolderKind.Design => "폴더 선택 - 디자인",
            LegacyOperatorFolderKind.Resource => "폴더 선택 - 설정",
            LegacyOperatorFolderKind.Background => "폴더 선택 - 배경",
            _ => throw new ArgumentOutOfRangeException(nameof(kind))
        };

    private void ResetOperatorFolder(LegacyOperatorFolderKind kind)
    {
        var next = kind switch
        {
            LegacyOperatorFolderKind.Design => _operatorSettings with
            {
                SceneDirectory = null
            },
            LegacyOperatorFolderKind.Resource => _operatorSettings with
            {
                ResourceDirectory = null
            },
            LegacyOperatorFolderKind.Background => _operatorSettings with
            {
                BackgroundDirectory = null
            },
            _ => throw new ArgumentOutOfRangeException(nameof(kind))
        };
        SaveOperatorSettings(
            next,
            "초기화됨 · 재시작 필요");
    }

    private void SaveOperatorSettings(
        LegacyOperatorSettings next,
        string successMessage)
    {
        var result = _operatorSettingsStore.Save(next);
        if (!result.Succeeded || result.SavedSettings is null)
        {
            // The Web surface applies the navigation preference optimistically.
            // Advance the snapshot revision even though persistence failed so the
            // next state re-applies the still-authoritative native value.
            Interlocked.Increment(ref _operatorSettingsRevision);
            SetOperatorSettingsMessage(
                result.WarningMessage ?? "설정을 저장하지 못했습니다.",
                LegacyOperatorSettingsMessageKind.Error);
            return;
        }

        _operatorSettings = result.SavedSettings;
        Interlocked.Increment(ref _operatorSettingsRevision);
        RefreshOperatorFolderSnapshots();
        SetOperatorSettingsMessage(
            successMessage,
            LegacyOperatorSettingsMessageKind.Success);
    }

    private void SetOperatorSettingsMessage(
        string message,
        LegacyOperatorSettingsMessageKind kind)
    {
        _operatorSettingsMessage = message;
        _operatorSettingsMessageKind = kind;
    }

    private void ReconcileRejectedOperatorSettingsIntent(
        LegacyUiIntent intent,
        string message)
    {
        if (!IsOperatorSettingsIntent(intent))
        {
            return;
        }

        ReconcileRejectedOperatorSettingsIntent(message);
    }

    private void ReconcileRejectedOperatorSettingsIntent(string message)
    {
        // Web applies the navigation switch optimistically. A new native revision
        // makes every early rejection re-project the persisted authoritative value.
        Interlocked.Increment(ref _operatorSettingsRevision);
        SetOperatorSettingsMessage(
            message,
            LegacyOperatorSettingsMessageKind.Warning);
    }

    private void RefreshOperatorFolderSnapshots()
    {
        _designFolderSnapshot = CreateOperatorFolderSnapshot(
            LegacyOperatorSettingsFolderKind.Scene,
            _operatorSettings.SceneDirectory,
            "앱 기본값");
        _resourceFolderSnapshot = CreateOperatorFolderSnapshot(
            LegacyOperatorSettingsFolderKind.Resource,
            _operatorSettings.ResourceDirectory,
            "앱 기본값");
        _backgroundFolderSnapshot = _operatorSettings.BackgroundDirectory is null
            ? new LegacyOperatorFolderSnapshot(
                "자동",
                IsCustom: false,
                IsValid: true,
                "사용 가능")
            : CreateOperatorFolderSnapshot(
                LegacyOperatorSettingsFolderKind.Background,
                _operatorSettings.BackgroundDirectory,
                "자동");
    }

    private static LegacyOperatorFolderSnapshot CreateOperatorFolderSnapshot(
        LegacyOperatorSettingsFolderKind kind,
        string? configuredPath,
        string defaultDisplay)
    {
        if (configuredPath is null)
        {
            var defaultPath = kind switch
            {
                LegacyOperatorSettingsFolderKind.Scene =>
                    Path.Combine(AppContext.BaseDirectory, "Cuts"),
                LegacyOperatorSettingsFolderKind.Resource =>
                    Path.Combine(AppContext.BaseDirectory, "Res"),
                _ => null
            };
            if (defaultPath is null ||
                !LegacyOperatorFolderValidator.TryValidate(
                    kind,
                    defaultPath,
                    out var defaultFolder,
                    out _) ||
                defaultFolder is null)
            {
                return new LegacyOperatorFolderSnapshot(
                    defaultDisplay,
                    IsCustom: false,
                    IsValid: false,
                    "기본 폴더 확인 필요");
            }

            return new LegacyOperatorFolderSnapshot(
                defaultDisplay,
                IsCustom: false,
                IsValid: true,
                "사용 가능");
        }

        var validation = LegacyOperatorFolderValidator.Validate(kind, configuredPath);
        if (!validation.IsValid || validation.Folder is null)
        {
            return new LegacyOperatorFolderSnapshot(
                LegacyOperatorFolderValidator.AbbreviateForDisplay(configuredPath),
                IsCustom: true,
                IsValid: false,
                "폴더 확인 필요");
        }

        return new LegacyOperatorFolderSnapshot(
            validation.Folder.AbbreviatedPath,
            IsCustom: true,
            IsValid: true,
            "사용 가능");
    }

    private LegacyOperatorSettingsSnapshot CreateOperatorSettingsSnapshot() => new(
        Volatile.Read(ref _operatorSettingsRevision),
        _designFolderSnapshot,
        _resourceFolderSnapshot,
        _backgroundFolderSnapshot,
        _operatorSettings.NavigationExpanded,
        _operatorSettings.ColorTheme,
        _operatorSettings.ViewMode,
        _operatorSettings.StartWorkspace,
        RestartRequired: !OperatorFolderSettingsEqual(
            _operatorSettings,
            _appliedOperatorSettings),
        _operatorSettingsMessage,
        _operatorSettingsMessageKind,
        ResolveApplicationVersion(),
        ResolveDatabaseHealthLabel(
            Volatile.Read(ref _oracleDatabaseHealthState)),
        ResolveDatabaseHealthLabel(
            Volatile.Read(ref _mariaDatabaseHealthState)),
        DatabasePollingSeconds: (int)DatabaseHealthPollingInterval.TotalSeconds);

    private string ResolveDatabaseHealthLabel(int rawState)
    {
        if (rawState < 0)
        {
            return _databaseRuntime is null ? "설정 안 됨" : "점검 대기";
        }

        return (DatabaseHealthState)rawState switch
        {
            DatabaseHealthState.NotConfigured => "설정 안 됨",
            DatabaseHealthState.Healthy => "연결됨",
            DatabaseHealthState.Unhealthy => "연결 끊김",
            DatabaseHealthState.TimedOut => "응답 지연",
            _ => "확인 필요"
        };
    }

    private static bool OperatorFolderSettingsEqual(
        LegacyOperatorSettings left,
        LegacyOperatorSettings right) =>
        string.Equals(
            left.SceneDirectory,
            right.SceneDirectory,
            StringComparison.OrdinalIgnoreCase) &&
        string.Equals(
            left.ResourceDirectory,
            right.ResourceDirectory,
            StringComparison.OrdinalIgnoreCase) &&
        string.Equals(
            left.BackgroundDirectory,
            right.BackgroundDirectory,
            StringComparison.OrdinalIgnoreCase);

    private static string ResolveApplicationVersion()
    {
        var version = typeof(MainWindow).Assembly.GetName().Version;
        return version is null
            ? "확인 불가"
            : $"{version.Major}.{version.Minor}.{Math.Max(0, version.Build)}";
    }

    private static LegacyOperatorSettingsFolderKind ToSettingsFolderKind(
        LegacyOperatorFolderKind kind) => kind switch
        {
            LegacyOperatorFolderKind.Design => LegacyOperatorSettingsFolderKind.Scene,
            LegacyOperatorFolderKind.Resource => LegacyOperatorSettingsFolderKind.Resource,
            LegacyOperatorFolderKind.Background => LegacyOperatorSettingsFolderKind.Background,
            _ => throw new ArgumentOutOfRangeException(nameof(kind))
        };

}
