import { z } from "zod"
import {
  serverCreateSchema,
  serverIdParamSchema,
  snapshotsQuerySchema,
  serverUpdateSchema,
  testConnectionSchema,
  type ServerRead as ContractServerRead,
  type SnapshotRead as ContractSnapshotRead,
  type ServerCreate as ContractServerCreate,
  type ServerUpdate as ContractServerUpdate,
  type WanUplink as ContractWanUplinkRead,
} from "@mmapp/contracts/servers"

// ── RouterOS raw response types ────────────────────────────────────────────────

export interface RosIdentity {
  name: string
}

export interface RosResource {
  "uptime": string
  "version": string
  "build-time": string
  "factory-software": string
  "free-memory": string
  "total-memory": string
  "cpu": string
  "cpu-count": string
  "cpu-frequency": string
  "cpu-load": string
  "free-hdd-space": string
  "total-hdd-space": string
  "architecture-name": string
  "board-name": string
  "platform": string
}

export interface RosInterface {
  ".id": string
  name: string
  type: string
  mtu?: string
  "actual-mtu"?: string
  "mac-address"?: string
  running: string   // "true" | "false" (RouterOS returns strings)
  disabled: string
  comment?: string
}

export interface RosIpAddress {
  ".id": string
  address: string     // "192.168.1.1/24"
  network: string     // "192.168.1.0"
  interface: string
  disabled: string
  dynamic?: string
  invalid?: string
  comment?: string
}

// ── Zod schemas for API validation ────────────────────────────────────────────

export const ServerCreateSchema = serverCreateSchema
export const ServerUpdateSchema = serverUpdateSchema
export const TestConnectionSchema = testConnectionSchema
export const ServerIdParamSchema = serverIdParamSchema
export const SnapshotsQuerySchema = snapshotsQuerySchema

// Request payload types for route handlers.
// (Type-provider-zod in this repo sometimes falls back to `unknown` during cross-package schema wiring.)
export type ServerIdParams = z.infer<typeof ServerIdParamSchema>
export type TestConnectionRequest = z.infer<typeof TestConnectionSchema>
export type SnapshotsQuery = z.infer<typeof SnapshotsQuerySchema>
export type ServerCreateRequest = z.infer<typeof ServerCreateSchema>
export type ServerUpdateRequest = z.infer<typeof ServerUpdateSchema>

// ── Response types (what the API returns) ─────────────────────────────────────

/** Flat server response — mirrors the frontend's Server interface from lib/data.ts */
export type WanUplinkRead = ContractWanUplinkRead
export type ServerCreate = ContractServerCreate
export type ServerUpdate = ContractServerUpdate
export type ServerRead = ContractServerRead
export type SnapshotRead = ContractSnapshotRead

// ── BGP types ────────────────────────────────────────────────────────────────

/**
 * Raw BGP session object returned by RouterOS 7.x REST API
 * (/rest/routing/bgp/session).
 *
 * NOTE: RouterOS 7.x does NOT have a "state" field.
 *   - "established": "true"  → session is Established
 *   - Field absence           → session is not established (Active/Idle/Connect…)
 *   - "ebgp": ""             → session role is eBGP
 * Capabilities are comma-separated short codes in "local.capabilities" /
 * "remote.capabilities" (e.g. "mp,rr,gr,as4,enhe,role").
 */
export interface RosBgpSession {
  ".id":                  string
  "name"?:                string
  // RouterOS 7.x state flags (no "state" field)
  "established"?:         string   // "true" when session is up
  "ebgp"?:                string   // "" when eBGP
  // Addressing
  "remote.address"?:      string   // "10.0.0.1" or "10.0.0.1/32"
  "remote.as"?:           string
  "remote.id"?:           string
  "remote.messages"?:     string   // total received messages
  "remote.hold-time"?:    string   // e.g. "1m30s"
  "remote.capabilities"?: string   // "mp,rr,gr,as4"
  "remote.bytes"?:        string
  "remote.eor"?:          string
  "remote.afi"?:          string
  "remote.gr-time"?:      string
  "local.address"?:       string
  "local.as"?:            string
  "local.id"?:            string
  "local.messages"?:      string   // total sent messages
  "local.capabilities"?:  string   // "mp,rr,enhe,role,gr,as4"
  "local.bytes"?:         string
  "local.eor"?:           string
  "local.afi"?:           string
  "local.role"?:          string   // "ebgp-customer" | "ebgp-provider" | "ibgp" …
  "local.cluster-id"?:    string
  // Timers
  "hold-time"?:           string   // "1m30s" (active hold time, RouterOS 7.x)
  "keepalive-time"?:      string   // "30s"
  // Routing
  "prefix-count"?:        string
  "uptime"?:              string   // "1d5h13m23s580ms"
  "instance"?:            string
  "multihop"?:            string   // "true" | "false"
  // Filters
  "input.filter"?:        string
  "output.filter-chain"?: string
  "input.procid"?:        string
  "output.procid"?:       string
  // Timestamps
  "last-started"?:        string
  "last-notification"?:   string
  // Old RouterOS 6.x / some 7.x fields (kept for compatibility)
  "state"?:               string
  "active-holdtime"?:     string
  "total-messages-sent"?:     string
  "total-messages-received"?: string
  "total-updates-sent"?:      string
  "total-updates-received"?:  string
  "4-octet-as-capability"?:   string
  "refresh-capability"?:      string
  "as4-capability"?:          string
  "add-path-capability"?:     string
  "graceful-restart-capability"?: string
  "extended-message-capability"?: string
}

export interface BgpSessionRead {
  id:           string
  serverId:     number
  serverName:   string
  serverSite:   string
  serverCountry: string
  name:         string
  peerIp:       string
  remoteAs:     number
  localAs:      number
  localId:      string
  remoteId:     string
  state:        string
  type:         "eBGP" | "iBGP"
  uptime:       string | null
  holdTime:     number
  keepalive:    number
  prefixesRx:   number
  prefixesTx:   number
  inputMessages:  number
  outputMessages: number
  capabilities:   string[]
  lastError:      string | null
}

// ── OSPF types ────────────────────────────────────────────────────────────────

/** Raw RouterOS 7.x /rest/routing/ospf/neighbor */
export interface RosOspfNeighbor {
  ".id":          string
  "address":      string   // neighbor IP
  "router-id":    string
  "instance":     string   // OSPF instance name
  "area":         string   // area NAME (not area-id)
  "interface":    string   // local interface
  "state":        string   // "Full" | "2-Way" | "ExStart" | "Exchange" | "Loading" | "Down"
  "adjacency"?:   string   // uptime of adjacency, e.g. "1h30m17s"
  "state-changes"?: string
  "timeout"?:     string
  "dynamic"?:     string
  "priority"?:    string
}

/** Raw RouterOS 7.x /rest/routing/ospf/area */
export interface RosOspfArea {
  ".id":         string
  "name":        string
  "area-id"?:    string   // "0.0.0.1" — may be absent for backbone when using ROS defaults
  "instance":    string
  "type":        string   // "default" | "stub" | "nssa" | "totally-stub"
  "disabled":    string
  "inactive":    string
  ".about"?:     string   // error note when area is inactive
  "nssa-translator"?: string
}

/** Raw RouterOS 7.x /rest/routing/ospf/interface-template */
export interface RosOspfInterfaceTemplate {
  ".id":                string
  "area":               string   // area NAME (not area-id)
  "interfaces"?:        string   // interface name or "*ID" ref
  "cost"?:              string
  "priority"?:          string
  "type"?:              string   // "ptp" | "broadcast" | "nbma" | "ptmp" | "ptmp-broadcast"
  "disabled":           string
  "inactive":           string
  "hello-interval"?:    string   // e.g. "10s"
  "dead-interval"?:     string   // e.g. "40s"
  "retransmit-interval"?: string
  "transmit-delay"?:    string
  "use-bfd"?:           string
  "instance-id"?:       string
  ".about"?:            string
}

/** Raw RouterOS 7.x /rest/routing/ospf/instance */
export interface RosOspfInstance {
  ".id":             string
  "name":            string
  "router-id":       string   // may be "main" to use main routing table router-id
  "version":         string   // "2" | "3"
  "disabled":        string
  "inactive":        string
  "redistribute"?:   string
  "routing-table"?:  string
  "vrf"?:            string
  "in-filter-chain"?:  string
  "out-filter-chain"?: string
}

// ── Normalized OSPF read types (API response) ─────────────────────────────────

export interface OspfNeighborRead {
  id:           string
  serverId:     number
  serverName:   string
  serverSite:   string
  serverCountry: string
  address:      string
  routerId:     string
  instance:     string
  area:         string    // area name
  areaId:       string    // area-id like "0.0.0.1"
  interface:    string
  state:        string
  uptime:       string | null
  stateChanges: number
  priority:     number
}

export interface OspfInterfaceRead {
  id:           string
  serverId:     number
  serverName:   string
  serverSite:   string
  serverCountry: string
  instance:     string
  area:         string   // area name
  areaId:       string   // area-id
  interface:    string   // interface name
  cost:         number
  type:         string   // "ptp" | "broadcast" | ...
  disabled:     boolean
  inactive:     boolean
  priority:     number
  helloInterval: number  // seconds
  deadInterval:  number  // seconds
  useBfd:       boolean
}

export interface OspfInstanceRead {
  id:           string
  serverId:     number
  serverName:   string
  serverSite:   string
  serverCountry: string
  name:         string
  routerId:     string
  version:      number
  disabled:     boolean
  inactive:     boolean
  redistribute: string
}

// ── IP Route / Firewall / Log / Ping ─────────────────────────────────────────

export interface RosIpRoute {
  ".id":            string
  "dst-address":    string
  "pref-src"?:      string
  "gateway"?:       string
  "distance"?:      string
  "scope"?:         string
  "active"?:        string   // "true"
  "dynamic"?:       string
  "static"?:        string
  "connect"?:       string
  "bgp"?:           string
  "ospf"?:          string
  "rip"?:           string
  "blackhole"?:     string
  "unreachable"?:   string
  "prohibit"?:      string
  "interface"?:     string
  "routing-mark"?:  string
  "type"?:          string
}

export interface RosFirewallFilter {
  ".id":                string
  "chain":              string
  "action":             string
  "protocol"?:          string
  "src-address"?:       string
  "dst-address"?:       string
  "src-port"?:          string
  "dst-port"?:          string
  "in-interface"?:      string
  "out-interface"?:     string
  "connection-state"?:  string
  "src-address-list"?:  string
  "dst-address-list"?:  string
  "layer7-protocol"?:   string
  "tls-host"?:          string
  "comment"?:           string
  "disabled"?:          string
  "invalid"?:           string
  "dynamic"?:           string
  "bytes"?:             string
  "packets"?:           string
  "log"?:               string
  "log-prefix"?:        string
}

export interface RosFirewallAddressList {
  ".id":             string
  list:              string
  address:           string
  comment?:          string
  disabled?:         string
  timeout?:          string
  dynamic?:          string
  "creation-time"?:  string
}

export type FirewallFamily = "ip" | "ip6"
export type FirewallTable = "filter" | "nat" | "mangle" | "raw"

export interface RosLogEntry {
  ".id":     string
  "time":    string
  "message": string
  "topics":  string
}

/** One reply item from POST /rest/tool/ping */
export interface RosPingResult {
  "host"?:         string
  "seq":           string
  "size"?:         string
  "ttl"?:          string
  "time"?:         string
  "sent"?:         string
  "received"?:     string
  "packet-loss"?:  string
  "status"?:       string   // "timeout" when lost
}

// ── BFD types ─────────────────────────────────────────────────────────────────

/** Raw RouterOS 7.x /rest/routing/bfd/session */
export interface RosBfdSession {
  ".id":                   string
  "state":                 string   // "up" | "down" | "init" | "admindown"
  "up"?:                   string   // "true" when up
  "uptime"?:               string   // e.g. "6h15m29s"
  "local-address":         string   // "10.100.2.13%NSK-SERVHOST-MTS" (IP%iface)
  "remote-address":        string   // "10.100.2.14%NSK-SERVHOST-MTS"
  "multihop"?:             string   // "true" | "false"
  "multiplier"?:           string   // detection multiplier
  "desired-tx-interval"?:  string   // "200ms"
  "required-min-rx"?:      string   // "200ms"
  "actual-tx-interval"?:   string   // "200ms"
  "remote-min-rx"?:        string   // "200ms"
  "remote-min-tx"?:        string   // "200ms"
  "hold-time"?:            string   // "1s"
  "packets-rx"?:           string
  "packets-tx"?:           string
  "state-changes"?:        string
  "vrf"?:                  string
}

export interface BfdSessionRead {
  id:           string
  serverId:     number
  serverName:   string
  serverSite:   string
  serverCountry: string
  localAddr:    string   // IP only, without %iface
  remoteAddr:   string   // IP only
  interface:    string   // extracted from %iface suffix
  state:        string   // "Up" | "Down" | "Init" | "AdminDown"
  uptime:       string | null
  multihop:     boolean
  multiplier:   number
  txInterval:   number   // ms
  rxInterval:   number   // ms
  holdTime:     number   // ms
  packetsRx:    number
  packetsTx:    number
  stateChanges: number
}
