use super::types::PlaceOrderResponse;
use crate::graphql::place_limit_order;
use crate::graphql::place_market_order;
use crate::types::{BuyOrSell, OrderStatus, OrderType};
use chrono::{DateTime, Utc};
use std::str::FromStr;

impl From<place_limit_order::ResponseData> for PlaceOrderResponse {
    fn from(response: place_limit_order::ResponseData) -> Self {
        let response = response.place_limit_order;
        Self {
            status: response.status.into(),
            order_id: response.id,
            remaining_orders: response.orders_till_sign_state as u64,
            placed_at: DateTime::<Utc>::from_str(&response.placed_at)
                .expect("ME returned invalid placed_at DateTime for PlaceOrderResponse"),
            order_type: response.type_.into(),
            buy_or_sell: response.buy_or_sell.into(),
            market_name: response.market.name.clone(),
        }
    }
}

impl From<place_limit_order::OrderStatus> for OrderStatus {
    fn from(status: place_limit_order::OrderStatus) -> Self {
        match status {
            place_limit_order::OrderStatus::PENDING => Self::Pending,
            place_limit_order::OrderStatus::CANCELLED => Self::Canceled,
            place_limit_order::OrderStatus::OPEN => Self::Open,
            place_limit_order::OrderStatus::FILLED => Self::Filled,
            // This should never happen. Seems to be generated by the the rust graphql library, not the schema
            place_limit_order::OrderStatus::Other(_) => {
                panic!("Order status set to something invalid")
            }
        }
    }
}

impl From<place_limit_order::OrderBuyOrSell> for BuyOrSell {
    fn from(response: place_limit_order::OrderBuyOrSell) -> Self {
        match response {
            place_limit_order::OrderBuyOrSell::BUY => Self::Buy,
            place_limit_order::OrderBuyOrSell::SELL => Self::Sell,
            _ => panic!("Unexpected value in BuyOrSell enum"),
        }
    }
}

impl From<place_limit_order::OrderType> for OrderType {
    fn from(response: place_limit_order::OrderType) -> Self {
        match response {
            place_limit_order::OrderType::MARKET => Self::Market,
            place_limit_order::OrderType::LIMIT => Self::Limit,
            place_limit_order::OrderType::STOP_MARKET => Self::StopMarket,
            place_limit_order::OrderType::STOP_LIMIT => Self::StopLimit,
            _ => panic!("Unexpected value in OrderType enum"),
        }
    }
}



impl From<place_market_order::ResponseData> for PlaceOrderResponse {
    fn from(response: place_market_order::ResponseData) -> Self {
        let response = response.place_market_order;
        Self {
            status: response.status.into(),
            order_id: response.id,
            remaining_orders: response.orders_till_sign_state as u64,
            placed_at: DateTime::<Utc>::from_str(&response.placed_at)
                .expect("ME returned invalid placed_at DateTime for PlaceOrderResponse"),
            order_type: OrderType::Market,
            buy_or_sell: response.buy_or_sell.into(),
            market_name: response.market.name.clone(),
        }
    }
}

impl From<place_market_order::OrderStatus> for OrderStatus {
    fn from(status: place_market_order::OrderStatus) -> Self {
        match status {
            place_market_order::OrderStatus::PENDING => Self::Pending,
            place_market_order::OrderStatus::CANCELLED => Self::Canceled,
            place_market_order::OrderStatus::OPEN => Self::Open,
            place_market_order::OrderStatus::FILLED => Self::Filled,
            // This should never happen. Seems to be generated by the the rust graphql library, not the schema
            place_market_order::OrderStatus::Other(_) => {
                panic!("Order status set to something invalid")
            }
        }
    }
}

impl From<place_market_order::OrderBuyOrSell> for BuyOrSell {
    fn from(response: place_market_order::OrderBuyOrSell) -> Self {
        match response {
            place_market_order::OrderBuyOrSell::BUY => Self::Buy,
            place_market_order::OrderBuyOrSell::SELL => Self::Sell,
            _ => panic!("Unexpected value in BuyOrSell enum"),
        }
    }
}