namespace DragonISO.App.Services;

// /presets/* route handlers.
//
//   POST /presets/refresh-discovery â†’ RefreshDiscovery
//   POST /presets/stop-all          â†’ StopAllAsync
//   POST /presets/{name}/apply      â†’ ApplyPresetAsync
public sealed partial class ControlSurfaceServer
{
    private object RefreshDiscovery()
    {
        _controller.RefreshDiscovery();
        return new { ok = true, action = "refresh-discovery" };
    }

    private async Task<object> StopAllAsync()
    {
        var vm = _viewModel();
        if (vm is null) return new { ok = false, error = "view-model not ready" };
        var dispatcher = System.Windows.Application.Current?.Dispatcher;
        if (dispatcher is null) return new { ok = false, error = "dispatcher not ready" };

        // Snapshot the enabled set on the UI thread â€” ObservableCollection
        // isn't safe to enumerate from a thread-pool task, and reading the
        // IsEnabled property indirectly walks the data-binding system.
        var enabled = await dispatcher.InvokeAsync(() =>
            vm.Participants.Where(p => p.IsEnabled).ToArray());

        foreach (var p in enabled)
        {
            try { await _controller.DisableIsoAsync(p.Id, CancellationToken.None); }
            catch { /* defensive */ }
            await dispatcher.InvokeAsync(() => p.IsEnabled = false);
        }
        return new { ok = true, action = "stop-all", count = enabled.Length };
    }

    private async Task<object> ApplyPresetAsync(string path)
    {
        // path = /presets/<name>/apply
        var segments = path.Split('/', StringSplitOptions.RemoveEmptyEntries);
        if (segments.Length != 3 || segments[0] != "presets" || segments[2] != "apply")
            return NotFound();
        var name = Uri.UnescapeDataString(segments[1]);
        var preset = OperatorPresetStore.Find(name);
        if (preset is null) return new { ok = false, error = "preset not found", name };

        var vm = _viewModel();
        var dispatcher = System.Windows.Application.Current?.Dispatcher;
        if (vm is null || dispatcher is null)
            return new { ok = false, error = "view-model not ready" };

        // Snapshot participants on the UI thread â€” ObservableCollection
        // enumeration and ParticipantViewModel state reads both need to
        // happen there. PresetApplier marshals subsequent property writes
        // via the dispatcher.
        var snapshot = await dispatcher.InvokeAsync(() => vm.Participants.ToList());

        var result = await PresetApplier.ApplyAsync(
            preset, snapshot, _controller, dispatcher);

        return new
        {
            ok = true,
            name = preset.Name,
            matched = result.Matched,
            changed = result.Changed,
            skipped = result.Skipped,
        };
    }
}
