import type { IServiceCallResult } from '../../core/types.js';

export const openrgbDefaultPort = 6742;
export const openrgbDefaultClientName = 'Home Assistant';
export const openrgbUidSeparator = '||';

export type TOpenRGBColorMode = 'none' | 'per_led' | 'mode_specific' | 'random' | string;
export type TOpenRGBDeviceType =
  | 'motherboard'
  | 'dram'
  | 'gpu'
  | 'cooler'
  | 'ledstrip'
  | 'keyboard'
  | 'mouse'
  | 'mousemat'
  | 'headset'
  | 'headset_stand'
  | 'gamepad'
  | 'light'
  | 'speaker'
  | 'virtual'
  | 'storage'
  | 'case'
  | 'microphone'
  | 'accessory'
  | 'keypad'
  | 'unknown'
  | string;
export type TOpenRGBZoneType = 'single' | 'linear' | 'matrix' | string;

export interface IOpenRGBConfig {
  entryId?: string;
  name?: string;
  host?: string;
  port?: number;
  clientName?: string;
  protocolVersion?: number;
  timeoutMs?: number;
  controller?: IOpenRGBController;
  device?: IOpenRGBDevice;
  devices?: IOpenRGBDevice[];
  snapshot?: IOpenRGBSnapshot;
  manualEntries?: IOpenRGBManualEntry[];
  profiles?: string[];
  events?: IOpenRGBEvent[];
  commandExecutor?: TOpenRGBCommandExecutor;
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface IHomeAssistantOpenrgbConfig extends IOpenRGBConfig {}

export interface IOpenRGBController {
  id?: string;
  name?: string;
  host?: string;
  port?: number;
  protocolVersion?: number;
  manufacturer?: string;
  model?: string;
  serialNumber?: string;
  softwareVersion?: string;
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface IOpenRGBSnapshot {
  connected: boolean;
  host?: string;
  port?: number;
  name?: string;
  protocolVersion?: number;
  controller: IOpenRGBController;
  devices: IOpenRGBDevice[];
  profiles: string[];
  events: IOpenRGBEvent[];
  metadata?: Record<string, unknown>;
}

export interface IOpenRGBDeviceMetadata {
  vendor?: string;
  description?: string;
  version?: string;
  serial?: string;
  location?: string;
  [key: string]: unknown;
}

export interface IOpenRGBRgbColor {
  red: number;
  green: number;
  blue: number;
}

export interface IOpenRGBLed {
  id?: number;
  name?: string;
  value?: number;
  color?: IOpenRGBRgbColor;
  [key: string]: unknown;
}

export interface IOpenRGBSegment {
  id?: number;
  name?: string;
  type?: number | TOpenRGBZoneType;
  typeName?: TOpenRGBZoneType;
  startIndex?: number;
  ledCount?: number;
  [key: string]: unknown;
}

export interface IOpenRGBZone {
  id?: number;
  name?: string;
  type?: number | TOpenRGBZoneType;
  typeName?: TOpenRGBZoneType;
  ledsMin?: number;
  ledsMax?: number;
  numLeds?: number;
  startIndex?: number;
  matrixHeight?: number;
  matrixWidth?: number;
  matrixMap?: Array<Array<number | null>>;
  segments?: IOpenRGBSegment[];
  leds?: IOpenRGBLed[];
  colors?: IOpenRGBRgbColor[];
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface IOpenRGBMode {
  id?: number;
  name: string;
  value?: number;
  flags?: number;
  speedMin?: number;
  speedMax?: number;
  brightnessMin?: number;
  brightnessMax?: number;
  colorsMin?: number;
  colorsMax?: number;
  speed?: number;
  brightness?: number;
  direction?: number | string;
  colorMode?: number | TOpenRGBColorMode;
  colors?: IOpenRGBRgbColor[];
  supportsColor?: boolean;
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface IOpenRGBDevice {
  id?: number | string;
  key?: string;
  name?: string;
  type?: number | TOpenRGBDeviceType;
  typeName?: TOpenRGBDeviceType;
  metadata?: IOpenRGBDeviceMetadata;
  leds?: IOpenRGBLed[];
  zones?: IOpenRGBZone[];
  modes?: IOpenRGBMode[];
  colors?: IOpenRGBRgbColor[];
  activeMode?: number | string;
  available?: boolean;
  host?: string;
  port?: number;
  extra?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface IOpenRGBManualEntry {
  entryId?: string;
  id?: string;
  host?: string;
  port?: number;
  name?: string;
  manufacturer?: string;
  model?: string;
  protocolVersion?: number;
  controller?: IOpenRGBController;
  device?: IOpenRGBDevice;
  devices?: IOpenRGBDevice[];
  snapshot?: IOpenRGBSnapshot;
  profiles?: string[];
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface IOpenRGBEvent {
  type: 'snapshot' | 'command_mapped' | 'command_executed' | 'command_failed' | 'sdk_response' | 'error' | string;
  timestamp?: number;
  deviceId?: string;
  entityId?: string;
  deviceKey?: string;
  command?: IOpenRGBClientCommand;
  data?: unknown;
  [key: string]: unknown;
}

export interface IOpenRGBClientCommand {
  type: string;
  service: string;
  deviceId?: string;
  entityId?: string;
  deviceKey?: string;
  zoneId?: string;
  target?: {
    entityId?: string;
    deviceId?: string;
  };
  operations: TOpenRGBCommandOperation[];
  payload: Record<string, unknown>;
  [key: string]: unknown;
}

export type TOpenRGBCommandOperation =
  | IOpenRGBSetModeOperation
  | IOpenRGBSetColorOperation
  | IOpenRGBLoadProfileOperation;

export interface IOpenRGBSetModeOperation {
  action: 'setMode';
  deviceIndex?: number;
  deviceKey?: string;
  modeName: string;
  mode?: IOpenRGBMode;
}

export interface IOpenRGBSetColorOperation {
  action: 'setColor';
  deviceIndex?: number;
  deviceKey?: string;
  zoneIndex?: number;
  zoneName?: string;
  ledCount: number;
  rgb: IOpenRGBRgbColor;
  brightness?: number;
}

export interface IOpenRGBLoadProfileOperation {
  action: 'loadProfile';
  profile: string;
}

export interface IOpenRGBCommandResult extends IServiceCallResult {}

export type TOpenRGBCommandExecutor = (
  commandArg: IOpenRGBClientCommand
) => Promise<IOpenRGBCommandResult | unknown> | IOpenRGBCommandResult | unknown;

export interface IOpenRGBManualDiscoveryRecord extends IOpenRGBManualEntry {
  integrationDomain?: string;
}
