export const daikinDomain = 'daikin';
export const daikinDisplayName = 'Daikin AC';
export const daikinDefaultHttpPort = 80;
export const daikinDefaultHttpsPort = 443;
export const daikinSkyFiPort = 2000;
export const daikinDefaultTimeoutMs = 10000;
export const daikinUdpSourcePort = 30000;
export const daikinUdpDiscoveryPort = 30050;
export const daikinUdpDiscoveryMessage = 'DAIKIN_UDP/common/basic_info';
export const daikinZeroconfType = '_dkapi._tcp.local.';

export type TDaikinApiVariant = 'auto' | 'brp069' | 'brp072c' | 'airbase' | 'skyfi' | 'brp084';
export type TDaikinSnapshotSource = 'http' | 'client' | 'manual' | 'snapshot' | 'runtime' | 'executor';
export type TDaikinHvacMode = 'off' | 'fan_only' | 'dry' | 'cool' | 'heat' | 'heat_cool' | 'auto' | 'unknown' | string;
export type TDaikinHvacAction = 'off' | 'idle' | 'cooling' | 'heating' | 'drying' | 'fan' | 'unknown';
export type TDaikinPresetMode = 'none' | 'away' | 'boost' | 'eco' | string;
export type TDaikinCommandAction = 'refresh' | 'set_control' | 'set_holiday' | 'set_advanced_mode' | 'set_streamer' | 'set_zone';

export interface IDaikinValueMap {
  [key: string]: string | undefined;
}

export interface IDaikinRawData {
  variant?: TDaikinApiVariant;
  values?: IDaikinValueMap;
  resources?: Record<string, IDaikinValueMap>;
  basicInfo?: IDaikinValueMap;
  controlInfo?: IDaikinValueMap;
  sensorInfo?: IDaikinValueMap;
  modelInfo?: IDaikinValueMap;
  holiday?: IDaikinValueMap;
  notify?: IDaikinValueMap;
  zoneSetting?: IDaikinValueMap;
  dayPowerEx?: IDaikinValueMap;
  weekPower?: IDaikinValueMap;
  yearPower?: IDaikinValueMap;
  skyfiAc?: IDaikinValueMap;
  skyfiZones?: IDaikinValueMap;
  brp084?: unknown;
  fetchedAt?: string;
}

export interface IDaikinDeviceSnapshotInfo {
  id: string;
  name: string;
  manufacturer: string;
  model?: string;
  firmware?: string;
  adapterVersion?: string;
  host?: string;
  port?: number;
  ssl?: boolean;
  macAddress?: string;
  apiVariant: TDaikinApiVariant;
}

export interface IDaikinClimateSnapshot {
  power: boolean;
  hvacMode: TDaikinHvacMode;
  hvacAction: TDaikinHvacAction;
  rawDaikinMode?: string;
  rawPower?: string;
  targetTemperature?: number;
  insideTemperature?: number;
  outsideTemperature?: number;
  humidity?: number;
  targetHumidity?: number;
  compressorFrequency?: number;
  fanMode?: string;
  swingMode?: string;
  presetMode: TDaikinPresetMode;
  fanModes: string[];
  swingModes: string[];
  presetModes: TDaikinPresetMode[];
  temperatureUnit: 'C';
  targetTemperatureStep: number;
}

export interface IDaikinEnergySnapshot {
  energyToday?: number;
  coolEnergyToday?: number;
  heatEnergyToday?: number;
  totalEnergyToday?: number;
  totalPower?: number;
  lastHourCoolEnergy?: number;
  lastHourHeatEnergy?: number;
}

export interface IDaikinZoneSnapshot {
  id: number;
  name: string;
  enabled: boolean;
  targetTemperature?: number;
  heatTargetTemperature?: number;
  coolTargetTemperature?: number;
}

export interface IDaikinCapabilities {
  localControl: boolean;
  fanRate: boolean;
  swingMode: boolean;
  awayMode: boolean;
  advancedModes: boolean;
  streamer: boolean;
  outsideTemperature: boolean;
  humidity: boolean;
  compressorFrequency: boolean;
  energyConsumption: boolean;
  zones: boolean;
  zoneTemperatureControl: boolean;
}

export interface IDaikinSnapshot {
  device: IDaikinDeviceSnapshotInfo;
  climate: IDaikinClimateSnapshot;
  energy: IDaikinEnergySnapshot;
  zones: IDaikinZoneSnapshot[];
  capabilities: IDaikinCapabilities;
  rawData?: IDaikinRawData;
  online: boolean;
  updatedAt: string;
  source: TDaikinSnapshotSource;
  error?: string;
}

export interface IDaikinControlSettings {
  mode?: string;
  pow?: string;
  stemp?: string | number;
  shum?: string | number;
  f_rate?: string;
  f_dir?: string;
}

export interface IDaikinCommandRequest {
  action: TDaikinCommandAction;
  method?: 'GET' | 'POST';
  path?: string;
  query?: Record<string, string | number | boolean | undefined>;
  protocol?: TDaikinApiVariant | 'legacy';
  settings?: Partial<IDaikinControlSettings>;
  mode?: string;
  enabled?: boolean;
  zoneId?: number;
  zoneKey?: string;
  zoneValue?: string;
  service?: string;
  target?: Record<string, unknown>;
  data?: Record<string, unknown>;
}

export interface IDaikinCommandExecutor {
  execute(requestArg: IDaikinCommandRequest): Promise<unknown>;
}

export interface IDaikinClientLike {
  getSnapshot?: () => Promise<IDaikinSnapshot | Partial<IDaikinRawData>>;
  getRawData?: () => Promise<Partial<IDaikinRawData>>;
  getResource?: (pathArg: string, queryArg?: Record<string, string | number | boolean | undefined>) => Promise<IDaikinValueMap>;
  execute?: (requestArg: IDaikinCommandRequest) => Promise<unknown>;
  destroy?: () => Promise<void>;
}

export interface IDaikinConfig {
  host?: string;
  url?: string;
  port?: number;
  ssl?: boolean;
  tls?: boolean;
  verifySsl?: boolean;
  apiKey?: string;
  uuid?: string;
  password?: string;
  apiVariant?: TDaikinApiVariant;
  timeoutMs?: number;
  name?: string;
  manufacturer?: string;
  model?: string;
  uniqueId?: string;
  macAddress?: string;
  snapshot?: IDaikinSnapshot;
  rawData?: Partial<IDaikinRawData>;
  values?: IDaikinValueMap;
  client?: IDaikinClientLike;
  commandExecutor?: IDaikinCommandExecutor;
  online?: boolean;
}

export interface IHomeAssistantDaikinConfig extends IDaikinConfig {}

export interface IDaikinManualEntry extends IDaikinConfig {
  id?: string;
  metadata?: Record<string, unknown>;
}

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

export interface IDaikinUdpDiscoveryRecord {
  host?: string;
  address?: string;
  ip?: string;
  port?: number;
  data?: string | IDaikinValueMap;
  response?: string | IDaikinValueMap;
  values?: IDaikinValueMap;
  metadata?: Record<string, unknown>;
}

export interface IDaikinHttpCandidateRecord {
  url?: string;
  location?: string;
  host?: string;
  port?: number;
  ssl?: boolean;
  path?: string;
  name?: string;
  manufacturer?: string;
  model?: string;
  headers?: Record<string, string | undefined>;
  body?: string;
  responseText?: string;
  metadata?: Record<string, unknown>;
}

export interface IDaikinRefreshResult {
  success: boolean;
  snapshot?: IDaikinSnapshot;
  error?: string;
  data?: unknown;
}
