use serde::Serialize;
use serde_json::Value;
use std::collections::HashMap;

#[derive(Debug, Clone, Serialize)]
pub struct LocalClusterDatabaseCreateOptions {
    pub owner: Option<String>,
    pub template: Option<String>,
    pub encoding: Option<String>,
    pub lc_collate: Option<String>,
    pub lc_ctype: Option<String>,
    pub tablespace: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct LocalClusterCreateDatabaseParams {
    pub database_name: String,
    pub options: LocalClusterDatabaseCreateOptions,
}

#[derive(Debug, Clone)]
pub struct SpinUpPostgresParams {
    pub client_name: String,
    pub container_name: Option<String>,
    pub image: Option<String>,
    pub host: Option<String>,
    pub host_port: Option<u16>,
    pub db_name: Option<String>,
    pub username: Option<String>,
    pub password: Option<String>,
    pub startup_timeout_secs: Option<u64>,
    pub reuse_existing: bool,
}

#[derive(Debug, Clone)]
pub struct NeonConnectionParams {
    pub api_key: String,
    pub project_id: String,
    pub branch_id: Option<String>,
    pub database_name: Option<String>,
    pub role_name: Option<String>,
    pub endpoint_id: Option<String>,
    pub api_base_url: Option<String>,
}

#[derive(Debug, Clone)]
pub struct RailwayConnectionParams {
    pub api_key: String,
    pub project_id: String,
    pub environment_id: String,
    pub service_id: Option<String>,
    pub plugin_id: Option<String>,
    pub graphql_url: Option<String>,
}

#[derive(Debug, Clone)]
pub struct RenderConnectionParams {
    pub api_key: String,
    pub service_id: String,
    pub api_base_url: Option<String>,
}

#[derive(Debug, Clone)]
pub struct NeonProjectCreateParams {
    pub api_key: String,
    pub project_name: Option<String>,
    pub project_payload: Option<Value>,
    pub api_base_url: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct NeonProjectCreateResult {
    pub project_id: String,
    pub branch_id: Option<String>,
    pub raw: Value,
}

#[derive(Debug, Clone)]
pub struct RailwayProjectCreateParams {
    pub api_key: String,
    pub project_input: Value,
    pub graphql_url: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct RailwayProjectCreateResult {
    pub project_id: String,
    pub base_environment_id: Option<String>,
    pub raw: Value,
}

#[derive(Debug, Clone)]
pub struct RailwayServiceCreateParams {
    pub api_key: String,
    pub service_input: Value,
    pub graphql_url: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct RailwayServiceCreateResult {
    pub service_id: String,
    pub raw: Value,
}

#[derive(Debug, Clone)]
pub struct RailwayPluginCreateParams {
    pub api_key: String,
    pub plugin_input: Value,
    pub graphql_url: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct RailwayPluginCreateResult {
    pub plugin_id: String,
    pub raw: Value,
}

#[derive(Debug, Clone)]
pub struct RenderPostgresCreateParams {
    pub api_key: String,
    pub owner_id: Option<String>,
    pub service_name: Option<String>,
    pub service_payload: Option<Value>,
    pub plan: Option<String>,
    pub region: Option<String>,
    pub postgres_version: Option<String>,
    pub disk_size_gb: Option<u32>,
    pub api_base_url: Option<String>,
}

#[derive(Debug, Clone, Serialize)]
pub struct RenderPostgresCreateResult {
    pub service_id: String,
    pub raw: Value,
}

#[derive(Debug, Clone, Serialize)]
pub struct SpinUpPostgresResult {
    pub client_name: String,
    pub container_name: String,
    pub image: String,
    pub host: String,
    pub host_port: u16,
    pub db_name: String,
    pub username: String,
    pub password: String,
    pub pg_uri: String,
    pub created_new_container: bool,
    pub reused_existing_container: bool,
    pub wait_ready_ms: u128,
}

#[derive(Debug, Clone, Serialize)]
pub struct DockerContainerStatus {
    pub container_name: String,
    pub exists: bool,
    pub running: bool,
    pub status: Option<String>,
    pub image: Option<String>,
    pub host_port: Option<u16>,
}

#[derive(Debug, Clone, Serialize)]
pub struct DockerManagedContainer {
    pub container_name: String,
    pub running: bool,
    pub status: Option<String>,
    pub image: Option<String>,
    pub host_port: Option<u16>,
    pub labels: HashMap<String, String>,
}

#[derive(Debug, Clone)]
pub(crate) struct ResolvedSpinUpConfig {
    pub(crate) client_name: String,
    pub(crate) container_name: String,
    pub(crate) image: String,
    pub(crate) host: String,
    pub(crate) host_port: u16,
    pub(crate) db_name: String,
    pub(crate) username: String,
    pub(crate) password: String,
    pub(crate) startup_timeout_secs: u64,
    pub(crate) reuse_existing: bool,
}
