import type {
  ContentExpectations,
  RawContentExpectations,
  RawValueExpectation,
  ValueExpectation,
} from "../../expect/types";
import type { ResolvedTargetBase } from "../../types";

export type DnsFamily = "any" | "ipv4" | "ipv6";
export type DnsProtocol = "tcp" | "udp";
export type DnsRecordType = "A" | "AAAA" | "CAA" | "CNAME" | "MX" | "NS" | "PTR" | "SOA" | "SRV" | "TXT";
export type DnsResolver = "server" | "system";

export interface DnsServerConfig {
  maxResponseBytes?: number | string;
  name: string;
  port?: number;
  protocol?: DnsProtocol;
  recordType?: DnsRecordType;
  recursionDesired?: boolean;
  resolver: "server";
  server: string;
  tcpFallback?: boolean;
}

export interface DnsSystemConfig {
  family?: DnsFamily;
  name: string;
  resolver: "system";
}

export type DnsTargetConfig = DnsServerConfig | DnsSystemConfig;

export interface DnsValuesExpectation {
  exact?: string[];
  exclude?: string[];
  include?: string[];
}

export interface RawDnsExpectConfig {
  answerCount?: RawValueExpectation;
  authenticatedData?: boolean;
  authoritative?: boolean;
  durationMs?: RawValueExpectation;
  rcode?: string[];
  recursionAvailable?: boolean;
  responded?: boolean;
  result?: RawContentExpectations;
  truncated?: boolean;
  ttlMax?: RawValueExpectation;
  ttlMin?: RawValueExpectation;
  valueCount?: RawValueExpectation;
  values?: DnsValuesExpectation;
}

export interface RawDnsServerExpectConfig extends RawDnsExpectConfig {
  responded?: boolean;
}

export interface RawDnsSystemExpectConfig {
  durationMs?: RawValueExpectation;
  valueCount?: RawValueExpectation;
  values?: DnsValuesExpectation;
}

export type ResolvedDnsConfig = ResolvedDnsServerConfig | ResolvedDnsSystemConfig;

export type ResolvedDnsExpectConfig = ResolvedDnsServerExpectConfig | ResolvedDnsSystemExpectConfig;

export interface ResolvedDnsServerConfig {
  maxResponseBytes: number;
  name: string;
  port: number;
  protocol: DnsProtocol;
  recordType: DnsRecordType;
  recursionDesired: boolean;
  resolver: "server";
  server: string;
  tcpFallback: boolean;
}

export interface ResolvedDnsServerExpectConfig {
  answerCount?: ValueExpectation;
  authenticatedData?: boolean;
  authoritative?: boolean;
  durationMs?: ValueExpectation;
  rcode?: string[];
  recursionAvailable?: boolean;
  responded: boolean;
  result?: ContentExpectations;
  truncated?: boolean;
  ttlMax?: ValueExpectation;
  ttlMin?: ValueExpectation;
  valueCount?: ValueExpectation;
  values?: DnsValuesExpectation;
}

export interface ResolvedDnsSystemConfig {
  family: DnsFamily;
  name: string;
  resolver: "system";
}

export interface ResolvedDnsSystemExpectConfig {
  durationMs?: ValueExpectation;
  valueCount?: ValueExpectation;
  values?: DnsValuesExpectation;
}

export interface ResolvedDnsTarget extends ResolvedTargetBase {
  dns: ResolvedDnsConfig;
  expect?: ResolvedDnsExpectConfig;
  group: string;
  intervalMs: number;
  name: null | string;
  timeoutMs: number;
  type: "dns";
}
