export const goodweDomain = 'goodwe';
export const goodweDisplayName = 'GoodWe Inverter';
export const goodweManufacturer = 'GoodWe';
export const goodweDefaultUdpPort = 8899;
export const goodweDefaultTcpPort = 502;
export const goodweDefaultTimeoutMs = 10000;
export const goodweDefaultRetries = 3;

export const goodweOperationModes = {
  general: 'general',
  offGrid: 'off_grid',
  backup: 'backup',
  eco: 'eco',
  peakShaving: 'peak_shaving',
  selfUse: 'self_use',
  ecoCharge: 'eco_charge',
  ecoDischarge: 'eco_discharge',
} as const;

export const goodweHomeAssistantOperationModeOptions = [
  goodweOperationModes.general,
  goodweOperationModes.offGrid,
  goodweOperationModes.backup,
  goodweOperationModes.eco,
  goodweOperationModes.peakShaving,
  goodweOperationModes.ecoCharge,
  goodweOperationModes.ecoDischarge,
] as const;

export const goodweOperationModeValues: Record<number, TGoodweOperationModeOption> = {
  0: goodweOperationModes.general,
  1: goodweOperationModes.offGrid,
  2: goodweOperationModes.backup,
  3: goodweOperationModes.eco,
  4: goodweOperationModes.peakShaving,
  5: goodweOperationModes.selfUse,
  98: goodweOperationModes.ecoCharge,
  99: goodweOperationModes.ecoDischarge,
};

export type TGoodweOperationModeOption = typeof goodweOperationModes[keyof typeof goodweOperationModes];
export type TGoodweSnapshotSource = 'client' | 'manual' | 'snapshot' | 'runtime' | 'executor';
export type TGoodweInverterFamily = 'ET' | 'ES' | 'DT' | string;
export type TGoodweSensorKind = 'PV' | 'AC' | 'UPS' | 'BAT' | 'GRID' | 'BMS' | string;

export interface IGoodweDeviceInfo {
  id?: string;
  host?: string;
  port?: number;
  name?: string;
  manufacturer?: string;
  model?: string;
  modelName?: string;
  modelFamily?: TGoodweInverterFamily;
  serialNumber?: string;
  firmware?: string;
  armFirmware?: string;
  ratedPower?: number;
  acOutputType?: number;
  dsp1Version?: number;
  dsp2Version?: number;
  dspSvnVersion?: number;
  armVersion?: number;
  armSvnVersion?: number;
}

export interface IGoodweSensorDefinition {
  id: string;
  name?: string;
  unit?: string;
  kind?: TGoodweSensorKind;
  entityCategory?: string;
  enabledByDefault?: boolean;
}

export interface IGoodweSettingDefinition extends IGoodweSensorDefinition {
  writable?: boolean;
  min?: number;
  max?: number;
  step?: number;
}

export interface IGoodweSensorSnapshot extends IGoodweSensorDefinition {
  value: unknown;
  available: boolean;
  deviceClass?: string;
  stateClass?: string;
}

export interface IGoodweSettingSnapshot extends IGoodweSettingDefinition {
  value?: unknown;
}

export interface IGoodweRawData {
  deviceInfo?: IGoodweDeviceInfo;
  runtimeData?: Record<string, unknown>;
  settingsData?: Record<string, unknown>;
  sensors?: IGoodweSensorDefinition[];
  settings?: IGoodweSettingDefinition[];
  operationMode?: TGoodweOperationModeOption | number | string;
  supportedOperationModes?: Array<TGoodweOperationModeOption | number | string>;
  gridExportLimit?: number;
  batteryDischargeDepth?: number;
  fetchedAt?: string;
  [key: string]: unknown;
}

export interface IGoodweCapabilities {
  localRead: boolean;
  localControl: boolean;
  operationModeSelect: boolean;
  gridExportLimitNumber: boolean;
  batteryDischargeDepthNumber: boolean;
  synchronizeClockButton: boolean;
}

export interface IGoodweInverterSnapshot {
  id: string;
  name: string;
  host?: string;
  port?: number;
  manufacturer: string;
  model?: string;
  modelFamily?: TGoodweInverterFamily;
  serialNumber?: string;
  firmware?: string;
  armFirmware?: string;
  ratedPower?: number;
  configurationUrl: string;
}

export interface IGoodweControlSnapshot {
  operationMode?: TGoodweOperationModeOption;
  supportedOperationModes: TGoodweOperationModeOption[];
  gridExportLimit?: number;
  gridExportLimitUnit: 'W' | '%';
  batteryDischargeDepth?: number;
}

export interface IGoodweSnapshot {
  inverter: IGoodweInverterSnapshot;
  runtimeData: Record<string, unknown>;
  settingsData: Record<string, unknown>;
  sensors: IGoodweSensorSnapshot[];
  settings: IGoodweSettingSnapshot[];
  controls: IGoodweControlSnapshot;
  capabilities: IGoodweCapabilities;
  rawData?: IGoodweRawData;
  online: boolean;
  updatedAt: string;
  source: TGoodweSnapshotSource;
  error?: string;
}

export interface IGoodweCommandRequest {
  action: string;
  operationMode?: TGoodweOperationModeOption;
  gridExportLimit?: number;
  batteryDischargeDepth?: number;
  settingId?: string;
  value?: unknown;
  timestamp?: string;
  service?: string;
  target?: Record<string, unknown>;
  data?: Record<string, unknown>;
}

export interface IGoodweCommandExecutor {
  execute(requestArg: IGoodweCommandRequest): Promise<unknown>;
}

export interface IGoodweClientLike {
  getSnapshot?: () => Promise<IGoodweSnapshot | Partial<IGoodweRawData>>;
  getRawData?: () => Promise<Partial<IGoodweRawData>>;
  readRuntimeData?: () => Promise<Record<string, unknown>>;
  read_runtime_data?: () => Promise<Record<string, unknown>>;
  readSettingsData?: () => Promise<Record<string, unknown>>;
  read_settings_data?: () => Promise<Record<string, unknown>>;
  getDeviceInfo?: () => Promise<Partial<IGoodweDeviceInfo> | undefined>;
  readDeviceInfo?: () => Promise<Partial<IGoodweDeviceInfo> | undefined>;
  read_device_info?: () => Promise<Partial<IGoodweDeviceInfo> | undefined>;
  sensors?: () => IGoodweSensorDefinition[] | Array<Record<string, unknown>>;
  settings?: () => IGoodweSettingDefinition[] | Array<Record<string, unknown>>;
  getOperationMode?: () => Promise<TGoodweOperationModeOption | number | string | undefined>;
  get_operation_mode?: () => Promise<TGoodweOperationModeOption | number | string | undefined>;
  getOperationModes?: (includeEmulatedArg?: boolean) => Promise<Array<TGoodweOperationModeOption | number | string>>;
  get_operation_modes?: (includeEmulatedArg?: boolean) => Promise<Array<TGoodweOperationModeOption | number | string>>;
  getGridExportLimit?: () => Promise<number>;
  get_grid_export_limit?: () => Promise<number>;
  getOngridBatteryDod?: () => Promise<number>;
  get_ongrid_battery_dod?: () => Promise<number>;
  execute?: (requestArg: IGoodweCommandRequest) => Promise<unknown>;
  destroy?: () => Promise<void>;
  [key: string]: unknown;
}

export interface IGoodweConfig {
  host?: string;
  port?: number;
  timeoutMs?: number;
  retries?: number;
  name?: string;
  manufacturer?: string;
  model?: string;
  modelFamily?: TGoodweInverterFamily;
  uniqueId?: string;
  serialNumber?: string;
  firmware?: string;
  armFirmware?: string;
  ratedPower?: number;
  snapshot?: IGoodweSnapshot;
  rawData?: Partial<IGoodweRawData>;
  client?: IGoodweClientLike;
  commandExecutor?: IGoodweCommandExecutor;
  online?: boolean;
}

export interface IHomeAssistantGoodweConfig extends IGoodweConfig {}

export interface IGoodweManualEntry extends IGoodweConfig {
  id?: string;
  metadata?: Record<string, unknown>;
  runtimeData?: Record<string, unknown>;
  settingsData?: Record<string, unknown>;
  sensors?: IGoodweSensorDefinition[];
  settings?: IGoodweSettingDefinition[];
}
