use std::sync::Arc;

use crate::config::RtcConfig;
use crate::error::EnigmaRtcError;
use crate::session::CallSession;
use crate::signaling::encode_signaling;
use crate::types::SignalingMessage;
use crate::MockWebRtcEngine;

#[test]
fn cannot_create_multiple_offers() {
    let config = RtcConfig::default();
    let engine = Arc::new(MockWebRtcEngine::new());
    let session = CallSession::with_engine(config, engine).unwrap();
    session.create_offer().unwrap();
    let err = session.create_offer().unwrap_err();
    assert!(matches!(err, EnigmaRtcError::InvalidState));
}

#[test]
fn cannot_accept_answer_before_offer() {
    let config = RtcConfig::default();
    let engine = Arc::new(MockWebRtcEngine::new());
    let session = CallSession::with_engine(config, engine).unwrap();
    let err = session.accept_answer("remote-answer").unwrap_err();
    assert!(matches!(err, EnigmaRtcError::InvalidState));
}

#[test]
fn invalid_candidate_json_is_rejected() {
    let config = RtcConfig::default();
    let engine = Arc::new(MockWebRtcEngine::new());
    let session = CallSession::with_engine(config, engine).unwrap();
    session.create_offer().unwrap();
    session.accept_answer("remote-answer").unwrap();
    let err = session.add_ice_candidate("not-json").unwrap_err();
    assert!(matches!(err, EnigmaRtcError::JsonError(_)));
}

#[test]
fn hangup_twice_fails() {
    let config = RtcConfig::default();
    let engine = Arc::new(MockWebRtcEngine::new());
    let session = CallSession::with_engine(config, engine).unwrap();
    session.create_offer().unwrap();
    session.accept_answer("remote-answer").unwrap();
    session.hangup(None).unwrap();
    let err = session.hangup(None).unwrap_err();
    assert!(matches!(err, EnigmaRtcError::InvalidState));
}

#[test]
fn add_invalid_candidate_payload() {
    let config = RtcConfig::default();
    let engine = Arc::new(MockWebRtcEngine::new());
    let session = CallSession::with_engine(config, engine).unwrap();
    session.create_offer().unwrap();
    session.accept_answer("remote-answer").unwrap();
    let message = SignalingMessage::Offer {
        sdp: "bad".to_string(),
    };
    let payload = encode_signaling(&message);
    let err = session.add_ice_candidate(&payload).unwrap_err();
    assert!(matches!(err, EnigmaRtcError::InvalidCandidate));
}
