use super::dynamic_state::{vato007::ingey::types::HostCsvWriter, DynamicState};
use crate::io::RecordSerializer;
use csv::Writer;
use std::collections::BTreeMap;
use std::fs;
use std::fs::File;

pub struct CsvWriterData {
    writer: Writer<File>,
    wrote_header: bool,
    path: String,
}

impl CsvWriterData {
    pub fn new(path: String) -> anyhow::Result<Self> {
        let writer = Writer::from_path(path.clone())?;
        Ok(CsvWriterData {
            writer,
            wrote_header: false,
            path,
        })
    }
}

impl HostCsvWriter for DynamicState {
    fn write_row(
        &mut self,
        self_: wasmtime::component::Resource<CsvWriterData>,
        row: Vec<(String, String)>,
    ) -> () {
        let resource = self
            .resources
            .get_mut(&self_)
            .expect("Failed to find resource");
        let write_data: BTreeMap<String, String> = row.into_iter().collect();
        if !resource.wrote_header {
            resource
                .writer
                .write_header(&write_data)
                .expect("Failed to write header");
            resource.wrote_header = true;
        }
        resource
            .writer
            .write_record(write_data.values())
            .expect("Failed to write row");
    }

    fn drop(&mut self, rep: wasmtime::component::Resource<CsvWriterData>) -> wasmtime::Result<()> {
        self.resources.delete(rep)?;
        Ok(())
    }
    fn write_string(
        &mut self,
        self_: wasmtime::component::Resource<CsvWriterData>,
        contents: String,
    ) {
        let resource = self
            .resources
            .get_mut(&self_)
            .expect("Failed to find resource");
        fs::write(&resource.path, contents);
    }
}
