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

export const esphomeDefaultNativeApiPort = 6053;

export type TEsphomeEntityPlatform =
  | TEntityPlatform
  | 'text_sensor'
  | 'alarm_control_panel'
  | 'camera'
  | 'date'
  | 'datetime'
  | 'event'
  | 'lock'
  | 'time'
  | 'valve'
  | 'water_heater';

export interface IEsphomeConfig {
  host?: string;
  port?: number;
  name?: string;
  deviceName?: string;
  password?: string;
  encryptionKey?: string;
  noisePsk?: string;
  snapshot?: IEsphomeSnapshot;
  deviceInfo?: IEsphomeDeviceInfo;
  entities?: IEsphomeEntityDescriptor[];
  states?: IEsphomeEntityState[] | Record<string, unknown>;
  services?: IEsphomeUserService[];
  manualEntries?: IEsphomeManualEntry[];
  commandExecutor?: TEsphomeCommandExecutor;
}

export interface IHomeAssistantEsphomeConfig extends IEsphomeConfig {}

export interface IEsphomeDeviceInfo {
  name?: string;
  friendlyName?: string;
  macAddress?: string;
  bluetoothMacAddress?: string;
  manufacturer?: string;
  model?: string;
  esphomeVersion?: string;
  compilationTime?: string;
  projectName?: string;
  projectVersion?: string;
  suggestedArea?: string;
  area?: IEsphomeAreaInfo;
  areas?: IEsphomeAreaInfo[];
  devices?: IEsphomeSubDeviceInfo[];
  webserverPort?: number;
  usesPassword?: boolean;
  apiEncryptionSupported?: boolean;
  hasDeepSleep?: boolean;
  host?: string;
  port?: number;
  [key: string]: unknown;
}

export interface IEsphomeAreaInfo {
  areaId?: number | string;
  area_id?: number | string;
  name?: string;
}

export interface IEsphomeSubDeviceInfo {
  deviceId?: number | string;
  device_id?: number | string;
  name?: string;
  areaId?: number | string;
  area_id?: number | string;
  [key: string]: unknown;
}

export interface IEsphomeEntityDescriptor {
  platform: TEsphomeEntityPlatform | string;
  key: number | string;
  deviceId?: number | string;
  device_id?: number | string;
  name?: string;
  objectId?: string;
  object_id?: string;
  uniqueId?: string;
  unique_id?: string;
  entityId?: string;
  entity_id?: string;
  disabledByDefault?: boolean;
  disabled_by_default?: boolean;
  deviceClass?: string;
  device_class?: string;
  icon?: string;
  entityCategory?: string;
  entity_category?: string;
  unitOfMeasurement?: string;
  unit_of_measurement?: string;
  accuracyDecimals?: number;
  accuracy_decimals?: number;
  stateClass?: string | number;
  state_class?: string | number;
  assumedState?: boolean;
  assumed_state?: boolean;
  writable?: boolean;
  minValue?: number;
  min_value?: number;
  maxValue?: number;
  max_value?: number;
  step?: number;
  mode?: string | number;
  options?: string[];
  effects?: string[];
  supportsPosition?: boolean;
  supports_position?: boolean;
  supportsTilt?: boolean;
  supports_tilt?: boolean;
  supportsStop?: boolean;
  supports_stop?: boolean;
  supportsSpeed?: boolean;
  supports_speed?: boolean;
  supportedSpeedCount?: number;
  supported_speed_count?: number;
  supportedModes?: Array<string | number>;
  supported_modes?: Array<string | number>;
  supportedFanModes?: Array<string | number>;
  supported_fan_modes?: Array<string | number>;
  supportedPresetModes?: string[];
  supported_preset_modes?: string[];
  raw?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface IEsphomeEntityState {
  platform?: TEsphomeEntityPlatform | string;
  key?: number | string;
  deviceId?: number | string;
  device_id?: number | string;
  uniqueId?: string;
  unique_id?: string;
  entityId?: string;
  entity_id?: string;
  state?: unknown;
  value?: unknown;
  missingState?: boolean;
  missing_state?: boolean;
  updatedAt?: number | string;
  updated_at?: number | string;
  raw?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface IEsphomeSnapshot {
  host?: string;
  port: number;
  connected: boolean;
  deviceInfo: IEsphomeDeviceInfo;
  apiVersion?: IEsphomeApiVersion;
  entities: IEsphomeEntityDescriptor[];
  states: IEsphomeEntityState[];
  services?: IEsphomeUserService[];
  events: IEsphomeEvent[];
}

export interface IEsphomeApiVersion {
  major?: number;
  minor?: number;
  patch?: number;
}

export interface IEsphomeEvent {
  type: string;
  timestamp?: number;
  deviceId?: string;
  entityId?: string;
  command?: IEsphomeClientCommand;
  data?: unknown;
}

export interface IEsphomeUserService {
  key?: number | string;
  name: string;
  args?: IEsphomeUserServiceArg[];
  supportsResponse?: 'none' | 'status' | 'optional' | 'only';
  supports_response?: 'none' | 'status' | 'optional' | 'only';
  [key: string]: unknown;
}

export interface IEsphomeUserServiceArg {
  name: string;
  type: 'bool' | 'int' | 'float' | 'string' | 'bool_array' | 'int_array' | 'float_array' | 'string_array' | string | number;
  [key: string]: unknown;
}

export interface IEsphomeClientCommand {
  type: string;
  service: string;
  platform?: TEsphomeEntityPlatform | string;
  key?: number | string;
  deviceId?: number | string;
  entityId?: string;
  uniqueId?: string;
  payload: Record<string, unknown>;
  target?: {
    entityId?: string;
    deviceId?: string;
  };
}

export interface IEsphomeCommandResult {
  success: boolean;
  error?: string;
  data?: unknown;
}

export type TEsphomeCommandExecutor = (
  commandArg: IEsphomeClientCommand
) => Promise<IEsphomeCommandResult | unknown> | IEsphomeCommandResult | unknown;

export interface IEsphomeMdnsRecord {
  type?: string;
  name?: string;
  host?: string;
  hostname?: string;
  addresses?: string[];
  port?: number;
  txt?: Record<string, string | undefined>;
  properties?: Record<string, string | undefined>;
}

export interface IEsphomeManualEntry {
  host?: string;
  port?: number;
  id?: string;
  name?: string;
  deviceName?: string;
  model?: string;
  manufacturer?: string;
  password?: string;
  encryptionKey?: string;
  noisePsk?: string;
  metadata?: Record<string, unknown>;
}

export interface IEsphomeDiscoveryRecord {
  source?: 'mdns' | 'manual' | 'mqtt' | string;
  host?: string;
  port?: number;
  name?: string;
  macAddress?: string;
  metadata?: Record<string, unknown>;
}
