export type TRainbirdProtocol = 'auto' | 'http' | 'https';

export type TRainbirdEventType =
  | 'snapshot_refreshed'
  | 'command_mapped'
  | 'command_executed'
  | 'command_failed'
  | 'zone_started'
  | 'zone_stopped'
  | 'rain_delay_set';

export type TRainbirdProgramFrequency = 'custom' | 'cyclic' | 'odd' | 'even' | 'unknown';

export interface IRainbirdConfig {
  host?: string;
  password?: string;
  protocol?: TRainbirdProtocol;
  port?: number;
  timeoutMs?: number;
  name?: string;
  uniqueId?: string;
  serialNumber?: string;
  macAddress?: string;
  model?: string;
  defaultIrrigationDurationMinutes?: number;
  connected?: boolean;
  zoneCount?: number;
  controller?: IRainbirdController;
  zones?: IRainbirdZone[];
  programs?: IRainbirdProgram[];
  schedule?: IRainbirdSchedule;
  events?: IRainbirdEvent[];
  snapshot?: IRainbirdSnapshot;
  commandExecutor?: (commandArg: IRainbirdCommand) => Promise<IRainbirdCommandResult | unknown>;
}

export interface IHomeAssistantRainbirdConfig extends IRainbirdConfig {}

export interface IRainbirdController {
  id?: string;
  name?: string;
  manufacturer?: string;
  modelId?: string;
  modelCode?: string;
  modelName?: string;
  serialNumber?: string;
  macAddress?: string;
  firmwareVersion?: string;
  protocolRevision?: string;
  host?: string;
  port?: number;
  protocol?: TRainbirdProtocol;
  online?: boolean;
  maxPrograms?: number;
  maxRunTimes?: number;
  maxStations?: number;
  supportsWaterBudget?: boolean;
  rainSensorActive?: boolean;
  rainDelayDays?: number;
  currentIrrigation?: boolean;
  activeStation?: number;
  remainingRuntimeSeconds?: number;
  rssi?: number;
  wifiSsid?: string;
  localIpAddress?: string;
  localGateway?: string;
  availableZoneIds?: number[];
  activeZoneIds?: number[];
  attributes?: Record<string, unknown>;
}

export interface IRainbirdZone {
  id: number;
  name?: string;
  available?: boolean;
  active?: boolean;
  defaultDurationMinutes?: number;
  remainingRuntimeSeconds?: number;
  lastStartedAt?: string;
  lastStoppedAt?: string;
  attributes?: Record<string, unknown>;
}

export interface IRainbirdProgram {
  id: number | string;
  name?: string;
  enabled?: boolean;
  frequency?: TRainbirdProgramFrequency;
  starts?: string[];
  daysOfWeek?: string[];
  periodDays?: number;
  synchroDays?: number;
  durationMinutes?: number;
  zoneDurations?: IRainbirdZoneDuration[];
  nextStartAt?: string;
  attributes?: Record<string, unknown>;
}

export interface IRainbirdZoneDuration {
  zoneId: number;
  durationMinutes: number;
}

export interface IRainbirdSchedule {
  programs: IRainbirdProgram[];
  zoneSchedules?: IRainbirdZoneSchedule[];
  rainDelayDays?: number;
  rainSensorActive?: boolean;
  updatedAt?: string;
  attributes?: Record<string, unknown>;
}

export interface IRainbirdZoneSchedule {
  zoneId: number;
  starts: string[];
  frequency?: TRainbirdProgramFrequency;
  durationMinutes?: number;
  daysOfWeek?: string[];
  periodDays?: number;
  synchroDays?: number;
  nextStartAt?: string;
  attributes?: Record<string, unknown>;
}

export interface IRainbirdSnapshot {
  controller: IRainbirdController;
  zones: IRainbirdZone[];
  programs: IRainbirdProgram[];
  schedule?: IRainbirdSchedule;
  events: IRainbirdEvent[];
  connected: boolean;
  updatedAt: string;
  raw?: Record<string, unknown>;
}

export interface IRainbirdEvent {
  type: TRainbirdEventType;
  command?: IRainbirdCommand;
  zoneId?: number;
  entityId?: string;
  deviceId?: string;
  uniqueId?: string;
  data?: unknown;
  timestamp: number;
}

export type IRainbirdCommand =
  | IRainbirdStartZoneCommand
  | IRainbirdStopZoneCommand
  | IRainbirdSetRainDelayCommand
  | IRainbirdRefreshCommand
  | IRainbirdStartProgramCommand
  | IRainbirdRawLocalRpcCommand;

export interface IRainbirdStartZoneCommand {
  type: 'start_zone';
  zoneId: number;
  durationMinutes: number;
  entityId?: string;
  deviceId?: string;
  uniqueId?: string;
}

export interface IRainbirdStopZoneCommand {
  type: 'stop_zone';
  zoneId?: number;
  entityId?: string;
  deviceId?: string;
  uniqueId?: string;
}

export interface IRainbirdSetRainDelayCommand {
  type: 'set_rain_delay';
  days: number;
  entityId?: string;
  deviceId?: string;
  uniqueId?: string;
}

export interface IRainbirdRefreshCommand {
  type: 'refresh';
}

export interface IRainbirdStartProgramCommand {
  type: 'start_program';
  programId: number;
  entityId?: string;
  deviceId?: string;
  uniqueId?: string;
}

export interface IRainbirdRawLocalRpcCommand {
  type: 'raw_local_rpc';
  method: string;
  params?: Record<string, unknown>;
}

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

export interface IRainbirdModelAndVersion {
  modelId: string;
  modelCode: string;
  modelName: string;
  protocolRevisionMajor: number;
  protocolRevisionMinor: number;
  maxPrograms: number;
  maxRunTimes: number;
  maxStations: number;
  supportsWaterBudget: boolean;
}

export interface IRainbirdWifiParams {
  macAddress?: string;
  localIpAddress?: string;
  localNetmask?: string;
  localGateway?: string;
  rssi?: number;
  wifiSsid?: string;
  stickVersion?: string;
  [key: string]: unknown;
}

export interface IRainbirdLocalJsonRpcRequest {
  id: number;
  jsonrpc: '2.0';
  method: string;
  params: Record<string, unknown>;
}

export interface IRainbirdLocalJsonRpcResponse<TResult = unknown> {
  id?: number;
  jsonrpc?: '2.0';
  result?: TResult;
  error?: {
    code?: number;
    message?: string;
    data?: unknown;
  };
}

export interface IRainbirdHttpLocalCommandShape {
  endpoint: '/stick';
  method: 'POST';
  contentType: 'application/octet-stream';
  jsonRpcMethod: string;
  encrypted: boolean;
  params: Record<string, unknown>;
}

export interface IRainbirdTunnelSipResponse {
  data?: string;
  [key: string]: unknown;
}

export interface IRainbirdManualEntry {
  host?: string;
  password?: string;
  port?: number;
  protocol?: TRainbirdProtocol;
  id?: string;
  name?: string;
  manufacturer?: string;
  model?: string;
  serialNumber?: string;
  macAddress?: string;
  metadata?: Record<string, unknown>;
}

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

export interface IRainbirdDhcpLease {
  hostname?: string;
  ipAddress?: string;
  macAddress?: string;
  vendorClassIdentifier?: string;
  manufacturer?: string;
  metadata?: Record<string, unknown>;
}
