import type { ComponentType, ReactNode } from "react";

export const DEVICE_PLUGIN_API_VERSION_V1ALPHA1 = "missioncore.nodedc/v1alpha1" as const;
export const DEVICE_PLUGIN_API_VERSION_V1ALPHA2 = "missioncore.nodedc/v1alpha2" as const;
export const DEVICE_PLUGIN_API_VERSION = DEVICE_PLUGIN_API_VERSION_V1ALPHA2;
export const SUPPORTED_DEVICE_PLUGIN_API_VERSIONS = Object.freeze([
  DEVICE_PLUGIN_API_VERSION_V1ALPHA1,
  DEVICE_PLUGIN_API_VERSION_V1ALPHA2,
] as const);
export const DEVICE_STATE_READ_ACTION_ID = "state.read" as const;

export type DevicePluginApiVersion =
  (typeof SUPPORTED_DEVICE_PLUGIN_API_VERSIONS)[number];

export interface DeviceCapability {
  id: string;
  label: string;
}

export interface DevicePluginActionDefinition {
  id: string;
  mutating: boolean;
  secretFields: readonly string[];
}

export interface DeviceModelDefinition {
  id: string;
  vendor: string;
  displayName: string;
  category: string;
  description: string;
  verified: boolean;
  capabilities: readonly DeviceCapability[];
  ui: {
    slot: "device.connection";
    componentKey: string;
  };
}

export interface DeviceCompatibilityProfileDefinition {
  profileId: string;
  path: string;
  modelId: string;
}

interface DevicePluginManifestBase {
  apiVersion: DevicePluginApiVersion;
  kind: "DevicePlugin";
  metadata: {
    id: string;
    version: string;
    displayName: string;
  };
}

export interface DevicePluginManifestV1Alpha1 extends DevicePluginManifestBase {
  apiVersion: typeof DEVICE_PLUGIN_API_VERSION_V1ALPHA1;
  spec: {
    hostApiRange: "v1alpha1";
    runtime: {
      backendEntrypoint: string;
      isolation: "transitional-in-process";
    };
    permissions: readonly string[];
    actions: readonly DevicePluginActionDefinition[];
    models: readonly DeviceModelDefinition[];
  };
}

export interface DevicePluginManifestV1Alpha2 extends DevicePluginManifestBase {
  apiVersion: typeof DEVICE_PLUGIN_API_VERSION_V1ALPHA2;
  spec: {
    hostApiRange: "v1alpha2";
    runtime: {
      backendEntrypoint: string;
      isolation: "transitional-in-process";
    };
    permissions: readonly string[];
    actions: readonly DevicePluginActionDefinition[];
    models: readonly DeviceModelDefinition[];
    compatibilityProfiles: readonly DeviceCompatibilityProfileDefinition[];
  };
}

export type DevicePluginManifest =
  | DevicePluginManifestV1Alpha1
  | DevicePluginManifestV1Alpha2;

export function isDevicePluginManifestV1Alpha2(
  manifest: DevicePluginManifest,
): manifest is DevicePluginManifestV1Alpha2 {
  return manifest.apiVersion === DEVICE_PLUGIN_API_VERSION_V1ALPHA2;
}

export interface DevicePluginHostActions {
  openSpatialScene: () => void;
  activateAutomaticSpatialSource: () => void;
}

export interface DevicePluginConnectionProps {
  model: DeviceModelDefinition;
  host: DevicePluginHostActions;
}

export interface DeviceUiPlugin {
  manifest: DevicePluginManifest;
  RuntimeProvider: ComponentType<{
    activeModel: DeviceModelDefinition | null;
    registerDeactivation: (handler: () => Promise<boolean>) => () => void;
    children: ReactNode;
  }>;
  connectionViews: Readonly<Record<string, ComponentType<DevicePluginConnectionProps>>>;
  SpatialControlsView?: ComponentType<DevicePluginConnectionProps>;
}

export interface RegisteredDeviceModel {
  plugin: DeviceUiPlugin;
  model: DeviceModelDefinition;
  ConnectionView: ComponentType<DevicePluginConnectionProps>;
  SpatialControlsView?: ComponentType<DevicePluginConnectionProps>;
}
