#![warn(unused_extern_crates)]
#![allow(clippy::style)]

use std::{path::PathBuf, str::FromStr};

use http::uri::Authority;
use lipgloss::Border;
use mq_markdown::{ColorTheme, ListStyle, RenderOptions, UrlSurroundStyle};
use mq_view::{RenderConfig, render_markdown_with_config};
use warp::{Filter, filters::path::FullPath};
#[path = "lib/html.rs"]
mod html;
#[path = "lib/markdowner.rs"]
mod markdowner;
#[path = "lib/sidebar.rs"]
mod sidebar;
use crate::{
    html::html_response,
    markdowner::{FrontMatter, MarkdownModule},
};
use sidebar::sidebar_content;

fn router(request_path: PathBuf) -> PathBuf {
    std::env::current_dir()
        .expect("unable to determine current directory")
        .join("serve")
        .join(request_path)
}

fn renderer(path: FullPath, user_agent: String) -> Box<dyn warp::Reply> {
    //let time = chrono::Local::now().to_rfc2822();
    println!("{:?} requested by {}", path, user_agent);
    let request_path: PathBuf = path.as_str().strip_prefix("/").unwrap_or_default().into();
    let target_path = router(request_path);
    if !target_path.exists() || target_path.is_file() {
        return Box::new(warp::redirect(
            warp::http::uri::Builder::new()
                .authority(".")
                .build()
                .unwrap(),
        ));
    }

    println!("serving path: {:?}", target_path);

    let page_contents = markdowner::get_markdown_modules(&target_path);
    let sidebar_dir = PathBuf::from("assets/sidebar/");
    let sidebar_contents = markdowner::get_markdown_modules(&router(sidebar_dir));

    let response = if user_agent.starts_with("curl/") {
        todo!("reimplement curl return")
    } else {
        html_response(
            page_contents,
            sidebar_contents,
            target_path
                .file_stem()
                .unwrap_or_default()
                .to_str()
                .unwrap_or_default()
                .to_owned(),
        )
    };
    response

    /*
    if user_agent.starts_with("curl/") {
        println!("displaying curl formatting");
        let page_markdowns: Vec<String> = page_contents
            .iter()
            .map(|x| {
                let source = std::fs::read_to_string(x).unwrap();
                let mut mq: mq_markdown::Markdown = source.parse().unwrap();
                let render_opts = RenderOptions {
                    list_style: ListStyle::Dash,
                    link_url_style: UrlSurroundStyle::None,
                    link_title_style: mq_markdown::TitleSurroundStyle::Single,
                };
                mq.set_options(render_opts);
                let theme = ColorTheme::parse_colors("heading=34:code=31");
                mq.to_colored_string_with_theme(&theme);
                let render_conf = RenderConfig {
                    header_full_width_highlight: false,
                };

                let _styled_mq = mq_view::render_markdown_to_string(&mq).unwrap();

                let mut writer: Vec<u8> = Vec::new();

                render_markdown_with_config(&mq, &mut writer, &render_conf).unwrap();

                let render_string = String::from_utf8(writer).unwrap();

                println!("{}", render_string);

                let _md = mdriver::StreamingParser::new().feed(
                    termimad::text(std::fs::read_to_string(x).unwrap_or_default().as_str())
                        .to_string()
                        .as_str(),
                );
                let border_style = lipgloss::Style::new()
                    .border(Border::new(
                        "─", "─", "│", "│", "╭", "╮", "╰", "╯", "", "", "", "", "",
                    ))
                    .width(80)
                    .padding(0, 2, 0, 2)
                    .align_horizontal(lipgloss::position::LEFT);
                border_style.render(render_string.as_str())
            })
            .collect();

        for c in &page_markdowns {
            println!("{}\n", c);
        }
        let page_md_collected = format!("{}\n", page_markdowns.join("\n"));

        Box::new(warp::reply::with_status(
            page_md_collected,
            warp::http::StatusCode::OK,
        ))
    }*/
}

#[tokio::main]
async fn main() {
    println!("Hello, world!");
    let assets = warp::path("assets").and(warp::fs::dir("./serve/assets/"));
    let favicon = warp::path("favicon.ico").and(warp::fs::file("./serve/favicon.ico"));

    //    let no_meta = warp::

    let markdowns = warp::any() //path::end()
        .and(warp::path::full())
        .and(warp::header("user-agent"))
        .map(|path: FullPath, agent: String| renderer(path, agent));

    let routes = favicon.or(assets).or(markdowns);

    warp::serve(routes).run(([127, 0, 0, 1], 3030)).await;
}
