use anyhow::Result;
use chrono::{DateTime, Utc};
use reqwest::Client;
use serde::{Deserialize, Serialize};
use std::time::Duration;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OwncastStatus {
    pub online: bool,
    pub viewer_count: Option<u32>,
    pub stream_title: Option<String>,
    pub last_connect_time: Option<DateTime<Utc>>,
    pub last_disconnect_time: Option<DateTime<Utc>>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StreamInfo {
    pub is_live: bool,
    pub stream_url: Option<String>,
    pub viewer_count: Option<u32>,
    pub stream_title: Option<String>,
    pub last_connect_time: Option<DateTime<Utc>>,
    pub last_disconnect_time: Option<DateTime<Utc>>,
}

#[derive(Debug, Clone)]
pub struct OwncastService {
    client: Client,
    base_url: String,
    stream_url: String,
}

impl OwncastService {
    pub fn new(owncast_host: &str, stream_host: &str) -> Self {
        let client = Client::builder()
            .timeout(Duration::from_secs(10))
            .build()
            .unwrap_or_default();

        Self {
            client,
            base_url: format!("https://{}", owncast_host),
            stream_url: "https://api.rockvilletollandsda.church/api/stream/hls/stream.m3u8".to_string(),
        }
    }

    pub async fn get_status(&self) -> Result<OwncastStatus> {
        let url = format!("{}/api/status", self.base_url);
        
        let response = self
            .client
            .get(&url)
            .send()
            .await?;

        if !response.status().is_success() {
            return Err(anyhow::anyhow!(
                "Failed to get Owncast status: HTTP {}",
                response.status()
            ));
        }

        let status: OwncastStatusResponse = response.json().await?;
        
        Ok(OwncastStatus {
            online: status.online,
            viewer_count: status.viewer_count,
            stream_title: status.stream_title,
            last_connect_time: status.last_connect_time,
            last_disconnect_time: status.last_disconnect_time,
        })
    }

    pub async fn get_stream_info(&self) -> Result<StreamInfo> {
        let status = self.get_status().await?;
        
        Ok(StreamInfo {
            is_live: status.online,
            stream_url: if status.online {
                Some(self.stream_url.clone())
            } else {
                None
            },
            viewer_count: status.viewer_count,
            stream_title: status.stream_title,
            last_connect_time: status.last_connect_time,
            last_disconnect_time: status.last_disconnect_time,
        })
    }
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "snake_case")]
struct OwncastStatusResponse {
    online: bool,
    #[serde(rename = "viewer_count")]
    viewer_count: Option<u32>,
    #[serde(rename = "stream_title")]
    stream_title: Option<String>,
    #[serde(rename = "last_connect_time")]
    last_connect_time: Option<DateTime<Utc>>,
    #[serde(rename = "last_disconnect_time")]
    last_disconnect_time: Option<DateTime<Utc>>,
}