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

export const piHoleDomain = 'pi_hole';
export const piHoleDefaultName = 'Pi-hole';
export const piHoleDefaultLocation = 'admin';
export const piHoleDefaultPort = 80;
export const piHoleDefaultTimeoutMs = 5000;

export type TPiHoleApiVersion = 5 | 6;
export type TPiHoleSnapshotSource = 'snapshot' | 'http' | 'manual' | 'runtime';
export type TPiHoleBlockingStatus = 'enabled' | 'disabled' | 'unknown';
export type TPiHoleHttpMethod = 'GET' | 'POST';
export type TPiHoleCommandType = 'enable' | 'disable' | 'refresh';
export type TPiHoleJsonValue = string | number | boolean | null | TPiHoleJsonValue[] | {
  [key: string]: TPiHoleJsonValue | undefined;
};

export interface IPiHoleStatistics {
  adsBlocked: number | null;
  adsPercentage: number | null;
  clientsSeen: number | null;
  dnsQueries: number | null;
  domainsBlocked: number | null;
  queriesCached: number | null;
  queriesForwarded: number | null;
  uniqueClients: number | null;
  uniqueDomains: number | null;
}

export interface IPiHoleComponentVersion {
  current?: string;
  latest?: string;
  updateAvailable?: boolean;
}

export interface IPiHoleVersions {
  core: IPiHoleComponentVersion;
  web: IPiHoleComponentVersion;
  ftl: IPiHoleComponentVersion;
}

export interface IPiHoleV5Summary {
  status?: string;
  ads_blocked_today?: number;
  ads_percentage_today?: number;
  clients_ever_seen?: number;
  dns_queries_today?: number;
  domains_being_blocked?: number;
  queries_cached?: number;
  queries_forwarded?: number;
  unique_clients?: number;
  unique_domains?: number;
  error?: TPiHoleJsonValue;
  [key: string]: TPiHoleJsonValue | undefined;
}

export interface IPiHoleV5Versions {
  FTL_current?: string;
  FTL_latest?: string;
  FTL_update?: boolean;
  core_current?: string;
  core_latest?: string;
  core_update?: boolean;
  web_current?: string;
  web_latest?: string;
  web_update?: boolean;
  [key: string]: TPiHoleJsonValue | undefined;
}

export interface IPiHoleV6Summary {
  queries?: Record<string, TPiHoleJsonValue | undefined>;
  clients?: Record<string, TPiHoleJsonValue | undefined>;
  gravity?: Record<string, TPiHoleJsonValue | undefined>;
  [key: string]: TPiHoleJsonValue | Record<string, TPiHoleJsonValue | undefined> | undefined;
}

export interface IPiHoleV6BlockingStatus {
  blocking?: string | boolean;
  timer?: number | null;
  [key: string]: TPiHoleJsonValue | undefined;
}

export interface IPiHoleV6VersionSide {
  version?: string;
  hash?: string;
  branch?: string;
  [key: string]: TPiHoleJsonValue | undefined;
}

export interface IPiHoleV6ComponentVersion {
  local?: IPiHoleV6VersionSide;
  remote?: IPiHoleV6VersionSide;
  [key: string]: TPiHoleJsonValue | IPiHoleV6VersionSide | undefined;
}

export interface IPiHoleV6InfoVersionResponse {
  version?: {
    core?: IPiHoleV6ComponentVersion;
    web?: IPiHoleV6ComponentVersion;
    ftl?: IPiHoleV6ComponentVersion;
    [key: string]: TPiHoleJsonValue | IPiHoleV6ComponentVersion | undefined;
  };
  [key: string]: TPiHoleJsonValue | IPiHoleV6InfoVersionResponse['version'] | undefined;
}

export interface IPiHoleRawData {
  v5Summary?: IPiHoleV5Summary;
  v5Versions?: IPiHoleV5Versions;
  v6Summary?: IPiHoleV6Summary;
  v6Blocking?: IPiHoleV6BlockingStatus;
  v6Versions?: IPiHoleV6InfoVersionResponse;
  [key: string]: unknown;
}

export interface IPiHoleSnapshot {
  online: boolean;
  apiVersion?: TPiHoleApiVersion;
  status: TPiHoleBlockingStatus;
  statistics: IPiHoleStatistics;
  versions: IPiHoleVersions;
  raw?: IPiHoleRawData;
  host?: string;
  port?: number;
  ssl?: boolean;
  verifySsl?: boolean;
  location?: string;
  name?: string;
  uniqueId?: string;
  updatedAt?: string;
  source?: TPiHoleSnapshotSource;
  error?: string;
}

export interface IPiHoleClientCommand {
  type: TPiHoleCommandType;
  service: string;
  method?: TPiHoleHttpMethod;
  path?: string;
  query?: Record<string, string | number | boolean | undefined>;
  payload?: Record<string, unknown>;
  target?: {
    entityId?: string;
    deviceId?: string;
  };
  entityId?: string;
  deviceId?: string;
  uniqueId?: string;
  apiVersion?: TPiHoleApiVersion;
  enabled?: boolean;
  durationSeconds?: number;
  requiresAuth?: boolean;
}

export interface IPiHoleCommandResult extends IServiceCallResult {}

export type TPiHoleCommandExecutor = (
  commandArg: IPiHoleClientCommand
) => Promise<IPiHoleCommandResult | unknown> | IPiHoleCommandResult | unknown;

export interface IPiHoleConfig {
  host?: string;
  port?: number;
  ssl?: boolean;
  verifySsl?: boolean;
  location?: string;
  apiKey?: string;
  password?: string;
  name?: string;
  uniqueId?: string;
  apiVersion?: TPiHoleApiVersion;
  timeoutMs?: number;
  snapshot?: IPiHoleSnapshot;
  rawData?: IPiHoleRawData;
  v5Summary?: IPiHoleV5Summary;
  v5Versions?: IPiHoleV5Versions;
  v6Summary?: IPiHoleV6Summary;
  v6Blocking?: IPiHoleV6BlockingStatus;
  v6Versions?: IPiHoleV6InfoVersionResponse;
  status?: string | boolean;
  statistics?: Partial<IPiHoleStatistics>;
  versions?: Partial<IPiHoleVersions>;
  online?: boolean;
  commandExecutor?: TPiHoleCommandExecutor;
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

export interface IPiHoleManualEntry {
  id?: string;
  host?: string;
  port?: number;
  url?: string;
  ssl?: boolean;
  verifySsl?: boolean;
  location?: string;
  apiKey?: string;
  password?: string;
  apiVersion?: TPiHoleApiVersion;
  name?: string;
  manufacturer?: string;
  model?: string;
  integrationDomain?: string;
  snapshot?: IPiHoleSnapshot;
  rawData?: IPiHoleRawData;
  status?: string | boolean;
  statistics?: Partial<IPiHoleStatistics>;
  versions?: Partial<IPiHoleVersions>;
  metadata?: Record<string, unknown>;
  [key: string]: unknown;
}

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

export interface IHomeAssistantPiHoleConfig extends IPiHoleConfig {}
