#![allow(non_camel_case_types, non_snake_case, dead_code, unused_imports)]

// All Rights Reserved — The Cochran Block, LLC
// Contributors: Mattbusel (XFactor), GotEmCoach, KOVA, Claude Opus 4.6, SuperNinja, Composer 1.5, Google Gemini Pro 3

use std::time::Instant;
use tempfile::TempDir;

use super::assert_ok;
use super::t24;
use crate::auth::session;
use crate::crypto::token;
use crate::db;

async fn run(p0: &str, p1: impl std::future::Future<Output = Result<(), String>>) -> t24 {
    let v0 = Instant::now();
    match p1.await {
        Ok(()) => t24 {
            s30: p0.into(),
            s31: true,
            s32: v0.elapsed().as_millis() as u64,
            s33: None,
        },
        Err(msg) => t24 {
            s30: p0.into(),
            s31: false,
            s32: v0.elapsed().as_millis() as u64,
            s33: Some(msg),
        },
    }
}

pub async fn f50() -> Vec<t24> {
    let mut v0 = Vec::new();
    let v1 = TempDir::new().unwrap();
    let v2 = v1.path().to_str().unwrap().to_string();

    v0.push(
        run("db_init", async {
            let v3 = db::f20(&v2).map_err(|e| e.to_string())?;
            assert_ok(db::f21(&v3).is_ok(), "migrations must apply")?;
            Ok(())
        })
        .await,
    );
    v0.push(
        run("admin_crud", async {
            let v3 = db::f20(&v2).map_err(|e| e.to_string())?;
            db::f21(&v3).map_err(|e| e.to_string())?;
            db::f37(&v3, "admin1", "hash1").map_err(|e| e.to_string())?;
            let v4 = db::f36(&v3, "admin1").map_err(|e| e.to_string())?;
            assert_ok(v4.is_some(), "admin must be retrievable")?;
            assert_ok(
                db::f38(&v3).map_err(|e| e.to_string())?,
                "admin count must be > 0",
            )?;
            Ok(())
        })
        .await,
    );
    v0.push(
        run("admin_duplicate_rejection", async {
            let v3 = db::f20(&v2).map_err(|e| e.to_string())?;
            db::f21(&v3).map_err(|e| e.to_string())?;
            db::f37(&v3, "dup", "h1").map_err(|e| e.to_string())?;
            assert_ok(
                db::f37(&v3, "dup", "h2").is_err(),
                "duplicate admin must be rejected",
            )?;
            Ok(())
        })
        .await,
    );
    v0.push(
        run("session_crud", async {
            let v3 = db::f20(&v2).map_err(|e| e.to_string())?;
            db::f21(&v3).map_err(|e| e.to_string())?;
            let v4 = session::t3::f18("u");
            db::f39(&v3, &v4).map_err(|e| e.to_string())?;
            let v5 = db::f40(&v3, &v4.s37).map_err(|e| e.to_string())?;
            assert_ok(v5.is_some(), "session must be stored")?;
            db::f41(&v3, &v4.s37).map_err(|e| e.to_string())?;
            let v6 = db::f40(&v3, &v4.s37).map_err(|e| e.to_string())?;
            assert_ok(v6.is_none(), "deleted session must be gone")?;
            Ok(())
        })
        .await,
    );
    v0.push(
        run("encrypted_settings", async {
            let v3 = db::f20(&v2).map_err(|e| e.to_string())?;
            db::f21(&v3).map_err(|e| e.to_string())?;
            let v4: [u8; 32] = crate::crypto::key::f31("key", "enc").map_err(|e| e.to_string())?;
            let v5 = token::f14("secret", &v4).map_err(|e| e.to_string())?;
            db::f43(&v3, "tok", &v5).map_err(|e| e.to_string())?;
            let v6 = db::f42(&v3, "tok")
                .map_err(|e| e.to_string())?
                .ok_or("setting not found")?;
            assert_ok(
                token::f15(&v6, &v4).map_err(|e| e.to_string())? == "secret",
                "decrypt must match",
            )?;
            Ok(())
        })
        .await,
    );
    v0.push(
        run("encrypted_settings_wrong_key", async {
            let v3 = db::f20(&v2).map_err(|e| e.to_string())?;
            db::f21(&v3).map_err(|e| e.to_string())?;
            let v4: [u8; 32] = crate::crypto::key::f31("key1", "enc").map_err(|e| e.to_string())?;
            let v5: [u8; 32] = crate::crypto::key::f31("key2", "enc").map_err(|e| e.to_string())?;
            let v6 = token::f14("secret", &v4).map_err(|e| e.to_string())?;
            db::f43(&v3, "tok", &v6).map_err(|e| e.to_string())?;
            let v7 = db::f42(&v3, "tok")
                .map_err(|e| e.to_string())?
                .ok_or("setting not found")?;
            assert_ok(token::f15(&v7, &v5).is_err(), "wrong key must fail decrypt")?;
            Ok(())
        })
        .await,
    );
    v0.push(
        run("plaintext_upsert", async {
            let v3 = db::f20(&v2).map_err(|e| e.to_string())?;
            db::f21(&v3).map_err(|e| e.to_string())?;
            db::f43(&v3, "k", "v1").map_err(|e| e.to_string())?;
            db::f43(&v3, "k", "v2").map_err(|e| e.to_string())?;
            let v4 = db::f42(&v3, "k")
                .map_err(|e| e.to_string())?
                .ok_or("setting not found")?;
            assert_ok(v4 == "v2", "upsert must overwrite")?;
            Ok(())
        })
        .await,
    );
    v0.push(
        run("dns_log", async {
            let v3 = db::f20(&v2).map_err(|e| e.to_string())?;
            db::f21(&v3).map_err(|e| e.to_string())?;
            db::f44(&v3, "1.2.3.4", "ok", "msg").map_err(|e| e.to_string())?;
            let v4 = db::f45(&v3, 5).map_err(|e| e.to_string())?;
            assert_ok(
                v4.len() == 1,
                format!("expected 1 log entry got {}", v4.len()),
            )?;
            assert_ok(v4[0].1 == "1.2.3.4", "log must store IP")?;
            Ok(())
        })
        .await,
    );
    v0.push(
        run("session_cleanup", async {
            let v3 = db::f20(&v2).map_err(|e| e.to_string())?;
            db::f21(&v3).map_err(|e| e.to_string())?;
            let v4 = session::t3 {
                s37: "expired-id".into(),
                s10: "u".into(),
                s13: "2020-01-01T00:00:00Z".into(),
                s14: "2020-01-01T00:00:01Z".into(),
            };
            db::f39(&v3, &v4).map_err(|e| e.to_string())?;
            db::f33(&v3).map_err(|e| e.to_string())?;
            let v5 = db::f40(&v3, "expired-id").map_err(|e| e.to_string())?;
            assert_ok(v5.is_none(), "expired session must be cleaned up")?;
            Ok(())
        })
        .await,
    );
    v0.push(
        run("db_nested_path", async {
            let v3_path = v1.path().join("nested/sub").to_str().unwrap().to_string();
            let v3 = db::f20(&v3_path).map_err(|e| e.to_string())?;
            db::f21(&v3).map_err(|e| e.to_string())?;
            db::f43(&v3, "nested_key", "nested_val").map_err(|e| e.to_string())?;
            let v4 = db::f42(&v3, "nested_key")
                .map_err(|e| e.to_string())?
                .ok_or("not found")?;
            assert_ok(v4 == "nested_val", "nested db must persist")?;
            Ok(())
        })
        .await,
    );
    v0.push(
        run("dns_log_limit", async {
            let v3 = db::f20(&v2).map_err(|e| e.to_string())?;
            db::f21(&v3).map_err(|e| e.to_string())?;
            db::f44(&v3, "1.1.1.1", "a", "m1").map_err(|e| e.to_string())?;
            db::f44(&v3, "2.2.2.2", "b", "m2").map_err(|e| e.to_string())?;
            db::f44(&v3, "3.3.3.3", "c", "m3").map_err(|e| e.to_string())?;
            let v4 = db::f45(&v3, 2).map_err(|e| e.to_string())?;
            assert_ok(
                v4.len() == 2,
                format!("limit 2 must return 2, got {}", v4.len()),
            )?;
            Ok(())
        })
        .await,
    );
    v0.push(
        run("settings_missing_key", async {
            let v3 = db::f20(&v2).map_err(|e| e.to_string())?;
            db::f21(&v3).map_err(|e| e.to_string())?;
            let v4 = db::f42(&v3, "nonexistent_key_xyz").map_err(|e| e.to_string())?;
            assert_ok(v4.is_none(), "missing key must return None")?;
            Ok(())
        })
        .await,
    );
    v0
}
