use std::path::PathBuf;

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum TransportKind {
    Rtu,
    Tcp,
}

impl TransportKind {
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::Rtu => "RTU",
            Self::Tcp => "TCP",
        }
    }

    pub fn file_segment(&self) -> &'static str {
        match self {
            Self::Rtu => "rtu",
            Self::Tcp => "tcp",
        }
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ApiKind {
    StaticRead,
    RuntimeRead,
    Write,
}

impl ApiKind {
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::StaticRead => "STATIC_READ",
            Self::RuntimeRead => "RUNTIME_READ",
            Self::Write => "WRITE",
        }
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ValueType {
    Boolean,
    Int,
    String,
    Bytes,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ReadReturnKind {
    Dto,
    Boolean,
    Int,
    String,
    Bytes,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RegisterArea {
    Coil,
    DiscreteInput,
    HoldingRegister,
    InputRegister,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ContractTypedItem {
    pub name: String,
    pub summary: Option<String>,
    pub value_type: ValueType,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ContractMethod {
    pub summary: Option<String>,
    pub method_name: String,
    pub read_return_kind: Option<ReadReturnKind>,
    pub read_return_type_name: Option<String>,
    pub read_area: Option<RegisterArea>,
    pub write_area: Option<RegisterArea>,
    pub read_fields: Vec<ContractTypedItem>,
    pub parameters: Vec<ContractTypedItem>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ContractService {
    pub api_kind: ApiKind,
    pub interface_name: String,
    pub interface_summary: Option<String>,
    pub methods: Vec<ContractMethod>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ContractRenderRequest {
    pub transports: Vec<TransportKind>,
    pub services: Vec<ContractService>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ArtifactGroup {
    CServiceContract,
    CTransportContract,
    MarkdownProtocol,
    RustTokioModbus,
}

impl ArtifactGroup {
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::CServiceContract => "C_SERVICE_CONTRACT",
            Self::CTransportContract => "C_TRANSPORT_CONTRACT",
            Self::MarkdownProtocol => "MARKDOWN_PROTOCOL",
            Self::RustTokioModbus => "RUST_TOKIO_MODBUS",
        }
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GeneratedArtifact {
    pub relative_path: PathBuf,
    pub package_name: Option<String>,
    pub file_name: String,
    pub extension_name: String,
    pub content: String,
    pub artifact_group: ArtifactGroup,
    pub transport: TransportKind,
    pub service_interface_name: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ServiceSummary {
    pub api_kind: String,
    pub interface_package: String,
    pub interface_simple_name: String,
    pub summary: String,
    pub operation_count: i64,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GeneratedBundle {
    pub summary: String,
    pub artifacts: Vec<GeneratedArtifact>,
    pub services: Vec<ServiceSummary>,
}
