import adminClient from "./client"
import type { ApiResponse } from "../../types"
import { listResult } from "./response"

type CloudServerType = "dcimcloud" | "zjmf_finance"
type CloudAccountType = "admin" | "agent" | "client" | "resource"
type CloudServerStatus = "unknown" | "online" | "offline"

export interface CloudServer {
  id: number
  name: string
  server_type: CloudServerType
  account_type: CloudAccountType
  hostname: string
  port: number
  secure: boolean
  username: string
  client_id: number | null
  user_prefix: string | null
  disabled: boolean
  status: CloudServerStatus
  last_check_at: string | null
  last_check_message: string | null
  remark: string | null
  sort_order: number
  created_at: string
  updated_at: string
}

export interface CloudServerCreatePayload {
  name: string
  server_type: CloudServerType
  account_type: CloudAccountType
  hostname: string
  port: number
  secure: boolean
  username: string
  password: string
  client_id?: number | null
  user_prefix?: string | null
  disabled?: boolean
  remark?: string | null
  sort_order?: number
}

export type CloudServerUpdatePayload = Partial<CloudServerCreatePayload>

export interface CloudServerTestPayload {
  server_type: CloudServerType
  account_type: CloudAccountType
  hostname: string
  port: number
  secure: boolean
  username: string
  password: string
}

export interface CloudServerTestResult {
  ok: boolean
  message: string
  latency_ms: number | null
}

const BASE = "/v1/admin/cloud-servers"

function pick<T = unknown>(row: Record<string, unknown>, ...keys: string[]): T | undefined {
  for (const key of keys) {
    if (row[key] !== undefined && row[key] !== null) return row[key] as T
  }
  return undefined
}

function asString(value: unknown, fallback = "") {
  return typeof value === "string" ? value : value == null ? fallback : String(value)
}

function asNumber(value: unknown, fallback = 0) {
  const parsed = Number(value)
  return Number.isFinite(parsed) ? parsed : fallback
}

function asBool(value: unknown, fallback = false) {
  if (typeof value === "boolean") return value
  if (typeof value === "number") return value !== 0
  if (typeof value === "string") return ["1", "true", "yes", "on"].includes(value.toLowerCase())
  return fallback
}

function normalizeServerType(value: unknown): CloudServerType {
  const text = asString(value).trim()
  if (text === "zjmf_finance") return "zjmf_finance"
  return "dcimcloud"
}

function normalizeAccountType(value: unknown, serverType: CloudServerType): CloudAccountType {
  const text = asString(value).trim()
  if (serverType === "zjmf_finance") {
    return text === "resource" ? "resource" : "client"
  }
  return text === "agent" ? "agent" : "admin"
}

function normalizeStatus(value: unknown): CloudServerStatus {
  const text = asString(value).trim()
  if (text === "online" || text === "offline") return text
  return "unknown"
}

function normalizeCloudServer(value: CloudServer | Record<string, unknown>): CloudServer {
  const row = value as Record<string, unknown>
  const serverType = normalizeServerType(pick(row, "server_type", "ServerType"))
  return {
    id: asNumber(pick(row, "id", "ID")),
    name: asString(pick(row, "name", "Name")),
    server_type: serverType,
    account_type: normalizeAccountType(pick(row, "account_type", "AccountType"), serverType),
    hostname: asString(pick(row, "hostname", "Hostname")),
    port: asNumber(pick(row, "port", "Port")),
    secure: asBool(pick(row, "secure", "Secure"), true),
    username: asString(pick(row, "username", "Username")),
    client_id: pick(row, "client_id", "ClientID") == null ? null : asNumber(pick(row, "client_id", "ClientID")),
    user_prefix: pick(row, "user_prefix", "UserPrefix") == null ? null : asString(pick(row, "user_prefix", "UserPrefix")),
    disabled: asBool(pick(row, "disabled", "Disabled")),
    status: normalizeStatus(pick(row, "status", "Status")),
    last_check_at: pick(row, "last_check_at", "last_check_time", "LastCheckAt") == null ? null : asString(pick(row, "last_check_at", "last_check_time", "LastCheckAt")),
    last_check_message: pick(row, "last_check_message", "LastCheckMessage") == null ? null : asString(pick(row, "last_check_message", "LastCheckMessage")),
    remark: pick(row, "remark", "Remark") == null ? null : asString(pick(row, "remark", "Remark")),
    sort_order: asNumber(pick(row, "sort_order", "SortOrder")),
    created_at: asString(pick(row, "created_at", "CreatedAt")),
    updated_at: asString(pick(row, "updated_at", "UpdatedAt")),
  }
}

export async function listCloudServers() {
  const { data } = await adminClient.get<ApiResponse<CloudServer[] | { items: CloudServer[]; total: number }>>(BASE)
  return { ...data, data: listResult<CloudServer | Record<string, unknown>>(data.data).map(normalizeCloudServer) }
}

export async function createCloudServer(payload: CloudServerCreatePayload) {
  const { data } = await adminClient.post<ApiResponse<CloudServer>>(BASE, payload)
  return data
}

export async function updateCloudServer(id: number, payload: CloudServerUpdatePayload) {
  const { data } = await adminClient.put<ApiResponse<CloudServer>>(`${BASE}/${id}`, payload)
  return data
}

export async function deleteCloudServer(id: number) {
  const { data } = await adminClient.delete<ApiResponse<null>>(`${BASE}/${id}`)
  return data
}

export async function testSavedCloudServer(id: number) {
  const { data } = await adminClient.post<ApiResponse<CloudServerTestResult>>(
    `${BASE}/${id}/test`,
  )
  return data
}

export async function testUnsavedCloudServer(payload: CloudServerTestPayload) {
  const { data } = await adminClient.post<ApiResponse<CloudServerTestResult>>(
    `${BASE}/test`,
    payload,
  )
  return data
}
