use erp_core::error::AppError;

/// Config module error types.
#[derive(Debug, thiserror::Error)]
pub enum ConfigError {
    #[error("验证失败: {0}")]
    Validation(String),

    #[error("资源未找到: {0}")]
    NotFound(String),

    #[error("键已存在: {0}")]
    DuplicateKey(String),

    #[error("编号序列耗尽: {0}")]
    NumberingExhausted(String),

    #[error("版本冲突: 数据已被其他操作修改，请刷新后重试")]
    VersionMismatch,
}

impl From<sea_orm::TransactionError<ConfigError>> for ConfigError {
    fn from(err: sea_orm::TransactionError<ConfigError>) -> Self {
        match err {
            sea_orm::TransactionError::Connection(err) => ConfigError::Validation(err.to_string()),
            sea_orm::TransactionError::Transaction(inner) => inner,
        }
    }
}

impl From<sea_orm::DbErr> for ConfigError {
    fn from(err: sea_orm::DbErr) -> Self {
        ConfigError::Validation(err.to_string())
    }
}

impl From<ConfigError> for AppError {
    fn from(err: ConfigError) -> Self {
        match err {
            ConfigError::Validation(s) => AppError::Validation(s),
            ConfigError::NotFound(s) => AppError::NotFound(s),
            ConfigError::DuplicateKey(s) => AppError::Conflict(s),
            ConfigError::NumberingExhausted(s) => AppError::Internal(s),
            ConfigError::VersionMismatch => AppError::VersionMismatch,
        }
    }
}

pub type ConfigResult<T> = Result<T, ConfigError>;

#[cfg(test)]
mod tests {
    use super::*;
    use erp_core::error::AppError;

    #[test]
    fn config_error_validation_maps_to_app_validation() {
        let app: AppError = ConfigError::Validation("字段不能为空".to_string()).into();
        match app {
            AppError::Validation(msg) => assert_eq!(msg, "字段不能为空"),
            other => panic!("期望 Validation，实际得到 {:?}", other),
        }
    }

    #[test]
    fn config_error_not_found_maps_to_app_not_found() {
        let app: AppError = ConfigError::NotFound("字典不存在".to_string()).into();
        match app {
            AppError::NotFound(msg) => assert_eq!(msg, "字典不存在"),
            other => panic!("期望 NotFound，实际得到 {:?}", other),
        }
    }

    #[test]
    fn config_error_duplicate_key_maps_to_app_conflict() {
        let app: AppError = ConfigError::DuplicateKey("编码已存在".to_string()).into();
        match app {
            AppError::Conflict(msg) => assert_eq!(msg, "编码已存在"),
            other => panic!("期望 Conflict，实际得到 {:?}", other),
        }
    }

    #[test]
    fn config_error_numbering_exhausted_maps_to_app_internal() {
        let app: AppError = ConfigError::NumberingExhausted("序列已耗尽".to_string()).into();
        match app {
            AppError::Internal(msg) => assert!(msg.contains("序列已耗尽")),
            other => panic!("期望 Internal，实际得到 {:?}", other),
        }
    }

    #[test]
    fn config_error_version_mismatch_maps_to_app_version_mismatch() {
        let app: AppError = ConfigError::VersionMismatch.into();
        match app {
            AppError::VersionMismatch => {}
            other => panic!("期望 VersionMismatch，实际得到 {:?}", other),
        }
    }

    #[test]
    fn config_error_display_messages() {
        // 验证各变体的 Display 输出包含中文描述
        assert!(
            ConfigError::Validation("test".into())
                .to_string()
                .contains("验证失败")
        );
        assert!(
            ConfigError::NotFound("test".into())
                .to_string()
                .contains("资源未找到")
        );
        assert!(
            ConfigError::DuplicateKey("test".into())
                .to_string()
                .contains("键已存在")
        );
        assert!(
            ConfigError::NumberingExhausted("test".into())
                .to_string()
                .contains("编号序列耗尽")
        );
        assert!(
            ConfigError::VersionMismatch
                .to_string()
                .contains("版本冲突")
        );
    }

    #[test]
    fn transaction_error_connection_maps_to_validation() {
        // TransactionError::Connection 应该转换为 ConfigError::Validation
        let config_err: ConfigError = sea_orm::TransactionError::Connection(sea_orm::DbErr::Conn(
            sea_orm::RuntimeErr::Internal("连接失败".to_string()),
        ))
        .into();
        match config_err {
            ConfigError::Validation(msg) => assert!(msg.contains("连接失败")),
            other => panic!("期望 Validation，实际得到 {:?}", other),
        }
    }
}
