use actix_web::{get, HttpRequest, Responder};
use maud::html;

use crate::pages::components::loading_spinner;

use super::components::{build_site, build_site_fn, video_element};

#[get("/search")]
pub async fn search(r: HttpRequest) -> impl Responder {
    let library: &actix_web::web::Data<crate::library::Library> = r.app_data().unwrap();
    const NUM_OF_RESULTS: usize = 20;

    if let Some(query) = web_base::parse_query_string(r.query_string()).get("query") {
        // get start parameter for search result chunks
        let start = web_base::parse_query_string(r.query_string())
            .get("offset")
            .map(|x| x.parse::<usize>().ok());
        let start = if let Some(Some(start)) = start {
            start
        } else {
            0
        };
        let mut video_matches = library.search_video(query, start, NUM_OF_RESULTS);

        // return raw html if request is from htmx
        if web_base::is_htmx_request(&r) && start != 0 {
            let content = if video_matches.is_empty() {
                // return end of search results
                String::new()
            } else {
                html!(
                @for vid_match in &mut video_matches {
                    (video_element(vid_match));
                };
                // request more results
                div hx-get=(format!("/search?query={query}&offset={}", start+NUM_OF_RESULTS)) hx-trigger="intersect" hx-swap="outerHTML" {
                    ( loading_spinner() )
                };
            )
            .into_string()
            };
            return actix_web::HttpResponse::Ok().message_body(content).unwrap();
        }

        // search page
        let content = html!(
            p { "You searched for " code { (query) }; };
            hr;
            @for vid_match in &mut video_matches {
                (video_element(vid_match));
            };
            div hx-get=(format!("/search?query={query}&offset={}", start+NUM_OF_RESULTS)) hx-trigger="load" hx-swap="outerHTML" {
                ( loading_spinner() )
            };
        )
        .into_string();
        build_site_fn(&r, "Search", &content, Some(query.to_owned()))
    } else {
        web_base::redirect("/")
    }
}

#[get("/d/{dir}")]
pub async fn channel_page(r: HttpRequest, p: actix_web::web::Path<String>) -> impl Responder {
    let library: &actix_web::web::Data<crate::library::Library> = r.app_data().unwrap();
    let dir_name = p.into_inner();

    let mut dir_videos = library.get_directory_videos(&dir_name);

    let video_grids: Vec<_> = dir_videos
        .chunks_mut(3)
        .map(|x| {
            html!(
                div class="grid" {
                @for video in x {
                    (video_element(video));
                };
            };
            )
        })
        .collect();

    let content = html!(
        h1 { (format!("{dir_name} ({})", dir_videos.len())) };
        @for grid in video_grids {
            ( grid )
        };
    )
    .into_string();
    build_site(&r, &dir_name, &content)
}

#[get("/")]
pub(crate) async fn index(r: HttpRequest) -> impl Responder {
    let library: &actix_web::web::Data<crate::library::Library> = r.app_data().unwrap();
    let dirs = library.get_directories();

    println!("{:?}", r.headers());

    let content = html!(
        h1 style="margin-bottom: -35px;" { "Random Videos" };
        div class="grid" style="margin-left: -80px;" {
        @for mut vid in library.get_random_videos(3) {
            ( video_element(&mut vid) );
        };
        };
        h1 { "Directories:" };
        @for dir in dirs {
            a href=(format!("/d/{dir}")) { (dir) };
            br;
        };
    )
    .into_string();
    build_site(&r, "WatchDogs", &content)
}
