use crate::client::HafasClient;
use crate::parse::journeys_response::HafasJourneysResponse;
use crate::Journey;
use crate::{Client, Result, TariffClass};
#[cfg(feature = "wasm-bindings")]
use js_sys::Promise;
use serde::Deserialize;
use serde::Serialize;
use serde_json::json;
#[cfg(feature = "wasm-bindings")]
use wasm_bindgen::prelude::wasm_bindgen;
#[cfg(feature = "wasm-bindings")]
use wasm_bindgen::JsValue;
#[cfg(feature = "wasm-bindings")]
use wasm_bindgen_futures::future_to_promise;

#[derive(Debug, Default, Deserialize, Serialize)]
pub struct RefreshJourneyOptions {
    pub stopovers: Option<bool>,
    #[cfg(feature = "polylines")]
    pub polylines: Option<bool>,
    pub tickets: Option<bool>,
    pub tariff_class: Option<TariffClass>,
    pub language: Option<String>,
}

pub type RefreshJourneyResponse = Journey;

impl HafasClient {
    pub async fn refresh_journey(
        &self,
        refresh_token: &str,
        opts: RefreshJourneyOptions,
    ) -> Result<RefreshJourneyResponse> {
        let tariff_class = opts.tariff_class.unwrap_or(TariffClass::Second);

        let mut req = json!({
            "svcReqL": [
                {
                    "cfg": {},
                    "meth": "Reconstruction",
                    "req": {
                        "getIST": true,
                        "getPasslist": opts.stopovers.unwrap_or(false),
                        "getTariff": opts.tickets.unwrap_or(false),
                    }
                }
            ],
            "lang": opts.language.as_deref().unwrap_or("en"),
        });
        if self.profile.refresh_journey_use_out_recon_l() {
            req["svcReqL"][0]["req"]["outReconL"] = json!([{ "ctx": refresh_token }]);
        } else {
            req["svcReqL"][0]["req"]["ctxRecon"] = json!(refresh_token);
        }
        #[cfg(feature = "polylines")]
        {
            req["svcReqL"][0]["req"]["getPolyline"] = json!(opts.polylines.unwrap_or(false));
        }
        #[cfg(not(feature = "polylines"))]
        {
            req["svcReqL"][0]["req"]["getPolyline"] = json!(false);
        }
        let data: HafasJourneysResponse = self.request(req).await?;

        let mut journeys = self.profile.parse_journeys_response(data, tariff_class)?;
        Ok(journeys.journeys.remove(0))
    }
}

#[cfg(feature = "wasm-bindings")]
#[wasm_bindgen]
impl HafasClient {
    #[wasm_bindgen(js_name = "refreshJourney")]
    pub fn wasm_refresh_journey(&self, refresh_token: String, opts: JsValue) -> Promise {
        let client = self.clone();
        future_to_promise(async move {
            let opts = opts.into_serde().map_err(|e| e.to_string())?;
            let res = client
                .refresh_journey(&refresh_token, opts)
                .await
                .map_err(|e| e.to_string())?;
            Ok(JsValue::from_serde(&res).map_err(|e| e.to_string())?)
        })
    }
}
