use crate::linter::Linter;
use crate::ruff_code::RuffCode;
use serde::Deserialize;
use std::collections::HashSet;
use std::process::Command;
use std::str::FromStr;

#[derive(Debug, Deserialize)]
struct RuffSparseJson {
    code: String,
}

pub fn read_codes() -> (HashSet<Linter>, usize) {
    let output = Command::new("ruff")
        .arg("check")
        .arg("--select")
        .arg("ALL")
        .arg("--exclude")
        .arg("COM812")
        .arg("--exclude")
        .arg("D203")
        .arg("--exclude")
        .arg("D212")
        .arg("--output-format")
        .arg("json")
        .output()
        .expect("failed to execute process");
    let out = String::from_utf8_lossy(&output.stdout);

    let items: Vec<RuffSparseJson> = serde_json::from_str::<Vec<RuffSparseJson>>(&out)
        .expect("Could not read json from ruff.")
        .into_iter()
        .filter(|item| item.code != "invalid-syntax")
        .collect();

    let ignored_amount: usize = items.len();

    let mut unique_groups = HashSet::new();

    for item in items {
        let error_message = format!("Could not parse ruff code: '{}'", &item.code);
        let code = RuffCode::from_str(&item.code).expect(&error_message);
        unique_groups.insert(code.linter);
    }

    (unique_groups, ignored_amount)
}
