use crate::error::AppError;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use tracing::info;

#[derive(Serialize)]
struct TushareRequest<'a> {
    api_name: &'a str,
    token: &'a str,
    params: serde_json::Value,
    fields: &'a str,
}

#[derive(Deserialize, Debug)]
pub struct TushareResponse<T> {
    pub code: i64,
    pub msg: String,
    pub data: Option<TushareData<T>>,
}

#[derive(Deserialize, Debug)]
pub struct TushareData<T> {
    pub fields: Vec<String>,
    pub items: Vec<Vec<serde_json::Value>>,
    #[serde(skip)]
    _marker: std::marker::PhantomData<T>,
}

#[derive(Clone)]
pub struct TushareClient {
    client: reqwest::Client,
    api_url: String,
    api_token: String,
}

impl TushareClient {
    pub fn new(api_url: String, api_token: String) -> Self {
        Self {
            client: reqwest::Client::builder()
                .timeout(std::time::Duration::from_secs(30))
                .build()
                .unwrap_or_else(|_| reqwest::Client::new()),
            api_url,
            api_token,
        }
    }

    pub async fn send_request<T: DeserializeOwned>(
        &self,
        api_name: &str,
        params: serde_json::Value,
        fields: &str,
    ) -> Result<Vec<T>, AppError> {
        let request_payload = TushareRequest {
            api_name,
            token: &self.api_token,
            params,
            fields,
        };

        info!("Sending Tushare request for api_name: {}", api_name);

        let res = self
            .client
            .post(&self.api_url)
            .json(&request_payload)
            .send()
            .await?;

        let text = res.text().await?;
        
        // Try to parse as TushareResponse
        let response: TushareResponse<T> = match serde_json::from_str(&text) {
            Ok(r) => r,
            Err(e) => {
                return Err(AppError::DataParsing(anyhow::anyhow!(format!(
                    "Failed to parse Tushare response: {}. Body: {}",
                    e, text
                ))));
            }
        };

        if response.code != 0 {
            return Err(AppError::DataParsing(anyhow::anyhow!(format!(
                "Tushare API error code {}: {}",
                response.code, response.msg
            ))));
        }

        let data = response.data.ok_or_else(|| {
            AppError::DataParsing(anyhow::anyhow!(
                "Tushare response missing data field"
            ))
        })?;

        let items = data
            .items
            .into_iter()
            .map(|row| {
                let json_map: serde_json::Map<String, serde_json::Value> = data
                    .fields
                    .iter()
                    .zip(row.into_iter())
                    .map(|(field, value)| (field.clone(), value))
                    .collect();
                serde_json::from_value::<T>(serde_json::Value::Object(json_map))
            })
            .collect::<Result<Vec<T>, _>>()?;

        Ok(items)
    }
}


