use crate::{
    lyrics_api::{Response, response::ResponseError},
    metadata::TrackMetadata,
};
use regex::Regex;
use reqwest::blocking::Client;
use serde::Deserialize;

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct LrcLibResponse {
    plain_lyrics: Option<String>,
    synced_lyrics: Option<String>,
    instrumental: bool,
}

impl LrcLibResponse {
    pub fn plain_lyrics(&self) -> Option<&str> {
        self.plain_lyrics.as_deref()
    }

    pub fn synced_lyrics(&self) -> Option<&str> {
        self.synced_lyrics.as_deref()
    }

    pub fn instrumental(&self) -> bool {
        self.instrumental
    }
}

pub fn strip_timestamp(synced_lyrics: &str) -> String {
    let re = Regex::new(r"^\[.*?\]\s*").unwrap();
    synced_lyrics
        .lines()
        .map(|line| re.replace(line, "").to_string())
        .collect::<Vec<_>>()
        .join("\n")
}

pub fn fetch_lrclib(metadata: &TrackMetadata, plain_only: bool) -> Result<Response, ResponseError> {
    let mut params = vec![("track_name", metadata.title())];
    params.push(("duration", metadata.duration()));
    if let Some(artist) = metadata.artist() {
        params.push(("artist_name", artist));
    }
    if let Some(album) = metadata.album() {
        params.push(("album_name", album));
    }
    let version = env!("CARGO_PKG_VERSION");
    let client = Client::builder()
        .user_agent(format!(
            "lscribe v{} https://codeberg.org/M23Snezhok/lscribe.git",
            version
        ))
        .build()
        .map_err(|e| ResponseError::new(format!("Failed to build HTTP client: {e}")))?;

    let response = client
        .get("https://lrclib.net/api/get")
        .query(&params)
        .send()
        .map_err(|e| ResponseError::new(format!("Request error: {e}")))?;

    match response.status().as_u16() {
        200 => {
            let mut raw: LrcLibResponse = response
                .json()
                .map_err(|e| ResponseError::new(format!("Failed to parse JSON: {e}")))?;
            if plain_only {
                raw.synced_lyrics = None;
            }
            Ok(Response::from_raw_lrclib_response(raw))
        }
        404 => Ok(Response::None),
        code => Err(ResponseError::new(format!(
            "Unexpected status code: {code}"
        ))),
    }
}
