import type { SSHHostWithStatus } from "@/main-axios";
import type { Host, Credential } from "@/types/ui-types";

type RawSSHHost = SSHHostWithStatus & {
  hasPassword?: boolean;
  hasKey?: boolean;
  hasKeyPassword?: boolean;
  hasSudoPassword?: boolean;
  hasRdpPassword?: boolean;
  hasVncPassword?: boolean;
  hasTelnetPassword?: boolean;
};
type HostQuickAction = Host["quickActions"][number];
type HostJumpHost = NonNullable<Host["jumpHosts"]>[number];
type RawCredential = {
  id: number | string;
  name: string;
  username: string;
  authType?: string;
  description?: string | null;
  folder?: string | null;
  tags?: string[];
  publicKey?: string | null;
  pin?: boolean | null;
  sortOrder?: number | null;
  certPublicKey?: string | null;
};

function parseJson<T>(v: unknown): T | undefined {
  if (!v) return undefined;
  if (typeof v === "string") {
    try {
      return JSON.parse(v) as T;
    } catch {
      return undefined;
    }
  }
  return v as T;
}

export function sshHostToHost(h: SSHHostWithStatus): Host {
  const host = h as RawSSHHost;
  const isSshHost = h.connectionType === "ssh" || !h.connectionType;
  const parsedTerminalConfig = parseJson(h.terminalConfig) as
    (Host["terminalConfig"] & { sudoPassword?: string }) | undefined;
  return {
    id: String(h.id),
    name: h.name,
    username: h.username,
    ip: h.ip,
    port: h.port,
    folder: h.folder ?? "",
    parentHostId:
      (h as { parentHostId?: number | string | null }).parentHostId != null
        ? String((h as { parentHostId?: number | string }).parentHostId)
        : null,
    online: h.status === "online",
    status: h.status,
    cpu: null,
    ram: null,
    lastAccess: "",
    tags: h.tags ?? [],
    syncId: h.syncId ?? null,
    authType: h.authType,
    shareSshAuth: h.shareSshAuth ?? false,
    password: h.password,
    hasPassword: !!host.hasPassword || !!h.password,
    hasKey: !!host.hasKey || !!(typeof h.key === "string" && h.key),
    hasKeyPassword: !!host.hasKeyPassword || !!h.keyPassword,
    key: typeof h.key === "string" ? h.key : undefined,
    keyPassword: h.keyPassword,
    keyType: h.keyType,
    credentialId: h.credentialId != null ? String(h.credentialId) : undefined,
    vaultProfileId:
      (h as { vaultProfileId?: number | string | null }).vaultProfileId != null
        ? String((h as { vaultProfileId?: number | string }).vaultProfileId)
        : undefined,
    notes: h.notes,
    pin: h.pin ?? false,
    sortOrder: h.sortOrder ?? null,
    macAddress: h.macAddress,
    wolBroadcastAddress: h.wolBroadcastAddress,
    enableSsh: h.enableSsh != null ? h.enableSsh : isSshHost,
    enableTerminal:
      h.enableTerminal ?? (h.enableSsh != null ? h.enableSsh : isSshHost),
    enableSessionLogging: h.enableSessionLogging ?? true,
    enableCommandHistory: h.enableCommandHistory ?? true,
    enableTunnel: h.enableTunnel ?? false,
    enableFileManager: h.enableFileManager ?? true,
    enableDocker: h.enableDocker ?? false,
    dockerConfig: h.dockerConfig ?? null,
    enableProxmox: h.enableProxmox ?? false,
    enableProxmoxStats: h.enableProxmoxStats ?? false,
    enableTmuxMonitor: h.enableTmuxMonitor ?? false,
    enableTerminalToolbar: h.enableTerminalToolbar ?? true,
    proxmoxConfig: h.proxmoxConfig ?? null,
    proxmoxStatsConfig: h.proxmoxStatsConfig ?? null,
    enableRdp: h.enableRdp != null ? h.enableRdp : h.connectionType === "rdp",
    enableVnc: h.enableVnc != null ? h.enableVnc : h.connectionType === "vnc",
    enableTelnet:
      h.enableTelnet != null ? h.enableTelnet : h.connectionType === "telnet",
    sshPort:
      h.sshPort ??
      (h.connectionType === "ssh" || !h.connectionType ? h.port : 22),
    rdpPort: h.rdpPort ?? (h.connectionType === "rdp" ? h.port : 3389),
    vncPort: h.vncPort ?? (h.connectionType === "vnc" ? h.port : 5900),
    telnetPort: h.telnetPort ?? (h.connectionType === "telnet" ? h.port : 23),
    rdpAuthType:
      (h.rdpAuthType as "direct" | "credential") ??
      (h.rdpCredentialId ? "credential" : "direct"),
    rdpCredentialId:
      h.rdpCredentialId != null ? String(h.rdpCredentialId) : undefined,
    rdpUser: h.rdpUser,
    rdpPassword: h.rdpPassword ?? "",
    hasRdpPassword: !!host.hasRdpPassword || !!h.rdpPassword,
    domain: h.rdpDomain,
    security: h.rdpSecurity,
    ignoreCert: h.rdpIgnoreCert ?? false,
    vncAuthType:
      (h.vncAuthType as "direct" | "credential") ??
      (h.vncCredentialId ? "credential" : "direct"),
    vncCredentialId:
      h.vncCredentialId != null ? String(h.vncCredentialId) : undefined,
    vncPassword: h.vncPassword ?? "",
    hasVncPassword: !!host.hasVncPassword || !!h.vncPassword,
    vncUser: h.vncUser,
    telnetAuthType:
      (h.telnetAuthType as "direct" | "credential") ??
      (h.telnetCredentialId ? "credential" : "direct"),
    telnetCredentialId:
      h.telnetCredentialId != null ? String(h.telnetCredentialId) : undefined,
    telnetUser: h.telnetUser,
    telnetPassword: h.telnetPassword ?? "",
    hasTelnetPassword: !!host.hasTelnetPassword || !!h.telnetPassword,
    quickActions: (h.quickActions ?? []).map((a) => ({
      name: a.name,
      snippetId: String(a.snippetId),
    })),
    serverTunnels: parseJson(h.tunnelConnections) ?? [],
    jumpHosts: (parseJson<HostJumpHost[]>(h.jumpHosts) ?? []).map((j) => ({
      hostId: String(j.hostId ?? j.hostid ?? j),
    })),
    portKnockSequence: parseJson(h.portKnockSequence) ?? [],
    defaultPath: h.defaultPath,
    terminalConfig: parsedTerminalConfig as Host["terminalConfig"],
    hasSudoPassword:
      !!host.hasSudoPassword || !!parsedTerminalConfig?.sudoPassword,
    statsConfig: parseJson(h.statsConfig) as Host["statsConfig"],
    guacamoleConfig: parseJson(h.guacamoleConfig),
    forceKeyboardInteractive: h.forceKeyboardInteractive ?? false,
    useSocks5: h.useSocks5,
    socks5Host: h.socks5Host,
    socks5Port: h.socks5Port,
    socks5Username: h.socks5Username,
    socks5Password: h.socks5Password,
    socks5ProxyChain: parseJson(h.socks5ProxyChain) ?? [],
    overrideCredentialUsername: h.overrideCredentialUsername ?? false,
    isShared: h.isShared ?? false,
    authOverrides: h.authOverrides
      ? Object.fromEntries(
          Object.entries(h.authOverrides).map(([protocol, state]) => [
            protocol,
            state
              ? {
                  ...state,
                  credentialId:
                    state.credentialId != null
                      ? String(state.credentialId)
                      : undefined,
                }
              : state,
          ]),
        )
      : undefined,
    permissionLevel: h.permissionLevel,
    sharedExpiresAt: h.sharedExpiresAt,
    ownerUsername: h.ownerUsername,
  };
}

export function mapCredentials(res: unknown): Credential[] {
  const arr = Array.isArray(res) ? res : [];
  return (arr as RawCredential[]).map((c) => ({
    id: String(c.id),
    name: c.name,
    username: c.username,
    type: c.authType === "key" ? "key" : "password",
    description: c.description ?? "",
    folder: c.folder ?? "",
    tags: c.tags ?? [],
    publicKey: c.publicKey ?? undefined,
    pin: c.pin ?? false,
    sortOrder: c.sortOrder ?? null,
    certPublicKey: c.certPublicKey ?? undefined,
  }));
}
