use std::{
    cell::RefCell,
    fs::File,
    io::Write,
    path::{Path, PathBuf},
};

use crate::prelude::*;

pub(super) struct StoryGenerator {
    messages_file: RefCell<File>,
}

impl report_generators::StoryReportGenerator for StoryGenerator {
    fn report_message(&self, message: &Message) {
        write!(
            &mut self.messages_file.borrow_mut(),
            "{}:{}:{}:{}\n",
            message.severity,
            message.filename,
            message.line,
            message.content
        )
        .unwrap();
    }
}

impl StoryGenerator {
    fn new(name: &str, directory: &Path) -> StoryGenerator {
        let directory = directory.join(name);
        std::fs::create_dir_all(&directory).unwrap();
        let messages_file = RefCell::new(File::create(directory.join("messages.md")).unwrap());
        StoryGenerator { messages_file }
    }
}

pub(super) struct Generator {
    directory: PathBuf,
    summary_file: RefCell<File>,
}

impl report_generators::Generator for Generator {
    type StoryReportGenerator = StoryGenerator;
    fn report_failure(
        &self,
        story: &story::Story,
        duration: std::time::Duration,
        reason: String,
    ) -> StoryGenerator {
        writeln!(
            &mut self.summary_file.borrow_mut(),
            "* {}: failed in {}s: {}\n  [messages]({}/messages.md)",
            story.name,
            duration.as_secs(),
            reason,
            story.name
        )
        .unwrap();
        StoryGenerator::new(&story.name, &self.directory)
    }
    fn report_success(
        &self,
        story: &story::Story,
        duration: std::time::Duration,
    ) -> StoryGenerator {
        writeln!(
            &mut self.summary_file.borrow_mut(),
            "* {}: success in {}s\n  [messages]({}/messages.md)",
            story.name,
            duration.as_secs(),
            story.name
        )
        .unwrap();
        StoryGenerator::new(&story.name, &self.directory)
    }
}

impl Generator {
    pub(super) fn new(name: &String, config: &story::MarkdownConfiguration) -> Generator {
        let directory: PathBuf = Path::new(&config.directory).into();
        std::fs::create_dir_all(&directory).unwrap();
        let summary_file = RefCell::new(File::create(directory.join("summary.md")).unwrap());
        writeln!(
            &mut summary_file.borrow_mut(),
            "{}\n{:=<width$}\n",
            name,
            "",
            width = name.len()
        )
        .unwrap();
        Generator {
            directory,
            summary_file,
        }
    }
}
