/*
    This file is part of jellything (https://codeberg.org/metamuffin/jellything)
    which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
    Copyright (C) 2026 metamuffin <metamuffin.org>
*/

use std::str::FromStr;

use super::error::MyResult;
use crate::{request_info::RequestInfo, ui_responder::UiResponse};
use anyhow::{Context, Result};
use jellycommon::{
    jellyobject::{Object, ObjectBuffer, ObjectBufferBuilder},
    *,
};
use jellydb::Query;
use jellyui::tr;
use rocket::get;

#[get("/home")]
pub fn r_home(ri: RequestInfo<'_>) -> MyResult<UiResponse> {
    ri.require_user()?;

    let mut page = ObjectBufferBuilder::default();

    page.push(VIEW_TITLE, &&*tr(ri.lang, "home"));

    page.push(
        VIEW_NODE_LIST,
        home_row(
            &ri,
            "home.bin.latest_video",
            "FILTER (visi = visi AND kind = vide) SORT DESCENDING BY FIRST rldt",
        )?
        .as_object(),
    );
    page.push(
        VIEW_NODE_LIST,
        home_row(
            &ri,
            "home.bin.latest_music",
            "FILTER (visi = visi AND kind = musi) SORT DESCENDING BY FIRST rldt",
        )?
        .as_object(),
    );
    page.push(
        VIEW_NODE_LIST,
        home_row_highlight(
            &ri,
            "home.bin.daily_random",
            "FILTER (visi = visi AND kind = movi) SORT RANDOM",
        )?
        .as_object(),
    );
    page.push(
        VIEW_NODE_LIST,
        home_row(
            &ri,
            "home.bin.max_rating",
            "SORT DESCENDING BY FIRST rtng.imdb",
        )?
        .as_object(),
    );
    page.push(
        VIEW_NODE_LIST,
        home_row_highlight(
            &ri,
            "home.bin.daily_random",
            "FILTER (visi = visi AND kind = show) SORT RANDOM",
        )?
        .as_object(),
    );

    Ok(ri.respond_ui(page.finish()))
}

fn home_row(ri: &RequestInfo<'_>, title: &str, query: &str) -> Result<ObjectBuffer> {
    let q = Query::from_str(query).context("parse query")?;
    let mut res = ObjectBuffer::empty();
    ri.state.database.transaction(&mut |txn| {
        let rows = txn.query(q.clone())?.take(16).collect::<Result<Vec<_>>>()?;

        let mut nkus = Vec::new();
        for (row, _) in rows {
            let node = txn.get(row)?.unwrap();
            nkus.push(ObjectBuffer::new(&mut [(NKU_NODE.0, &node.as_object())]));
        }
        let nkus = nkus.iter().map(|n| n.as_object()).collect::<Vec<_>>(); // TODO -_-

        res = Object::EMPTY.insert(NODELIST_DISPLAYSTYLE, NLSTYLE_INLINE);
        res = res.as_object().insert(NODELIST_TITLE, title);
        res = res.as_object().insert_multi(NODELIST_ITEM, &nkus);

        Ok(())
    })?;
    Ok(res)
}

fn home_row_highlight(ri: &RequestInfo<'_>, title: &str, query: &str) -> Result<ObjectBuffer> {
    let q = Query::from_str(query).context("parse query")?;
    let mut res = ObjectBuffer::empty();
    ri.state.database.transaction(&mut |txn| {
        let Some(row) = txn.query(q.clone())?.next() else {
            return Ok(());
        };
        let row = row?.0;
        let node = txn.get(row)?.unwrap();
        let nku = ObjectBuffer::new(&mut [(NKU_NODE.0, &node.as_object())]);
        res = Object::EMPTY.insert(NODELIST_DISPLAYSTYLE, NLSTYLE_HIGHLIGHT);
        res = res.as_object().insert(NODELIST_TITLE, title);
        res = res.as_object().insert(NODELIST_ITEM, nku.as_object());
        Ok(())
    })?;
    Ok(res)
}
