import React, { act } from 'react';
import { createRoot } from 'react-dom/client';

import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

import {
  type RuntimeProviderManagementActions,
  type RuntimeProviderManagementState,
  useRuntimeProviderManagement,
} from '../../../../src/features/runtime-provider-management/renderer/hooks/useRuntimeProviderManagement';
import {
  getStoredCreateTeamModel,
  getStoredCreateTeamProvider,
} from '../../../../src/renderer/services/createTeamPreferences';

import type {
  RuntimeProviderConnectionDto,
  RuntimeProviderDirectoryEntryDto,
  RuntimeProviderManagementDirectoryResponse,
  RuntimeProviderManagementModelTestResponse,
  RuntimeProviderManagementProviderResponse,
  RuntimeProviderManagementSetupFormResponse,
  RuntimeProviderManagementViewDto,
  RuntimeProviderManagementViewResponse,
} from '../../../../src/features/runtime-provider-management/contracts';
import type { ElectronAPI } from '../../../../src/shared/types/api';

function installRuntimeProviderManagementApi(
  response: RuntimeProviderManagementModelTestResponse
): void {
  Object.defineProperty(window, 'electronAPI', {
    configurable: true,
    value: {
      runtimeProviderManagement: {
        testModel: vi.fn(() => Promise.resolve(response)),
      },
    } as unknown as ElectronAPI,
  });
}

function createRuntimeView(
  providers: readonly RuntimeProviderConnectionDto[] = []
): RuntimeProviderManagementViewDto {
  return {
    runtimeId: 'opencode',
    title: 'OpenCode',
    runtime: {
      state: 'ready',
      cliPath: '/opt/homebrew/bin/opencode',
      version: '1.0.0',
      managedProfile: 'active',
      localAuth: 'synced',
    },
    providers,
    defaultModel: null,
    fallbackModel: null,
    diagnostics: [],
  };
}

function createOpenAiLocalProvider(): RuntimeProviderConnectionDto {
  return {
    providerId: 'openai',
    displayName: 'OpenAI',
    state: 'connected',
    ownership: ['local'],
    recommended: true,
    modelCount: 12,
    defaultModelId: null,
    authMethods: ['oauth'],
    actions: [],
    detail: 'Connected via local OpenCode credential',
  };
}

function createOpenAiLocalDirectoryEntry(): RuntimeProviderDirectoryEntryDto {
  return {
    ...createOpenAiLocalProvider(),
    setupKind: 'connected',
    sources: ['opencode-provider'],
    sourceLabel: 'OpenCode catalog',
    providerSource: 'models.dev',
    metadata: {
      hasKnownModels: true,
      requiresManualConfig: false,
      supportedInlineAuth: false,
      configuredAuthless: false,
    },
  };
}

describe('useRuntimeProviderManagement', () => {
  let host: HTMLDivElement;
  let state: RuntimeProviderManagementState | null = null;
  let actions: RuntimeProviderManagementActions | null = null;

  function Harness(): React.ReactElement {
    const hook = useRuntimeProviderManagement({
      runtimeId: 'opencode',
      enabled: false,
    });
    state = hook[0];
    actions = hook[1];
    return React.createElement('div');
  }

  function EnabledHarness(props: { projectPath?: string | null }): React.ReactElement {
    const hook = useRuntimeProviderManagement({
      runtimeId: 'opencode',
      enabled: true,
      projectPath: props.projectPath,
    });
    state = hook[0];
    actions = hook[1];
    return React.createElement('div');
  }

  function ConfigurableHarness(props: {
    enabled: boolean;
    projectPath?: string | null;
  }): React.ReactElement {
    const hook = useRuntimeProviderManagement({
      runtimeId: 'opencode',
      enabled: props.enabled,
      projectPath: props.projectPath,
    });
    state = hook[0];
    actions = hook[1];
    return React.createElement('div');
  }

  beforeEach(() => {
    vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);
    host = document.createElement('div');
    document.body.appendChild(host);
    window.localStorage.clear();
    state = null;
    actions = null;
  });

  afterEach(() => {
    Reflect.deleteProperty(window, 'electronAPI');
    document.body.innerHTML = '';
    vi.unstubAllGlobals();
  });

  it('uses a clicked model as the app default for new teams without a global success banner', async () => {
    const modelId = 'openrouter/openai/gpt-oss-20b:free';
    const root = createRoot(host);
    await act(async () => {
      root.render(React.createElement(Harness));
      await Promise.resolve();
    });

    act(() => {
      actions?.useModelForNewTeams(modelId);
    });

    expect(state?.selectedModelId).toBe(modelId);
    expect(state?.successMessage).toBeNull();
    expect(getStoredCreateTeamProvider()).toBe('opencode');
    expect(getStoredCreateTeamModel('opencode')).toBe(modelId);
  });

  it('passes projectPath to the runtime provider management API', async () => {
    const loadView = vi.fn(() =>
      Promise.resolve({
        schemaVersion: 1,
        runtimeId: 'opencode',
        view: createRuntimeView(),
      })
    );
    Object.defineProperty(window, 'electronAPI', {
      configurable: true,
      value: {
        runtimeProviderManagement: {
          loadView,
        },
      } as unknown as ElectronAPI,
    });

    const root = createRoot(host);
    await act(async () => {
      root.render(React.createElement(EnabledHarness, { projectPath: '/tmp/project-a' }));
      await Promise.resolve();
    });

    expect(loadView).toHaveBeenCalledWith({
      runtimeId: 'opencode',
      projectPath: '/tmp/project-a',
    });
  });

  it('clears structured errors and stale provider state when disabled', async () => {
    const loadView = vi.fn(() =>
      Promise.resolve({
        schemaVersion: 1,
        runtimeId: 'opencode',
        error: {
          code: 'runtime-misconfigured',
          message: 'OpenCode provider settings are using the wrong runtime binary.',
          recoverable: true,
          diagnostics: {
            summary: 'OpenCode provider settings are using the wrong runtime binary.',
            likelyCause:
              'The app resolved the OpenCode CLI itself as the Agent Teams runtime binary.',
            binaryPath: '/opt/homebrew/bin/opencode',
            command:
              '/opt/homebrew/bin/opencode runtime providers view --runtime opencode --json --compact',
            projectPath: null,
            exitCode: null,
            stderrPreview: null,
            stdoutPreview: null,
            hints: ['Those environment variables must not point to opencode.'],
          },
        },
      })
    );
    Object.defineProperty(window, 'electronAPI', {
      configurable: true,
      value: {
        runtimeProviderManagement: {
          loadView,
        },
      } as unknown as ElectronAPI,
    });

    const root = createRoot(host);
    await act(async () => {
      root.render(React.createElement(ConfigurableHarness, { enabled: true }));
      await Promise.resolve();
    });

    await act(async () => {
      await vi.waitFor(() => {
        expect(state?.error ?? '').toContain('wrong runtime binary');
      });
    });

    expect(state?.errorDiagnostics?.binaryPath).toBe('/opt/homebrew/bin/opencode');

    await act(async () => {
      root.render(React.createElement(ConfigurableHarness, { enabled: false }));
      await Promise.resolve();
    });

    expect(state?.view).toBeNull();
    expect(state?.selectedProviderId).toBeNull();
    expect(state?.error).toBeNull();
    expect(state?.errorDiagnostics).toBeNull();
    expect(state?.loading).toBe(false);
  });

  it('ignores pending directory and setup-form responses after being disabled', async () => {
    let resolveDirectory:
      | ((response: RuntimeProviderManagementDirectoryResponse) => void)
      | null = null;
    let resolveSetupForm:
      | ((response: RuntimeProviderManagementSetupFormResponse) => void)
      | null = null;
    const directoryResponse = new Promise<RuntimeProviderManagementDirectoryResponse>(
      (resolve) => {
        resolveDirectory = resolve;
      }
    );
    const setupFormResponse = new Promise<RuntimeProviderManagementSetupFormResponse>(
      (resolve) => {
        resolveSetupForm = resolve;
      }
    );
    const loadView = vi.fn(() =>
      Promise.resolve({
        schemaVersion: 1,
        runtimeId: 'opencode',
        view: createRuntimeView(),
      })
    );
    const loadProviderDirectory = vi.fn(() => directoryResponse);
    const loadSetupForm = vi.fn(() => setupFormResponse);
    Object.defineProperty(window, 'electronAPI', {
      configurable: true,
      value: {
        runtimeProviderManagement: {
          loadView,
          loadProviderDirectory,
          loadSetupForm,
        },
      } as unknown as ElectronAPI,
    });

    const root = createRoot(host);
    await act(async () => {
      root.render(React.createElement(ConfigurableHarness, { enabled: true }));
      await Promise.resolve();
    });

    await act(async () => {
      await vi.waitFor(() => {
        expect(loadProviderDirectory).toHaveBeenCalled();
      });
      actions?.startConnect('openrouter');
    });
    await act(async () => {
      await vi.waitFor(() => {
        expect(loadSetupForm).toHaveBeenCalled();
      });
    });

    await act(async () => {
      root.render(React.createElement(ConfigurableHarness, { enabled: false }));
      await Promise.resolve();
    });

    await act(async () => {
      resolveDirectory?.({
        schemaVersion: 1,
        runtimeId: 'opencode',
        directory: {
          runtimeId: 'opencode',
          totalCount: 1,
          returnedCount: 1,
          query: null,
          filter: 'all',
          limit: 50,
          cursor: null,
          nextCursor: null,
          entries: [createOpenAiLocalDirectoryEntry()],
          diagnostics: [],
          fetchedAt: '2026-05-22T00:00:00.000Z',
        },
      });
      resolveSetupForm?.({
        schemaVersion: 1,
        runtimeId: 'opencode',
        setupForm: {
          runtimeId: 'opencode',
          providerId: 'openrouter',
          displayName: 'OpenRouter',
          method: 'api',
          supported: true,
          title: 'Connect OpenRouter',
          description: null,
          submitLabel: 'Connect',
          disabledReason: null,
          source: 'curated',
          secret: {
            key: 'key',
            label: 'API key',
            placeholder: 'Paste API key',
            required: true,
          },
          prompts: [],
        },
      });
      await Promise.resolve();
      await Promise.resolve();
    });

    expect(state?.directoryEntries).toEqual([]);
    expect(state?.directoryLoaded).toBe(false);
    expect(state?.setupForm).toBeNull();
    expect(state?.activeFormProviderId).toBeNull();
    expect(state?.setupFormLoading).toBe(false);
  });

  it('ignores stale provider views after project context changes', async () => {
    let resolveProjectA:
      | ((response: {
          schemaVersion: 1;
          runtimeId: 'opencode';
          view: RuntimeProviderManagementViewDto;
        }) => void)
      | null = null;
    const projectAResponse = new Promise<{
      schemaVersion: 1;
      runtimeId: 'opencode';
      view: RuntimeProviderManagementViewDto;
    }>((resolve) => {
      resolveProjectA = resolve;
    });
    const loadView = vi.fn((input: { projectPath?: string | null }) => {
      if (input.projectPath === '/tmp/project-a') {
        return projectAResponse;
      }
      return Promise.resolve({
        schemaVersion: 1,
        runtimeId: 'opencode',
        view: {
          ...createRuntimeView(),
          projectPath: '/tmp/project-b',
          defaultModel: 'opencode/project-b',
        },
      });
    });
    Object.defineProperty(window, 'electronAPI', {
      configurable: true,
      value: {
        runtimeProviderManagement: {
          loadView,
        },
      } as unknown as ElectronAPI,
    });

    const root = createRoot(host);
    await act(async () => {
      root.render(React.createElement(EnabledHarness, { projectPath: '/tmp/project-a' }));
      await Promise.resolve();
    });
    await act(async () => {
      root.render(React.createElement(EnabledHarness, { projectPath: '/tmp/project-b' }));
      await Promise.resolve();
    });

    expect(state?.view?.projectPath).toBe('/tmp/project-b');

    await act(async () => {
      resolveProjectA?.({
        schemaVersion: 1,
        runtimeId: 'opencode',
        view: {
          ...createRuntimeView(),
          projectPath: '/tmp/project-a',
          defaultModel: 'opencode/project-a',
        },
      });
      await Promise.resolve();
    });

    expect(state?.view?.projectPath).toBe('/tmp/project-b');
    expect(state?.view?.defaultModel).toBe('opencode/project-b');

    await act(async () => {
      root.unmount();
      await Promise.resolve();
    });
  });

  it('restarts provider directory loading when project context changes while loading', async () => {
    let resolveProjectADirectory:
      | ((response: RuntimeProviderManagementDirectoryResponse) => void)
      | null = null;
    let resolveProjectBDirectory:
      | ((response: RuntimeProviderManagementDirectoryResponse) => void)
      | null = null;
    const projectBEntry: RuntimeProviderDirectoryEntryDto = {
      ...createOpenAiLocalDirectoryEntry(),
      providerId: 'project-b-provider',
      displayName: 'Project B Provider',
    };
    const loadView = vi.fn((input: { projectPath?: string | null }) =>
      Promise.resolve({
        schemaVersion: 1,
        runtimeId: 'opencode',
        view: {
          ...createRuntimeView(),
          projectPath: input.projectPath ?? null,
        },
      })
    );
    const loadProviderDirectory = vi.fn((input: { projectPath?: string | null }) => {
      if (input.projectPath === '/tmp/project-a') {
        return new Promise<RuntimeProviderManagementDirectoryResponse>((resolve) => {
          resolveProjectADirectory = resolve;
        });
      }
      return new Promise<RuntimeProviderManagementDirectoryResponse>((resolve) => {
        resolveProjectBDirectory = resolve;
      });
    });
    Object.defineProperty(window, 'electronAPI', {
      configurable: true,
      value: {
        runtimeProviderManagement: {
          loadView,
          loadProviderDirectory,
        },
      } as unknown as ElectronAPI,
    });

    const root = createRoot(host);
    await act(async () => {
      root.render(React.createElement(EnabledHarness, { projectPath: '/tmp/project-a' }));
      await Promise.resolve();
    });
    await act(async () => {
      await new Promise((resolve) => window.setTimeout(resolve, 10));
      await vi.waitFor(() => {
        expect(loadProviderDirectory).toHaveBeenCalledWith({
          runtimeId: 'opencode',
          projectPath: '/tmp/project-a',
          query: null,
          filter: 'all',
          limit: 50,
          cursor: null,
          refresh: false,
        });
      });
    });

    await act(async () => {
      root.render(React.createElement(EnabledHarness, { projectPath: '/tmp/project-b' }));
      await Promise.resolve();
    });
    await act(async () => {
      await new Promise((resolve) => window.setTimeout(resolve, 10));
      await vi.waitFor(() => {
        expect(loadProviderDirectory).toHaveBeenCalledWith({
          runtimeId: 'opencode',
          projectPath: '/tmp/project-b',
          query: null,
          filter: 'all',
          limit: 50,
          cursor: null,
          refresh: false,
        });
      });
    });

    await act(async () => {
      resolveProjectBDirectory?.({
        schemaVersion: 1,
        runtimeId: 'opencode',
        directory: {
          runtimeId: 'opencode',
          totalCount: 1,
          returnedCount: 1,
          query: null,
          filter: 'all',
          limit: 50,
          cursor: null,
          nextCursor: null,
          fetchedAt: '2026-05-22T00:00:00.000Z',
          entries: [projectBEntry],
          diagnostics: [],
        },
      });
      await Promise.resolve();
    });

    expect(state?.directoryEntries.map((entry) => entry.providerId)).toEqual([
      'project-b-provider',
    ]);

    await act(async () => {
      resolveProjectADirectory?.({
        schemaVersion: 1,
        runtimeId: 'opencode',
        directory: {
          runtimeId: 'opencode',
          totalCount: 1,
          returnedCount: 1,
          query: null,
          filter: 'all',
          limit: 50,
          cursor: null,
          nextCursor: null,
          fetchedAt: '2026-05-22T00:00:00.000Z',
          entries: [createOpenAiLocalDirectoryEntry()],
          diagnostics: [],
        },
      });
      await Promise.resolve();
    });

    expect(state?.directoryEntries.map((entry) => entry.providerId)).toEqual([
      'project-b-provider',
    ]);

    await act(async () => {
      root.unmount();
      await Promise.resolve();
    });
  });

  it('drops stale model probe results after project context changes', async () => {
    const modelId = 'llama.cpp/qwen-test:0.5b';
    let resolveProbe: ((value: RuntimeProviderManagementModelTestResponse) => void) | null = null;
    const loadView = vi.fn((input: { projectPath?: string | null }) =>
      Promise.resolve({
        schemaVersion: 1,
        runtimeId: 'opencode',
        view: {
          ...createRuntimeView(),
          projectPath: input.projectPath ?? null,
          defaultModel: input.projectPath === '/tmp/project-b' ? 'opencode/project-b' : null,
        },
      })
    );
    const testModel = vi.fn(
      () =>
        new Promise<RuntimeProviderManagementModelTestResponse>((resolve) => {
          resolveProbe = resolve;
        })
    );
    Object.defineProperty(window, 'electronAPI', {
      configurable: true,
      value: {
        runtimeProviderManagement: {
          loadView,
          testModel,
        },
      } as unknown as ElectronAPI,
    });

    const root = createRoot(host);
    await act(async () => {
      root.render(React.createElement(EnabledHarness, { projectPath: '/tmp/project-a' }));
      await Promise.resolve();
    });

    let probe: Promise<void> | null = null;
    await act(async () => {
      probe = actions?.testModel('llama.cpp', modelId) ?? null;
      await Promise.resolve();
    });

    expect(testModel).toHaveBeenCalledWith({
      runtimeId: 'opencode',
      providerId: 'llama.cpp',
      modelId,
      projectPath: '/tmp/project-a',
    });
    expect(state?.testingModelIds).toEqual([modelId]);

    await act(async () => {
      root.render(React.createElement(EnabledHarness, { projectPath: '/tmp/project-b' }));
      await Promise.resolve();
    });

    expect(state?.view?.projectPath).toBe('/tmp/project-b');
    expect(state?.testingModelIds).toEqual([]);

    await act(async () => {
      resolveProbe?.({
        schemaVersion: 1,
        runtimeId: 'opencode',
        result: {
          providerId: 'llama.cpp',
          modelId,
          ok: true,
          availability: 'available',
          message: 'Stale project A probe passed',
          diagnostics: [],
        },
      });
      await probe;
    });

    expect(state?.view?.projectPath).toBe('/tmp/project-b');
    expect(state?.modelResults[modelId]).toBeUndefined();

    await act(async () => {
      root.unmount();
      await Promise.resolve();
    });
  });

  it('drops stale set-default responses after project context changes', async () => {
    const projectAModelId = 'llama.cpp/project-a:0.5b';
    let resolveSetDefault: ((value: RuntimeProviderManagementViewResponse) => void) | null = null;
    const loadView = vi.fn((input: { projectPath?: string | null }) =>
      Promise.resolve({
        schemaVersion: 1,
        runtimeId: 'opencode',
        view: {
          ...createRuntimeView(),
          projectPath: input.projectPath ?? null,
          defaultModel: input.projectPath === '/tmp/project-b' ? 'opencode/project-b' : null,
        },
      })
    );
    const setDefaultModel = vi.fn(
      () =>
        new Promise<RuntimeProviderManagementViewResponse>((resolve) => {
          resolveSetDefault = resolve;
        })
    );
    Object.defineProperty(window, 'electronAPI', {
      configurable: true,
      value: {
        runtimeProviderManagement: {
          loadView,
          setDefaultModel,
        },
      } as unknown as ElectronAPI,
    });

    const root = createRoot(host);
    await act(async () => {
      root.render(React.createElement(EnabledHarness, { projectPath: '/tmp/project-a' }));
      await Promise.resolve();
    });

    let setDefault: Promise<void> | null = null;
    await act(async () => {
      setDefault = actions?.setDefaultModel('llama.cpp', projectAModelId, 'project') ?? null;
      await Promise.resolve();
    });

    expect(setDefaultModel).toHaveBeenCalledWith({
      runtimeId: 'opencode',
      providerId: 'llama.cpp',
      modelId: projectAModelId,
      probe: true,
      scope: 'project',
      projectPath: '/tmp/project-a',
    });
    expect(state?.savingDefaultModelId).toBe(projectAModelId);

    await act(async () => {
      root.render(React.createElement(EnabledHarness, { projectPath: '/tmp/project-b' }));
      await Promise.resolve();
    });

    expect(state?.view?.projectPath).toBe('/tmp/project-b');
    expect(state?.savingDefaultModelId).toBeNull();

    await act(async () => {
      resolveSetDefault?.({
        schemaVersion: 1,
        runtimeId: 'opencode',
        view: {
          ...createRuntimeView(),
          projectPath: '/tmp/project-a',
          defaultModel: projectAModelId,
        },
      });
      await setDefault;
    });

    expect(state?.view?.projectPath).toBe('/tmp/project-b');
    expect(state?.view?.defaultModel).toBe('opencode/project-b');
    expect(state?.selectedModelId).toBeNull();
    expect(state?.successMessage).toBeNull();

    await act(async () => {
      root.unmount();
      await Promise.resolve();
    });
  });

  it('clears pending provider save state after project context changes', async () => {
    const connectedProvider: RuntimeProviderConnectionDto = {
      ...createOpenAiLocalProvider(),
      ownership: ['managed'],
      detail: 'Connected via managed OpenCode credential',
    };
    let resolveConnect: ((value: RuntimeProviderManagementProviderResponse) => void) | null =
      null;
    const loadView = vi.fn((input: { projectPath?: string | null }) =>
      Promise.resolve({
        schemaVersion: 1,
        runtimeId: 'opencode',
        view: {
          ...createRuntimeView(),
          projectPath: input.projectPath ?? null,
          defaultModel: input.projectPath === '/tmp/project-b' ? 'opencode/project-b' : null,
        },
      })
    );
    const loadProviderDirectory = vi.fn(() =>
      Promise.resolve({
        schemaVersion: 1,
        runtimeId: 'opencode',
        directory: {
          runtimeId: 'opencode',
          totalCount: 1,
          returnedCount: 1,
          query: null,
          filter: 'all',
          limit: 50,
          cursor: null,
          nextCursor: null,
          fetchedAt: '2026-04-25T00:00:00.000Z',
          entries: [createOpenAiLocalDirectoryEntry()],
          diagnostics: [],
        },
      })
    );
    const loadSetupForm = vi.fn(() =>
      Promise.resolve({
        schemaVersion: 1,
        runtimeId: 'opencode',
        setupForm: {
          runtimeId: 'opencode',
          providerId: 'openai',
          displayName: 'OpenAI',
          method: 'api',
          supported: true,
          title: 'Connect OpenAI',
          description: null,
          submitLabel: 'Connect',
          disabledReason: null,
          source: 'curated',
          secret: {
            key: 'key',
            label: 'API key',
            placeholder: 'Paste API key',
            required: true,
          },
          prompts: [],
        },
      })
    );
    const connectProvider = vi.fn(
      () =>
        new Promise<RuntimeProviderManagementProviderResponse>((resolve) => {
          resolveConnect = resolve;
        })
    );
    Object.defineProperty(window, 'electronAPI', {
      configurable: true,
      value: {
        runtimeProviderManagement: {
          loadView,
          loadProviderDirectory,
          loadSetupForm,
          connectProvider,
        },
      } as unknown as ElectronAPI,
    });

    const root = createRoot(host);
    await act(async () => {
      root.render(React.createElement(EnabledHarness, { projectPath: '/tmp/project-a' }));
      await Promise.resolve();
    });

    await act(async () => {
      actions?.startConnect('openai');
      actions?.setApiKeyValue('sk-project-a');
      await vi.waitFor(() => {
        expect(loadSetupForm).toHaveBeenCalled();
      });
    });

    let submitPromise: Promise<void> | null = null;
    await act(async () => {
      submitPromise = actions?.submitConnect('openai') ?? null;
      await vi.waitFor(() => {
        expect(connectProvider).toHaveBeenCalledWith({
          runtimeId: 'opencode',
          providerId: 'openai',
          method: 'api',
          apiKey: 'sk-project-a',
          metadata: {},
          projectPath: '/tmp/project-a',
        });
      });
      await Promise.resolve();
    });

    expect(state?.savingProviderId).toBe('openai');

    await act(async () => {
      root.render(React.createElement(EnabledHarness, { projectPath: '/tmp/project-b' }));
      await Promise.resolve();
      await Promise.resolve();
    });
    await vi.waitFor(() => {
      expect(loadView).toHaveBeenCalledWith({
        runtimeId: 'opencode',
        projectPath: '/tmp/project-b',
      });
    });

    expect(state?.savingProviderId).toBeNull();
    expect(state?.activeFormProviderId).toBeNull();

    await act(async () => {
      resolveConnect?.({
        schemaVersion: 1,
        runtimeId: 'opencode',
        provider: connectedProvider,
      });
      await submitPromise;
    });

    expect(state?.view?.providers).toEqual([]);
    expect(state?.savingProviderId).toBeNull();
    expect(state?.setupSubmitError).toBeNull();

    await act(async () => {
      root.unmount();
      await Promise.resolve();
    });
  });

  it('refreshes view and catalog after forgetting managed auth while local auth remains', async () => {
    const localProvider = createOpenAiLocalProvider();
    const loadView = vi.fn(() =>
      Promise.resolve({
        schemaVersion: 1,
        runtimeId: 'opencode',
        view: createRuntimeView([localProvider]),
      })
    );
    const loadProviderDirectory = vi.fn(() =>
      Promise.resolve({
        schemaVersion: 1,
        runtimeId: 'opencode',
        directory: {
          runtimeId: 'opencode',
          totalCount: 1,
          returnedCount: 1,
          query: null,
          filter: 'all',
          limit: 50,
          cursor: null,
          nextCursor: null,
          fetchedAt: '2026-04-25T00:00:00.000Z',
          entries: [createOpenAiLocalDirectoryEntry()],
          diagnostics: [],
        },
      })
    );
    const forgetCredential = vi.fn(() =>
      Promise.resolve({
        schemaVersion: 1,
        runtimeId: 'opencode',
        provider: localProvider,
      })
    );
    Object.defineProperty(window, 'electronAPI', {
      configurable: true,
      value: {
        runtimeProviderManagement: {
          loadView,
          loadProviderDirectory,
          forgetCredential,
          loadModels: vi.fn(() =>
            Promise.resolve({
              schemaVersion: 1,
              runtimeId: 'opencode',
              models: {
                runtimeId: 'opencode',
                providerId: 'openai',
                models: [],
                defaultModelId: null,
                diagnostics: [],
              },
            })
          ),
        },
      } as unknown as ElectronAPI,
    });

    const root = createRoot(host);
    await act(async () => {
      root.render(React.createElement(EnabledHarness, { projectPath: '/tmp/project-a' }));
      await Promise.resolve();
    });
    await vi.waitFor(() => {
      expect(loadView).toHaveBeenCalledTimes(1);
    });

    await act(async () => {
      await actions?.forgetProvider('openai');
    });

    expect(forgetCredential).toHaveBeenCalledWith({
      runtimeId: 'opencode',
      providerId: 'openai',
      projectPath: '/tmp/project-a',
    });
    expect(loadView).toHaveBeenCalledTimes(2);
    const refreshDirectoryArgs = {
      runtimeId: 'opencode',
      projectPath: '/tmp/project-a',
      query: null,
      filter: 'all',
      limit: 50,
      cursor: null,
      refresh: true,
    };
    expect(loadProviderDirectory).toHaveBeenCalledWith(refreshDirectoryArgs);
    expect(state?.successMessage).toBe(
      'Managed credential removed. Provider remains connected through local OpenCode credentials.'
    );

    await act(async () => {
      await actions?.refreshDirectory();
    });

    expect(loadView).toHaveBeenCalledTimes(3);
    expect(
      loadProviderDirectory.mock.calls.filter((call) => {
        const input = (call as unknown[])[0] as { refresh?: boolean } | undefined;
        return input?.refresh === true;
      })
    ).toHaveLength(2);
    expect(state?.successMessage).toBeNull();

    await act(async () => {
      root.unmount();
    });
  });

  it('keeps connect action busy until the post-connect refresh finishes', async () => {
    const disconnectedProvider: RuntimeProviderConnectionDto = {
      ...createOpenAiLocalProvider(),
      state: 'not-connected',
      ownership: [],
      modelCount: 0,
      actions: [
        {
          id: 'connect',
          label: 'Connect',
          enabled: true,
          disabledReason: null,
          requiresSecret: true,
          ownershipScope: 'managed',
        },
      ],
      detail: null,
    };
    const connectedProvider = createOpenAiLocalProvider();
    const initialViewResponse = {
      schemaVersion: 1 as const,
      runtimeId: 'opencode' as const,
      view: createRuntimeView([disconnectedProvider]),
    };
    const refreshedViewResponse = {
      schemaVersion: 1 as const,
      runtimeId: 'opencode' as const,
      view: createRuntimeView([connectedProvider]),
    };
    const directoryResponse = {
      schemaVersion: 1 as const,
      runtimeId: 'opencode' as const,
      directory: {
        runtimeId: 'opencode' as const,
        totalCount: 1,
        returnedCount: 1,
        query: null,
        filter: 'all' as const,
        limit: 50,
        cursor: null,
        nextCursor: null,
        fetchedAt: '2026-04-25T00:00:00.000Z',
        entries: [createOpenAiLocalDirectoryEntry()],
        diagnostics: [],
      },
    };
    let resolveRefreshView: (() => void) | null = null;
    let resolveRefreshDirectory: (() => void) | null = null;
    const loadView = vi
      .fn()
      .mockResolvedValueOnce(initialViewResponse)
      .mockImplementation(
        () =>
          new Promise<typeof refreshedViewResponse>((resolve) => {
            resolveRefreshView = () => resolve(refreshedViewResponse);
          })
      );
    const loadProviderDirectory = vi
      .fn()
      .mockResolvedValueOnce(directoryResponse)
      .mockImplementation(
        () =>
          new Promise<typeof directoryResponse>((resolve) => {
            resolveRefreshDirectory = () => resolve(directoryResponse);
          })
      );
    const loadSetupForm = vi.fn(() =>
      Promise.resolve({
        schemaVersion: 1,
        runtimeId: 'opencode',
        setupForm: {
          runtimeId: 'opencode',
          providerId: 'openai',
          displayName: 'OpenAI',
          method: 'api',
          supported: true,
          title: 'Connect OpenAI',
          description: null,
          submitLabel: 'Connect',
          disabledReason: null,
          source: 'curated',
          secret: {
            key: 'key',
            label: 'API key',
            placeholder: 'Paste API key',
            required: true,
          },
          prompts: [],
        },
      })
    );
    const connectProvider = vi.fn(() =>
      Promise.resolve({
        schemaVersion: 1,
        runtimeId: 'opencode',
        provider: connectedProvider,
      })
    );
    Object.defineProperty(window, 'electronAPI', {
      configurable: true,
      value: {
        runtimeProviderManagement: {
          loadView,
          loadProviderDirectory,
          loadSetupForm,
          connectProvider,
          loadModels: vi.fn(() =>
            Promise.resolve({
              schemaVersion: 1,
              runtimeId: 'opencode',
              models: {
                runtimeId: 'opencode',
                providerId: 'openai',
                models: [],
                defaultModelId: null,
                diagnostics: [],
              },
            })
          ),
        },
      } as unknown as ElectronAPI,
    });

    const root = createRoot(host);
    await act(async () => {
      root.render(React.createElement(EnabledHarness, { projectPath: '/tmp/project-a' }));
      await Promise.resolve();
    });
    await act(async () => {
      actions?.startConnect('openai');
      actions?.setApiKeyValue('sk-good-value');
      await vi.waitFor(() => {
        expect(loadSetupForm).toHaveBeenCalled();
      });
    });

    let submitPromise: Promise<void> | null = null;
    await act(async () => {
      submitPromise = actions?.submitConnect('openai') ?? null;
      await vi.waitFor(() => {
        expect(connectProvider).toHaveBeenCalled();
      });
      await Promise.resolve();
    });

    expect(state?.savingProviderId).toBe('openai');
    expect(state?.activeFormProviderId).toBeNull();

    await act(async () => {
      resolveRefreshView?.();
      resolveRefreshDirectory?.();
      await submitPromise;
    });

    expect(loadView).toHaveBeenCalledTimes(2);
    expect(
      loadProviderDirectory.mock.calls.filter((call) => {
        const input = (call as unknown[])[0] as { refresh?: boolean } | undefined;
        return input?.refresh === true;
      })
    ).toHaveLength(1);
    expect(state?.savingProviderId).toBeNull();

    await act(async () => {
      root.unmount();
    });
  });

  it('keeps provider data visible during catalog refresh', async () => {
    const localProvider = { ...createOpenAiLocalProvider(), modelCount: 0 };
    const localDirectoryEntry = { ...createOpenAiLocalDirectoryEntry(), modelCount: 0 };
    const viewResponse = {
      schemaVersion: 1 as const,
      runtimeId: 'opencode' as const,
      view: createRuntimeView([localProvider]),
    };
    const directoryResponse = {
      schemaVersion: 1 as const,
      runtimeId: 'opencode' as const,
      directory: {
        runtimeId: 'opencode' as const,
        totalCount: 1,
        returnedCount: 1,
        query: null,
        filter: 'all' as const,
        limit: 50,
        cursor: null,
        nextCursor: null,
        fetchedAt: '2026-04-25T00:00:00.000Z',
        entries: [localDirectoryEntry],
        diagnostics: [],
      },
    };
    let resolveRefreshView: (() => void) | null = null;
    let resolveRefreshDirectory: (() => void) | null = null;
    const loadView = vi
      .fn()
      .mockResolvedValueOnce(viewResponse)
      .mockImplementation(
        () =>
          new Promise<typeof viewResponse>((resolve) => {
            resolveRefreshView = () => resolve(viewResponse);
          })
      );
    const loadProviderDirectory = vi
      .fn()
      .mockResolvedValueOnce(directoryResponse)
      .mockImplementation(
        () =>
          new Promise<typeof directoryResponse>((resolve) => {
            resolveRefreshDirectory = () => resolve(directoryResponse);
          })
      );
    Object.defineProperty(window, 'electronAPI', {
      configurable: true,
      value: {
        runtimeProviderManagement: {
          loadView,
          loadProviderDirectory,
          loadModels: vi.fn(() =>
            Promise.resolve({
              schemaVersion: 1,
              runtimeId: 'opencode',
              models: {
                runtimeId: 'opencode',
                providerId: 'openai',
                models: [],
                defaultModelId: null,
                diagnostics: [],
              },
            })
          ),
        },
      } as unknown as ElectronAPI,
    });

    const root = createRoot(host);
    await act(async () => {
      root.render(React.createElement(EnabledHarness, { projectPath: '/tmp/project-a' }));
      await Promise.resolve();
    });
    await act(async () => {
      await new Promise((resolve) => window.setTimeout(resolve, 10));
    });
    await act(async () => {
      await vi.waitFor(() => {
        expect(state?.providers).toHaveLength(1);
        expect(state?.directoryEntries).toHaveLength(1);
      });
    });

    let refreshPromise: Promise<void> | null = null;
    await act(async () => {
      refreshPromise = actions?.refreshDirectory() ?? null;
      await Promise.resolve();
    });

    expect(state?.loading).toBe(false);
    expect(state?.directoryRefreshing).toBe(true);
    expect(state?.providers).toHaveLength(1);
    expect(state?.directoryEntries).toHaveLength(1);

    await act(async () => {
      resolveRefreshView?.();
      resolveRefreshDirectory?.();
      await refreshPromise;
    });

    expect(state?.loading).toBe(false);
    expect(state?.directoryRefreshing).toBe(false);

    await act(async () => {
      root.unmount();
    });
  });

  it('lazy-loads provider directory and ignores stale search responses', async () => {
    let resolveFirst: ((value: unknown) => void) | null = null;
    const loadView = vi.fn(() =>
      Promise.resolve({
        schemaVersion: 1,
        runtimeId: 'opencode',
        view: {
          runtimeId: 'opencode',
          title: 'OpenCode',
          runtime: {
            state: 'ready',
            cliPath: '/opt/homebrew/bin/opencode',
            version: '1.0.0',
            managedProfile: 'active',
            localAuth: 'synced',
          },
          providers: [],
          defaultModel: null,
          fallbackModel: null,
          diagnostics: [],
        },
      })
    );
    const deepseekDirectoryResponse = {
      schemaVersion: 1 as const,
      runtimeId: 'opencode' as const,
      directory: {
        runtimeId: 'opencode' as const,
        totalCount: 1,
        returnedCount: 1,
        query: 'deep',
        filter: 'all' as const,
        limit: 50,
        cursor: null,
        nextCursor: null,
        fetchedAt: '2026-04-25T00:00:00.000Z',
        entries: [
          {
            providerId: 'deepseek',
            displayName: 'DeepSeek',
            state: 'available' as const,
            setupKind: 'available-readonly' as const,
            ownership: [],
            recommended: false,
            modelCount: 62,
            authMethods: [],
            defaultModelId: null,
            sources: ['opencode-provider'] as const,
            sourceLabel: 'OpenCode catalog',
            providerSource: 'models.dev',
            detail: null,
            actions: [],
            metadata: {
              hasKnownModels: true,
              requiresManualConfig: false,
              supportedInlineAuth: false,
              configuredAuthless: false,
            },
          },
        ],
        diagnostics: [],
      },
    };
    const loadProviderDirectory = vi.fn().mockImplementationOnce(
      () =>
        new Promise((resolve) => {
          resolveFirst = resolve;
        })
    );
    loadProviderDirectory.mockResolvedValue(deepseekDirectoryResponse);
    Object.defineProperty(window, 'electronAPI', {
      configurable: true,
      value: {
        runtimeProviderManagement: {
          loadView,
          loadProviderDirectory,
        },
      } as unknown as ElectronAPI,
    });

    const root = createRoot(host);
    await act(async () => {
      root.render(React.createElement(EnabledHarness, { projectPath: '/tmp/project-a' }));
      await Promise.resolve();
    });

    await act(async () => {
      await new Promise((resolve) => window.setTimeout(resolve, 10));
    });
    await act(async () => {
      await vi.waitFor(() => {
        expect(loadProviderDirectory).toHaveBeenCalled();
      });
    });
    const callCountBeforeSearch = loadProviderDirectory.mock.calls.length;

    act(() => {
      actions?.setProviderQuery('deep');
    });
    await act(async () => {
      await new Promise((resolve) => window.setTimeout(resolve, 300));
      await vi.waitFor(() => {
        expect(loadProviderDirectory.mock.calls.length).toBeGreaterThan(callCountBeforeSearch);
      });
    });

    await act(async () => {
      resolveFirst?.({
        schemaVersion: 1,
        runtimeId: 'opencode',
        directory: {
          runtimeId: 'opencode',
          totalCount: 1,
          returnedCount: 1,
          query: null,
          filter: 'all',
          limit: 50,
          cursor: null,
          nextCursor: null,
          fetchedAt: '2026-04-25T00:00:00.000Z',
          entries: [
            {
              providerId: 'openrouter',
              displayName: 'OpenRouter',
              state: 'connected',
              setupKind: 'connected',
              ownership: ['managed'],
              recommended: true,
              modelCount: 174,
              authMethods: ['api'],
              defaultModelId: null,
              sources: ['opencode-provider'],
              sourceLabel: 'OpenCode catalog',
              providerSource: 'models.dev',
              detail: null,
              actions: [],
              metadata: {
                hasKnownModels: true,
                requiresManualConfig: false,
                supportedInlineAuth: true,
                configuredAuthless: false,
              },
            },
          ],
          diagnostics: [],
        },
      });
      await Promise.resolve();
    });

    expect(loadProviderDirectory).toHaveBeenLastCalledWith({
      runtimeId: 'opencode',
      projectPath: '/tmp/project-a',
      query: 'deep',
      filter: 'all',
      limit: 50,
      cursor: null,
      refresh: false,
    });
    expect(state?.directoryEntries.map((entry) => entry.providerId)).toEqual(['deepseek']);
  });

  it('keeps the API key draft when provider connect fails', async () => {
    const loadSetupForm = vi.fn(() =>
      Promise.resolve({
        schemaVersion: 1,
        runtimeId: 'opencode',
        setupForm: {
          runtimeId: 'opencode',
          providerId: 'openrouter',
          displayName: 'OpenRouter',
          method: 'api',
          supported: true,
          title: 'Connect OpenRouter',
          description: null,
          submitLabel: 'Connect',
          disabledReason: null,
          source: 'curated',
          secret: {
            key: 'key',
            label: 'API key',
            placeholder: 'Paste API key',
            required: true,
          },
          prompts: [],
        },
      })
    );
    const connectProvider = vi.fn(() =>
      Promise.resolve({
        schemaVersion: 1,
        runtimeId: 'opencode',
        error: {
          code: 'auth-failed',
          message: 'Invalid API key',
        },
      })
    );
    Object.defineProperty(window, 'electronAPI', {
      configurable: true,
      value: {
        runtimeProviderManagement: {
          loadSetupForm,
          connectProvider,
        },
      } as unknown as ElectronAPI,
    });

    const root = createRoot(host);
    await act(async () => {
      root.render(React.createElement(Harness));
      await Promise.resolve();
    });

    act(() => {
      actions?.startConnect('openrouter');
      actions?.setApiKeyValue('sk-bad-value');
    });
    await act(async () => {
      await vi.waitFor(() => {
        expect(loadSetupForm).toHaveBeenCalled();
      });
    });

    await act(async () => {
      await actions?.submitConnect('openrouter');
    });

    expect(connectProvider).toHaveBeenCalledWith({
      runtimeId: 'opencode',
      providerId: 'openrouter',
      method: 'api',
      apiKey: 'sk-bad-value',
      metadata: {},
      projectPath: null,
    });
    expect(state?.error).toBeNull();
    expect(state?.setupSubmitError).toBe('Invalid API key');
    expect(state?.apiKeyValue).toBe('sk-bad-value');
  });

  it('keeps setup form diagnostics available when submit is attempted after form load failure', async () => {
    const loadSetupForm = vi.fn(() =>
      Promise.resolve({
        schemaVersion: 1,
        runtimeId: 'opencode',
        error: {
          code: 'runtime-misconfigured',
          message: 'OpenCode provider settings are using the wrong runtime binary.',
          recoverable: true,
          diagnostics: {
            summary: 'OpenCode provider settings are using the wrong runtime binary.',
            likelyCause: 'The app resolved the OpenCode CLI itself as the runtime binary.',
            binaryPath: '/opt/homebrew/bin/opencode',
            command: '/opt/homebrew/bin/opencode runtime providers setup-form',
            projectPath: null,
            exitCode: null,
            stderrPreview: null,
            stdoutPreview: null,
            hints: ['Those environment variables must not point to opencode.'],
          },
        },
      })
    );
    Object.defineProperty(window, 'electronAPI', {
      configurable: true,
      value: {
        runtimeProviderManagement: {
          loadSetupForm,
        },
      } as unknown as ElectronAPI,
    });

    const root = createRoot(host);
    await act(async () => {
      root.render(React.createElement(Harness));
      await Promise.resolve();
    });

    act(() => {
      actions?.startConnect('openrouter');
    });
    await act(async () => {
      await vi.waitFor(() => {
        expect(loadSetupForm).toHaveBeenCalled();
      });
    });

    expect(state?.setupFormError).toBe(
      'OpenCode provider settings are using the wrong runtime binary.'
    );
    expect(state?.setupFormErrorDiagnostics?.binaryPath).toBe('/opt/homebrew/bin/opencode');

    await act(async () => {
      await actions?.submitConnect('openrouter');
    });

    expect(state?.setupSubmitError).toBe(
      'OpenCode provider settings are using the wrong runtime binary.'
    );
    expect(state?.setupSubmitErrorDiagnostics?.binaryPath).toBe('/opt/homebrew/bin/opencode');
  });

  it('submits a supported setup form without a secret as a null API key', async () => {
    const loadSetupForm = vi.fn(() =>
      Promise.resolve({
        schemaVersion: 1,
        runtimeId: 'opencode',
        setupForm: {
          runtimeId: 'opencode',
          providerId: 'openai',
          displayName: 'OpenAI',
          method: 'oauth',
          supported: true,
          title: 'Connect OpenAI',
          description: null,
          submitLabel: 'Connect',
          disabledReason: null,
          source: 'oauth',
          secret: null,
          prompts: [],
        },
      })
    );
    const connectProvider = vi.fn(() =>
      Promise.resolve({
        schemaVersion: 1,
        runtimeId: 'opencode',
        provider: createOpenAiLocalProvider(),
      })
    );
    Object.defineProperty(window, 'electronAPI', {
      configurable: true,
      value: {
        runtimeProviderManagement: {
          loadSetupForm,
          connectProvider,
        },
      } as unknown as ElectronAPI,
    });

    const root = createRoot(host);
    await act(async () => {
      root.render(React.createElement(Harness));
      await Promise.resolve();
    });

    act(() => {
      actions?.startConnect('openai');
    });
    await act(async () => {
      await vi.waitFor(() => {
        expect(loadSetupForm).toHaveBeenCalled();
      });
    });

    await act(async () => {
      await actions?.submitConnect('openai');
    });

    expect(connectProvider).toHaveBeenCalledWith({
      runtimeId: 'opencode',
      providerId: 'openai',
      method: 'oauth',
      apiKey: null,
      metadata: {},
      projectPath: null,
    });
    expect(state?.setupSubmitError).toBeNull();

    await act(async () => {
      root.unmount();
    });
  });

  it('clears model loading when switching from model picker to setup form', async () => {
    const localProvider = createOpenAiLocalProvider();
    let resolveModels: ((value: unknown) => void) | null = null;
    const loadView = vi.fn(() =>
      Promise.resolve({
        schemaVersion: 1,
        runtimeId: 'opencode',
        view: createRuntimeView([localProvider]),
      })
    );
    const loadProviderDirectory = vi.fn(() =>
      Promise.resolve({
        schemaVersion: 1,
        runtimeId: 'opencode',
        directory: {
          runtimeId: 'opencode',
          totalCount: 0,
          returnedCount: 0,
          query: null,
          filter: 'all',
          limit: 50,
          cursor: null,
          nextCursor: null,
          fetchedAt: '2026-04-25T00:00:00.000Z',
          entries: [],
          diagnostics: [],
        },
      })
    );
    const loadModels = vi.fn(
      () =>
        new Promise((resolve) => {
          resolveModels = resolve;
        })
    );
    const loadSetupForm = vi.fn(() =>
      Promise.resolve({
        schemaVersion: 1,
        runtimeId: 'opencode',
        setupForm: {
          runtimeId: 'opencode',
          providerId: 'openrouter',
          displayName: 'OpenRouter',
          method: 'api',
          supported: true,
          title: 'Connect OpenRouter',
          description: null,
          submitLabel: 'Connect',
          disabledReason: null,
          source: 'curated',
          secret: {
            key: 'key',
            label: 'API key',
            placeholder: 'Paste API key',
            required: true,
          },
          prompts: [],
        },
      })
    );
    Object.defineProperty(window, 'electronAPI', {
      configurable: true,
      value: {
        runtimeProviderManagement: {
          loadView,
          loadProviderDirectory,
          loadModels,
          loadSetupForm,
        },
      } as unknown as ElectronAPI,
    });

    const root = createRoot(host);
    await act(async () => {
      root.render(React.createElement(EnabledHarness, { projectPath: '/tmp/project-a' }));
      await Promise.resolve();
    });
    await act(async () => {
      await vi.waitFor(() => {
        expect(loadModels).toHaveBeenCalled();
        expect(state?.modelsLoading).toBe(true);
      });
    });

    await act(async () => {
      actions?.startConnect('openrouter');
      await Promise.resolve();
    });

    expect(state?.modelPickerProviderId).toBeNull();
    expect(state?.activeFormProviderId).toBe('openrouter');
    expect(state?.modelsLoading).toBe(false);

    await act(async () => {
      resolveModels?.({
        schemaVersion: 1,
        runtimeId: 'opencode',
        models: {
          runtimeId: 'opencode',
          providerId: 'openai',
          models: [
            {
              modelId: 'openai/stale-model',
              providerId: 'openai',
              displayName: 'Stale model',
              sourceLabel: 'OpenCode catalog',
              free: false,
              default: false,
              availability: 'available',
            },
          ],
          defaultModelId: null,
          diagnostics: [],
        },
      });
      await Promise.resolve();
    });

    expect(state?.modelsLoading).toBe(false);
    expect(state?.models).toEqual([]);

    await act(async () => {
      root.unmount();
    });
  });

  it('tracks concurrent model probes independently', async () => {
    const firstModelId = 'openrouter/anthropic/claude-3.5-haiku';
    const secondModelId = 'openrouter/openai/gpt-oss-20b:free';
    const resolvers = new Map<string, (value: unknown) => void>();
    const testModel = vi.fn(
      (input: { modelId: string }) =>
        new Promise((resolve) => {
          resolvers.set(input.modelId, resolve);
        })
    );
    Object.defineProperty(window, 'electronAPI', {
      configurable: true,
      value: {
        runtimeProviderManagement: {
          testModel,
        },
      } as unknown as ElectronAPI,
    });

    const root = createRoot(host);
    await act(async () => {
      root.render(React.createElement(Harness));
      await Promise.resolve();
    });

    let firstProbe: Promise<void> | null = null;
    let secondProbe: Promise<void> | null = null;
    await act(async () => {
      firstProbe = actions?.testModel('openrouter', firstModelId) ?? null;
      secondProbe = actions?.testModel('openrouter', secondModelId) ?? null;
      await Promise.resolve();
    });

    expect(state?.testingModelIds).toEqual([firstModelId, secondModelId]);

    await act(async () => {
      resolvers.get(firstModelId)?.({
        schemaVersion: 1,
        runtimeId: 'opencode',
        result: {
          providerId: 'openrouter',
          modelId: firstModelId,
          ok: true,
          availability: 'available',
          message: 'First passed',
          diagnostics: [],
        },
      });
      await firstProbe;
    });

    expect(state?.testingModelIds).toEqual([secondModelId]);

    await act(async () => {
      resolvers.get(secondModelId)?.({
        schemaVersion: 1,
        runtimeId: 'opencode',
        result: {
          providerId: 'openrouter',
          modelId: secondModelId,
          ok: true,
          availability: 'available',
          message: 'Second passed',
          diagnostics: [],
        },
      });
      await secondProbe;
    });

    expect(state?.testingModelIds).toEqual([]);
    expect(state?.modelResults[firstModelId]?.message).toBe('First passed');
    expect(state?.modelResults[secondModelId]?.message).toBe('Second passed');

    await act(async () => {
      root.unmount();
    });
  });

  it('drops stale model probe results after leaving the model picker', async () => {
    const modelId = 'openrouter/anthropic/claude-3.5-haiku';
    let resolveProbe: ((value: RuntimeProviderManagementModelTestResponse) => void) | null = null;
    const testModel = vi.fn(
      () =>
        new Promise<RuntimeProviderManagementModelTestResponse>((resolve) => {
          resolveProbe = resolve;
        })
    );
    const loadSetupForm = vi.fn(() =>
      Promise.resolve({
        schemaVersion: 1,
        runtimeId: 'opencode',
        setupForm: {
          runtimeId: 'opencode',
          providerId: 'openai',
          displayName: 'OpenAI',
          method: 'api',
          supported: true,
          title: 'Connect OpenAI',
          description: null,
          submitLabel: 'Connect',
          disabledReason: null,
          source: 'curated',
          secret: {
            key: 'key',
            label: 'API key',
            placeholder: 'Paste API key',
            required: true,
          },
          prompts: [],
        },
      })
    );
    Object.defineProperty(window, 'electronAPI', {
      configurable: true,
      value: {
        runtimeProviderManagement: {
          testModel,
          loadSetupForm,
        },
      } as unknown as ElectronAPI,
    });

    const root = createRoot(host);
    await act(async () => {
      root.render(React.createElement(Harness));
      await Promise.resolve();
    });

    act(() => {
      actions?.openModelPicker('openrouter', 'use');
    });

    let probe: Promise<void> | null = null;
    await act(async () => {
      probe = actions?.testModel('openrouter', modelId) ?? null;
      await Promise.resolve();
    });

    expect(state?.testingModelIds).toEqual([modelId]);

    await act(async () => {
      actions?.startConnect('openai');
      await Promise.resolve();
    });

    expect(state?.modelPickerProviderId).toBeNull();
    expect(state?.testingModelIds).toEqual([]);

    await act(async () => {
      resolveProbe?.({
        schemaVersion: 1,
        runtimeId: 'opencode',
        result: {
          providerId: 'openrouter',
          modelId,
          ok: true,
          availability: 'available',
          message: 'Stale probe passed',
          diagnostics: [],
        },
      });
      await probe;
    });

    expect(state?.modelResults[modelId]).toBeUndefined();
    expect(state?.testingModelIds).toEqual([]);

    await act(async () => {
      root.unmount();
    });
  });

  it('keeps failed model probes scoped to the model result instead of a global success banner', async () => {
    const modelId = 'openrouter/anthropic/claude-3.5-haiku';
    const message =
      'This request requires more credits, or fewer max_tokens. You requested up to 8192 tokens, but can only afford 381.';
    installRuntimeProviderManagementApi({
      schemaVersion: 1,
      runtimeId: 'opencode',
      result: {
        providerId: 'openrouter',
        modelId,
        ok: false,
        availability: 'unavailable',
        message,
        diagnostics: [],
      },
    });

    const root = createRoot(host);
    await act(async () => {
      root.render(React.createElement(Harness));
      await Promise.resolve();
    });

    await act(async () => {
      await actions?.testModel('openrouter', modelId);
    });

    expect(state?.successMessage).toBeNull();
    expect(state?.error).toBeNull();
    expect(state?.modelResults[modelId]?.ok).toBe(false);
    expect(state?.modelResults[modelId]?.message).toBe(message);
  });

  it('promotes structured model probe failures to the global diagnostics alert state', async () => {
    const modelId = 'openrouter/anthropic/claude-3.5-haiku';
    installRuntimeProviderManagementApi({
      schemaVersion: 1,
      runtimeId: 'opencode',
      error: {
        code: 'runtime-misconfigured',
        message: 'OpenCode provider settings are using the wrong runtime binary.',
        recoverable: true,
        diagnostics: {
          summary: 'OpenCode provider settings are using the wrong runtime binary.',
          likelyCause: 'The app resolved the OpenCode CLI itself as the runtime binary.',
          binaryPath: '/opt/homebrew/bin/opencode',
          command: '/opt/homebrew/bin/opencode runtime providers test-model',
          projectPath: null,
          exitCode: null,
          stderrPreview: null,
          stdoutPreview: null,
          hints: ['Those environment variables must not point to opencode.'],
        },
      },
    });

    const root = createRoot(host);
    await act(async () => {
      root.render(React.createElement(Harness));
      await Promise.resolve();
    });

    await act(async () => {
      await actions?.testModel('openrouter', modelId);
    });

    expect(state?.error).toBe('OpenCode provider settings are using the wrong runtime binary.');
    expect(state?.errorDiagnostics?.binaryPath).toBe('/opt/homebrew/bin/opencode');
    expect(state?.modelResults[modelId]).toMatchObject({
      ok: false,
      message: 'OpenCode provider settings are using the wrong runtime binary.',
    });
  });

  it('keeps successful model probes scoped to the model card instead of a global success banner', async () => {
    const modelId = 'openrouter/openai/gpt-oss-20b:free';
    installRuntimeProviderManagementApi({
      schemaVersion: 1,
      runtimeId: 'opencode',
      result: {
        providerId: 'openrouter',
        modelId,
        ok: true,
        availability: 'available',
        message: 'Model probe passed',
        diagnostics: [],
      },
    });

    const root = createRoot(host);
    await act(async () => {
      root.render(React.createElement(Harness));
      await Promise.resolve();
    });

    await act(async () => {
      await actions?.testModel('openrouter', modelId);
    });

    expect(state?.successMessage).toBeNull();
    expect(state?.error).toBeNull();
    expect(state?.modelResults[modelId]?.ok).toBe(true);
    expect(state?.modelResults[modelId]?.message).toBe('Model probe passed');
  });

  it('keeps a successful set-default probe visible as verified model state', async () => {
    const modelId = 'llama.cpp/qwen-test:0.5b';
    const setDefaultModel = vi.fn(() =>
      Promise.resolve({
        schemaVersion: 1,
        runtimeId: 'opencode',
        view: {
          ...createRuntimeView(),
          defaultModel: modelId,
          configuredModels: [
            {
              providerId: 'llama.cpp',
              modelId,
              displayName: 'qwen-test:0.5b',
              sourceLabel: 'llama.cpp',
              free: false,
              default: true,
              availability: 'untested',
              accessKind: 'configured_authless',
              routeKind: 'configured_local',
              proofState: 'needs_probe',
              requiresExecutionProof: true,
              accessReason: 'Execution proof required',
            },
          ],
        },
      })
    );
    Object.defineProperty(window, 'electronAPI', {
      configurable: true,
      value: {
        runtimeProviderManagement: {
          setDefaultModel,
        },
      } as unknown as ElectronAPI,
    });

    const root = createRoot(host);
    await act(async () => {
      root.render(React.createElement(Harness));
      await Promise.resolve();
    });

    await act(async () => {
      await actions?.setDefaultModel('llama.cpp', modelId);
      await Promise.resolve();
    });

    expect(setDefaultModel).toHaveBeenCalledWith({
      runtimeId: 'opencode',
      providerId: 'llama.cpp',
      modelId,
      probe: true,
      scope: 'project',
      projectPath: null,
    });
    expect(state?.view?.configuredModels?.[0]).toMatchObject({
      modelId,
      default: true,
      availability: 'available',
      accessKind: 'verified',
      proofState: 'verified',
      requiresExecutionProof: false,
    });
    expect(state?.modelResults[modelId]).toMatchObject({
      ok: true,
      availability: 'available',
      message: 'Model probe passed',
    });
  });

  it('keeps the effective project default selected when an all-projects default is shadowed', async () => {
    const allProjectsModelId = 'llama.cpp/qwen-test:0.5b';
    const projectModelId = 'llama.cpp/project-test:1b';
    const setDefaultModel = vi.fn(() =>
      Promise.resolve({
        schemaVersion: 1,
        runtimeId: 'opencode',
        view: {
          ...createRuntimeView(),
          defaultModel: projectModelId,
          projectDefaultModel: projectModelId,
          allProjectsDefaultModel: allProjectsModelId,
          defaultModelSource: 'project',
          configuredModels: [
            {
              providerId: 'llama.cpp',
              modelId: allProjectsModelId,
              displayName: 'qwen-test:0.5b',
              sourceLabel: 'llama.cpp',
              free: false,
              default: false,
              availability: 'untested',
              accessKind: 'configured_authless',
              routeKind: 'configured_local',
              proofState: 'needs_probe',
              requiresExecutionProof: true,
              accessReason: 'Execution proof required',
            },
            {
              providerId: 'llama.cpp',
              modelId: projectModelId,
              displayName: 'project-test:1b',
              sourceLabel: 'llama.cpp',
              free: false,
              default: true,
              availability: 'available',
              accessKind: 'verified',
              routeKind: 'configured_local',
              proofState: 'verified',
              requiresExecutionProof: false,
              accessReason: null,
            },
          ],
        },
      })
    );
    Object.defineProperty(window, 'electronAPI', {
      configurable: true,
      value: {
        runtimeProviderManagement: {
          setDefaultModel,
        },
      } as unknown as ElectronAPI,
    });

    const root = createRoot(host);
    await act(async () => {
      root.render(React.createElement(Harness));
      await Promise.resolve();
    });

    await act(async () => {
      await actions?.setDefaultModel('llama.cpp', allProjectsModelId, 'all_projects');
      await Promise.resolve();
    });

    expect(state?.selectedModelId).toBe(projectModelId);
    expect(state?.view?.defaultModel).toBe(projectModelId);
    expect(state?.view?.defaultModelSource).toBe('project');
    expect(
      state?.view?.configuredModels?.find((model) => model.modelId === allProjectsModelId)
    ).toMatchObject({
      default: false,
      availability: 'available',
      accessKind: 'verified',
      proofState: 'verified',
    });
    expect(
      state?.view?.configuredModels?.find((model) => model.modelId === projectModelId)
    ).toMatchObject({
      default: true,
      accessKind: 'verified',
    });
  });
});
