#[warn(unused_imports)]
use clap::{Parser, Subcommand};
mod markdown;
use markdown::{get_all_posts, get_post_by_slug, get_posts_by_tag, watch_posts, get_parser_logs, clear_parser_logs, load_parser_logs_from_disk};
use serde_json;
use std::fs;
use std::io;
use std::io::Read; // STD AYOOOOOOOOOOOOOO - Tsodin


//
//  This is the Parsers "Command Centeral"
//  Commands for the CLI are Defined Here
//  The Parser will provide appropriate Errors, if you care then modify.
//  Hours wasted: 2.42h (Due to shitty error logging)

#[derive(Parser)]
#[command(name = "Markdown Backend")]
#[command(about = "A CLI for managing markdown blog posts", long_about = None)]
struct Cli {
    #[command(subcommand)]
    command: Commands,
}

#[derive(Subcommand)]
enum Commands {
    /// List all posts
    List,
    /// Show a post by slug
    Show {
        slug: String,
    },
    /// List posts by tag
    Tags {
        tag: String,
    },
    /// Watch for changes in the posts directory
    Watch,
    /// Show Rust parser statistics
    Rsparseinfo,
    /// Check backend health
    Checkhealth,
    /// Get parser logs
    Logs,
    /// Clear parser logs
    ClearLogs,
    /// Parse markdown from file or stdin
    Parse {
        #[arg(long)]
        file: Option<String>,
        #[arg(long)]
        stdin: bool,
        #[arg(long)]
        ast: bool,
    },
}

fn main() {
    markdown::load_post_cache_from_disk();
    load_parser_logs_from_disk();
    let cli = Cli::parse();
    match &cli.command {
        Commands::List => {
            let posts = get_all_posts().unwrap_or_else(|e| {
                eprintln!("{}", e);
                std::process::exit(1);
            });
            println!("{}", serde_json::to_string(&posts).unwrap());
        }
        Commands::Show { slug } => {
            match get_post_by_slug(slug) {
                Ok(post) => {
                    println!("{}", serde_json::to_string(&post).unwrap());
                    markdown::save_post_cache_to_disk();
                }
                Err(e) => {
                    eprintln!("{}", e);
                    std::process::exit(1);
                }
            }
        }
        Commands::Tags { tag } => {
            let posts = get_posts_by_tag(tag).unwrap_or_else(|e| {
                eprintln!("{}", e);
                std::process::exit(1);
            });
            println!("{}", serde_json::to_string(&posts).unwrap());
        }
        Commands::Watch => {
            println!("Watching for changes in posts directory. Press Ctrl+C to exit.");
            let _ = watch_posts(|| {
                println!("Posts directory changed!");
            });
            // Keep the main thread alive
            loop {
                std::thread::sleep(std::time::Duration::from_secs(60));
            }
        }
        Commands::Rsparseinfo => {
            println!("{}", markdown::rsparseinfo());
        }
        Commands::Checkhealth => {
            let health = markdown::checkhealth();
            println!("{}", serde_json::to_string_pretty(&health).unwrap());
        }
        Commands::Logs => {
            let logs = get_parser_logs();
            println!("{}", serde_json::to_string_pretty(&logs).unwrap());
        }
        Commands::ClearLogs => {
            clear_parser_logs();
            println!("{}", serde_json::to_string(&serde_json::json!({"success": true, "message": "Logs cleared"})).unwrap());
        }
        Commands::Parse { file, stdin, ast } => {
            let content = if *stdin {
                let mut buffer = String::new();
                io::stdin().read_to_string(&mut buffer).unwrap();
                buffer
            } else if let Some(file_path) = file {
                fs::read_to_string(file_path).unwrap()
            } else {
                eprintln!("Either --file or --stdin must be specified");
                std::process::exit(1);
            };

            if *ast {
                // Parse and output AST as debug format
                let parser = pulldown_cmark::Parser::new_ext(&content, pulldown_cmark::Options::all());
                let events: Vec<_> = parser.collect();
                for event in events {
                    println!("{:?}", event);
                }
            } else {
                // Parse and output HTML
                let parser = pulldown_cmark::Parser::new_ext(&content, pulldown_cmark::Options::all());
                let mut html_output = String::new();
                pulldown_cmark::html::push_html(&mut html_output, parser);
                println!("{}", html_output);
            }
        }
    }
} 