use std::collections::VecDeque;

use nana_domain::{TurnFailure, TurnFailureCode, TurnRequest, TurnResult};
use thiserror::Error;

pub const LAPP_BASELINE_COMMIT: &str = "5ba3c659e1536ec4bee16340faca603940a5cb17";

#[derive(Debug, Error)]
pub enum ProviderError {
    #[error("no recorded response remains")]
    FixtureExhausted,
    #[error("LAPP profile could not be loaded: {0}")]
    Profile(String),
}

pub trait TurnProvider {
    fn complete_turn(&mut self, request: &TurnRequest) -> Result<TurnResult, ProviderError>;
}

#[derive(Debug)]
pub struct FakeProvider {
    responses: VecDeque<TurnResult>,
}

impl FakeProvider {
    #[must_use]
    pub fn new(responses: impl IntoIterator<Item = TurnResult>) -> Self {
        Self {
            responses: responses.into_iter().collect(),
        }
    }
}

impl TurnProvider for FakeProvider {
    fn complete_turn(&mut self, _request: &TurnRequest) -> Result<TurnResult, ProviderError> {
        self.responses
            .pop_front()
            .ok_or(ProviderError::FixtureExhausted)
    }
}

pub fn load_default_lapp_profile() -> Result<openlapp::Profile, ProviderError> {
    openlapp::load_default_profile().map_err(|error| ProviderError::Profile(error.to_string()))
}

#[must_use]
pub fn provider_failure(message: impl Into<String>) -> TurnFailure {
    TurnFailure {
        code: TurnFailureCode::ProviderUnavailable,
        message: message.into(),
        retryable: true,
    }
}
