import { ToastStyles } from "@/twui/components/elements/Toast";
import { DATASQUIREL_LoggedInUser } from "@moduletrace/datasquirel/dist/package-shared/types";
import useAppInit from "../hooks/use-app-init";
import { ServerWebSocket } from "bun";
import { ChildProcess } from "child_process";
import { NSQLITE_TURBOCI_ADMIN_USERS } from "../db/types";

export type User = DATASQUIREL_LoggedInUser & {
    super_admin?: boolean;
};

export const CloudProviders = [
    {
        title: "Hetzner",
        value: "hetzner",
    },
    {
        title: "Amazon Web Services",
        value: "aws",
    },
    {
        title: "Google Cloud Platform",
        value: "gcp",
    },
    {
        title: "Microsoft Azure",
        value: "azure",
    },
] as const;

export type ParsedDeploymentServiceConfig = TCIConfigServiceConfig & {
    service_name: string;
    parent_service_name?: string;
    servers?: NormalizedServerObject[];
};

export type NormalizedServerObject = {
    public_ip?: string;
    private_ip?: string;
};

export type TCIConfig = {
    deployment_name: string;
    duplicate_deployment_name?: string;
    description?: string;
    location?: string;
    availability_zone?: string;
    provider: (typeof CloudProviders)[number]["value"];
    services: TCIConfigService;
    env?: { [k: string]: string };
    env_file?: string;
    pre_deployment?: TCIRunObj;
};

export type TCIGlobalConfig = Omit<TCIConfig, "services"> & {
    services: ParsedDeploymentServiceConfig[];
    relay_server_ip?: string;
};

export type TCIConfigService = {
    [k: string]: TCIConfigServiceConfig;
};

export const TCIServiceTypes = [
    {
        title: "Default Service",
        value: "default",
    },
    {
        title: "Docker",
        value: "docker",
    },
    {
        title: "Load Balancer",
        value: "load_balancer",
    },
] as const;

export const TCIServiceOS = [
    {
        title: "Debian 12 Bookworm",
        value: "debian_12",
    },
    {
        title: "Debian 13 Buster",
        value: "debian_13",
    },
    {
        title: "Ubuntu 23.0.4",
        value: "ubuntu_23_0_4",
    },
] as const;

export const TCIServiceDependecyTypes = [
    {
        title: "Debian APT",
        value: "apt",
    },
    {
        title: "Turbo CI",
        value: "turboci",
    },
] as const;

export type TCIConfigServiceConfig = {
    type?: (typeof TCIServiceTypes)[number]["value"];
    os?: string;
    server_type?: string;
    enable_public_ip?: boolean;
    instances?: number;
    clusters?: number;
    dir_mappings?: TCIConfigServiceConfigDirMApping[];
    dependencies?: {
        [k in (typeof TCIServiceDependecyTypes)[number]["value"]]?: string[];
    };
    env?: { [k: string]: string };
    env_file?: string;
    target_services?: TCIConfigServiceConfigLBTarget[];
    run?: TCIConfigServiceConfigRun;
    ssl?: TCIConfigServiceSSL;
    duplicate_service_name?: string;
    healthcheck?: TCIConfigServiceHealthcheck;
    /**
     * Commoands to Run on first run
     */
    init?: string[];
    logs?: TCIConfigServiceConfigLog[];
};

export type TCIConfigServiceConfigLog =
    | string
    | {
          cmd: string;
      };

export type TCIConfigServiceHealthcheck = {
    cmd: string;
    test: string;
};

export type TCIConfigServiceDomain = {
    domain_name: string;
};

export type TCIConfigServiceSSL = {
    email: string;
};

export type TCIConfigServiceConfigLBTarget = {
    service_name: string;
    port: number;
    weight?: number;
    backup?: boolean;
    domains?: (string | TCIConfigServiceDomain)[];
};

export type TCIConfigServiceConfigRun = {
    preflight?: TCIRunObj;
    start?: TCIRunObj;
    postflight?: TCIRunObj;
    work_dir?: string;
};

export type TCIRunObj = {
    cmds?: string[];
    work_dir?: string;
    file?: string;
};

export type TCIConfigServiceConfigDirMApping = {
    src: string;
    dst: string;
    ignore_file?: string;
    ignore_patterns?: string[];
    use_gitignore?: boolean;
    relay_ignore?: string[];
};

export type ServiceScriptObject = {
    sh: string;
    service_name: string;
    deployment_name: string;
    work_dir?: string;
};

export type URLQueryType = {
    service_name?: string | null;
    deployment_user_id?: string | null;
};

export type PagePropsType = {
    deployment?: TCIGlobalConfig | null;
    query?: URLQueryType | null;
    user: User;
    pageUrl?: string | null;
    deployment_id?: string | null;
    service?: ParsedDeploymentServiceConfig | null;
    children_services?: ParsedDeploymentServiceConfig[] | null;
    deployment_users?: NSQLITE_TURBOCI_ADMIN_USERS[] | null;
    deployment_user?: NSQLITE_TURBOCI_ADMIN_USERS | null;
};

export type APIReqObject = {
    username?: string;
    email?: string;
    password?: string;
    new_user?: TurboCISignupFormObject;
    user_id?: string | number;
};

export type LoginFormData = {
    username?: string;
    email?: string;
    password?: string;
};

export type AlertObject = {
    text?: string;
    field_name?: string;
};

export type WebSocketData = {
    user: User;
};

export type TurboCISignupFormObject = {
    first_name?: string;
    last_name?: string;
    email?: string;
    password?: string;
    confirmed_password?: string;
    username?: string;
    image?: string;
};

export type TurboCIAdminAppContextType = ReturnType<typeof useAppInit>;

export const WebSocketEvents = [
    "client:ping",
    "client:service-server-logs",
    "client:kill-port",
    "client:kill-all-ports",
    "client:service-server-shell",

    "server:ping",
    "server:error",
    "server:message",
    "server:ready",
    "server:success",
    "server:update",
    "server:service-server-logs",
    "server:killed-port",
    "server:killed-all-ports",
    "server:service-server-shell",
] as const;

export type WebSocketDataType = {
    event: (typeof WebSocketEvents)[number];
    message?: string;
    service?: Omit<ParsedDeploymentServiceConfig, "servers">;
    server?: NormalizedServerObject;
    ttyd?: TtydInfoObject;
    port?: string | number;
    cmd?: string;
};

export type WebSocketMessageParam = {
    ws: ServerWebSocket<WebSocketData>;
    message?: string | Buffer;
    data?: WebSocketDataType;
};

export type WebSocketType = {
    socket?: WebSocket;
    data?: WebSocketDataType | null;
    message?: string;
    sendData?: (data: WebSocketDataType) => void;
};

export type ToastType = {
    toastStyle?: (typeof ToastStyles)[number];
    toastMessage?: string;
    toastOpen: boolean;
    closeDelay?: number;
};

export type TtydInfoObject = {
    url: string;
    href?: string;
    port: number;
};

export const PrivateServerTtydParadigms = [
    {
        name: "logs",
    },
    {
        name: "terminal",
    },
] as const;

export type WebSocketConnectedUserData = {
    user: User;
    child_processes: ChildProcess[];
    ports: (string | number)[];
};

export const ServerTerminalTargets = [
    { name: "logs" },
    { name: "shell" },
] as const;
