use std::collections::HashMap;

#[derive(Debug, Clone, Default)]
pub struct Ids {
    pub doi: Option<String>,
    pub arxiv: Option<String>,
    pub isbn: Option<String>,
}

impl Ids {
    pub fn as_map(&self) -> HashMap<&'static str, &str> {
        let mut map = HashMap::new();
        if let Some(ref doi) = self.doi {
            map.insert("doi", doi.as_str());
        }
        if let Some(ref arxiv) = self.arxiv {
            map.insert("arxiv", arxiv.as_str());
        }
        if let Some(ref isbn) = self.isbn {
            map.insert("isbn", isbn.as_str());
        }
        map
    }
}

#[derive(Debug, Clone, Default)]
pub struct ReferenceFields {
    pub title: Option<String>,
    pub authors: Vec<String>,
    pub year: Option<i32>,
    pub venue: Option<String>,
    pub ids: Ids,
}

#[derive(Debug, Clone, Default)]
pub struct Candidate {
    pub provider: Option<String>,
    pub provider_id: Option<String>,
    pub title: Option<String>,
    pub authors: Vec<String>,
    pub year: Option<i32>,
    pub venue: Option<String>,
    pub ids: Ids,
    pub url: Option<String>,
}

#[derive(Debug, Clone, Default)]
pub struct ScoreBreakdown {
    pub title: f64,
    pub authors: f64,
    pub year: f64,
    pub venue: f64,
}

#[derive(Debug, Clone, Default)]
pub struct ScoreConfig {
    pub title_weight: f64,
    pub author_weight: f64,
    pub year_weight: f64,
    pub venue_weight: f64,
}

impl ScoreConfig {
    pub fn new() -> Self {
        Self {
            title_weight: 0.5,
            author_weight: 0.2,
            year_weight: 0.2,
            venue_weight: 0.1,
        }
    }
}

#[derive(Debug, Clone)]
pub struct ScoreResult {
    pub score: f64,
    pub breakdown: ScoreBreakdown,
}

#[derive(Debug, Clone)]
pub struct MatchConfig {
    pub verified_threshold: f64,
    pub likely_threshold: f64,
    pub overwrite_threshold: f64,
    pub score_config: ScoreConfig,
}

impl MatchConfig {
    pub fn new() -> Self {
        Self {
            verified_threshold: 0.85,
            likely_threshold: 0.7,
            overwrite_threshold: 0.9,
            score_config: ScoreConfig::new(),
        }
    }
}

#[derive(Debug, Clone)]
pub struct EntryResult {
    pub verdict: String,
    pub score: f64,
    pub reasons: Vec<String>,
    pub best_candidate: Option<Candidate>,
    pub breakdown: Option<ScoreBreakdown>,
}
