// DB
// ------------------------
// * this program will use sqlite and make use of two tables:
// [issues]
// item:
// id<int>, descr<str>, tag<str>, priority<int>, status<open|closed|progress>, date_created<date>
// [todo]
// item:
// id, text<str>, tag<str>, status <current|done>, date_created<date>

// UX
// ------------------------
// * the end-user will interface with the program through a cli
// * a typical database will exist in a ".nogran_db" directory

use std::{
    io::{self},
    path::PathBuf,
};

use crate::{
    // db::{Db, Issue, IssueStatus, Todo, TodoStatus},
    db::Db,
    utils::args::Arguments,
};
use rusqlite::Connection;

mod app;
mod db;
mod utils;

/// parent folder name
const DB_FOLDER: &str = ".ngn";
/// main db file name
const DB_NAME: &str = "ngn.db";

// *brakoll - d: logo readme and license, p: 0, t: docs, s: closed
fn main() -> io::Result<()> {
    // ====================================
    // arguments and misc subcommands
    // ====================================

    let args = utils::args::parse()?;

    if args.help {
        utils::help::print();
        return Ok(());
    }

    // ====================================
    // setup database and main program
    // ====================================

    let db_par_dir = args.target_dir.join(DB_FOLDER);
    // if parent db dir doesn't exist:
    // ask the user if they want to create one and quit if not
    if !utils::cli_confirm::confirm(&db_par_dir, &args)? {
        return Ok(());
    };

    let mut n = Ngn::new(args, db_par_dir).unwrap();

    // create db tables if they don't exist
    n.db.init_tables().unwrap();

    // ====================================
    // start gui event loop
    // ====================================

    app::app(n)?;

    Ok(())
}

#[allow(dead_code)]
struct Ngn {
    args: Arguments,
    db: Db,
}

impl Ngn {
    fn new(args: Arguments, db_par_dir: PathBuf) -> rusqlite::Result<Self> {
        let db_file = db_par_dir.join(DB_NAME);
        let conn = Connection::open(db_file)?;

        Ok(Self {
            args,
            db: db::Db {
                conn,
                issues: Vec::new(),
                todos: Vec::new(),
            },
        })
    }
}

// // *brakoll - d: implement the inital database structure and methods, p: 0, t: feature, s: closed
// // test issues
// let mut i = Issue {
//     id: None,
//     descr: String::from("add a new decoding function"),
//     tag: String::from("feat"),
//     file_name: String::from("lib.rs"),
//     status: IssueStatus::InProgress,
//     priority: 5,
//     date: get_current_date(),
// };
// i.insert(&n.db.conn).unwrap();
//
// let mut i2 = Issue {
//     id: None,
//     descr: String::from("fix y bug in another function"),
//     tag: String::from("fix"),
//     file_name: String::from("main.rs"),
//     status: IssueStatus::Closed,
//     priority: 2,
//     date: get_current_date(),
// };
// i2.insert(&n.db.conn).unwrap();
//
// // test todo
// let mut t = Todo {
//     id: None,
//     descr: String::from("do the laundry"),
//     status: TodoStatus::NotDone,
//     date: get_current_date(),
// };
//
// t.insert(&n.db.conn).unwrap();
//
// i.copy_to_cb();
//
// // n.db.todo_delete(t.id.unwrap()).unwrap();
// n.db.issue_delete(i.id.unwrap()).unwrap();
//
// n.db.debug_print_all().unwrap();
//
