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

export type TCiscoIosSnapshotSource = 'snapshot' | 'manual' | 'client' | 'transport' | 'executor' | 'runtime';
export type TCiscoIosCommandAction = 'refresh' | 'show_ip_arp' | 'run_command';
export type TCiscoIosEventType = 'snapshot_refreshed' | 'command_mapped' | 'command_succeeded' | 'command_failed' | 'state_changed';

export interface ICiscoIosValueMap {
  [key: string]: unknown;
}

export interface ICiscoIosArpEntry {
  protocol?: string;
  ipAddress?: string;
  ageMinutes?: number | null;
  rawAge?: string;
  hardwareAddress?: string;
  macAddress?: string;
  type?: string;
  interfaceName?: string;
  present: boolean;
  rawLine?: string;
  attributes?: Record<string, unknown>;
}

export interface ICiscoIosTrackedDevice {
  id?: string;
  macAddress: string;
  ipAddress?: string;
  interfaceName?: string;
  ageMinutes?: number | null;
  connected: boolean;
  name?: string;
  hostname?: string;
  attributes?: Record<string, unknown>;
}

export interface ICiscoIosDeviceSnapshot {
  id?: string;
  name?: string;
  host?: string;
  port?: number;
  username?: string;
  manufacturer?: string;
  modelName?: string;
  modelId?: string;
  firmwareVersion?: string;
  macAddress?: string;
  configurationUrl?: string;
  available?: boolean;
  authenticated?: boolean;
  metadata?: Record<string, unknown>;
}

export interface ICiscoIosCliCommands {
  terminalLength?: string;
  arp: string;
}

export interface ICiscoIosSnapshot {
  connected: boolean;
  source: TCiscoIosSnapshotSource;
  device: ICiscoIosDeviceSnapshot;
  commands: ICiscoIosCliCommands;
  arpEntries: ICiscoIosArpEntry[];
  trackedDevices: ICiscoIosTrackedDevice[];
  rawArpOutput?: string;
  updatedAt?: string;
  events: ICiscoIosEvent[];
  metadata?: Record<string, unknown>;
  error?: string;
}

export interface ICiscoIosCommand {
  action: TCiscoIosCommandAction;
  command: string;
  service: string;
  target?: IServiceCallRequest['target'];
  data?: Record<string, unknown>;
  deviceId?: string;
  entityId?: string;
  host?: string;
  transmitted?: boolean;
  metadata?: Record<string, unknown>;
}

export interface ICiscoIosCommandResult extends IServiceCallResult {
  transmitted?: boolean;
  action?: TCiscoIosCommandAction;
  output?: string;
}

export interface ICiscoIosEvent {
  type: TCiscoIosEventType;
  command?: ICiscoIosCommand;
  deviceId?: string;
  entityId?: string;
  data?: unknown;
  error?: string;
  timestamp: number;
}

export interface ICiscoIosNativeClient {
  login?(): Promise<boolean | void>;
  getSnapshot?(): Promise<ICiscoIosSnapshot | Partial<ICiscoIosSnapshot>>;
  getArpOutput?(): Promise<string>;
  readArpOutput?(): Promise<string>;
  executeCommand?(commandArg: ICiscoIosCommand): Promise<ICiscoIosCommandResult | string | ICiscoIosValueMap | boolean | void>;
  execute?(commandArg: ICiscoIosCommand): Promise<ICiscoIosCommandResult | string | ICiscoIosValueMap | boolean | void>;
  destroy?(): Promise<void>;
}

export interface ICiscoIosTransport {
  readSnapshot?(): Promise<ICiscoIosSnapshot | Partial<ICiscoIosSnapshot>>;
  execute(commandArg: ICiscoIosCommand): Promise<ICiscoIosCommandResult | string | ICiscoIosValueMap | boolean | void>;
}

export type TCiscoIosCommandExecutor = ((commandArg: ICiscoIosCommand) => Promise<ICiscoIosCommandResult | string | ICiscoIosValueMap | boolean | void>) | {
  execute(commandArg: ICiscoIosCommand): Promise<ICiscoIosCommandResult | string | ICiscoIosValueMap | boolean | void>;
};

export interface ICiscoIosManualEntry {
  integrationDomain?: string;
  id?: string;
  host?: string;
  ip?: string;
  ipAddress?: string;
  address?: string;
  port?: number;
  name?: string;
  username?: string;
  password?: string;
  manufacturer?: string;
  model?: string;
  modelName?: string;
  modelId?: string;
  firmwareVersion?: string;
  mac?: string;
  macAddress?: string;
  presentAgeMinutes?: number;
  terminalLengthCommand?: string | false;
  arpCommand?: string;
  snapshot?: ICiscoIosSnapshot;
  arpOutput?: string;
  rawArpOutput?: string;
  metadata?: Record<string, unknown>;
}

export interface ICiscoIosDhcpRecord {
  integrationDomain?: string;
  host?: string;
  ip?: string;
  ipAddress?: string;
  address?: string;
  hostname?: string;
  hostName?: string;
  manufacturer?: string;
  model?: string;
  mac?: string;
  macAddress?: string;
  macaddress?: string;
  registeredDevice?: boolean;
  metadata?: Record<string, unknown>;
}

export interface ICiscoIosCandidateMetadata extends Record<string, unknown> {
  ciscoIos?: boolean;
  discoveryProtocol?: 'dhcp-explicit' | 'manual';
  hostname?: string;
  username?: string;
  snapshot?: ICiscoIosSnapshot;
  arpOutput?: string;
  nativeSshImplemented?: false;
  readOnly?: boolean;
}

export interface ICiscoIosConfig extends ICiscoIosManualEntry {
  timeoutMs?: number;
  connected?: boolean;
  snapshot?: ICiscoIosSnapshot;
  arpOutput?: string;
  rawArpOutput?: string;
  nativeClient?: ICiscoIosNativeClient;
  commandExecutor?: TCiscoIosCommandExecutor;
  transport?: ICiscoIosTransport;
}

export type IHomeAssistantCiscoIosConfig = ICiscoIosConfig;
