use actix_web::{Error, HttpRequest};
use base64::{Engine, engine::general_purpose::STANDARD};
use db::database::AppDatabase;
use model::{
    repos::RepoModel,
    workspace::{
        wk_history_name::WkHistoryNameModel, workspace::WorkspaceModel,
    },
};

pub async fn get_repo_model(
    namespace: &str,
    repo_name: &str,
    db: &AppDatabase,
) -> Result<RepoModel, Error> {
    let wk_id = if let Some(wk) = sqlx::query_as::<_, WorkspaceModel>(
        "SELECT id, name, description, avatar_url, created_at FROM workspace WHERE name = $1",
    )
    .bind(namespace)
    .fetch_optional(db.reader())
    .await
    .map_err(|_| actix_web::error::ErrorInternalServerError("Database error"))?
    {
        wk.id
    } else if let Some(history) = sqlx::query_as::<_, WkHistoryNameModel>(
        "SELECT id, wk, name, changed_by, created_at FROM wk_history_name WHERE name = $1",
    )
    .bind(namespace)
    .fetch_optional(db.reader())
    .await
    .map_err(|_| actix_web::error::ErrorInternalServerError("Database error"))?
    {
        history.wk
    } else {
        return Err(actix_web::error::ErrorNotFound("Project not found").into());
    };

    let repo = sqlx::query_as::<_, RepoModel>(
        "SELECT id, wk, name, description, default_branch, visibility, size_bytes, \
                is_archived, is_template, is_mirror, created_by, storage_path, \
                created_at, updated_at, deleted_at \
         FROM repo \
         WHERE name = $1 AND wk = $2 AND deleted_at IS NULL",
    )
    .bind(repo_name)
    .bind(wk_id)
    .fetch_optional(db.reader())
    .await
    .map_err(|_| actix_web::error::ErrorInternalServerError("Database error"))?
    .ok_or_else(|| actix_web::error::ErrorNotFound("Repository not found"))?;

    Ok(repo)
}

pub fn extract_basic_credentials(
    req: &HttpRequest,
) -> Result<(String, String), Error> {
    let auth_header = req
        .headers()
        .get("authorization")
        .ok_or_else(|| {
            actix_web::error::ErrorUnauthorized("Missing authorization header")
        })?
        .to_str()
        .map_err(|_| {
            actix_web::error::ErrorUnauthorized("Invalid authorization header")
        })?;

    let encoded = auth_header.strip_prefix("Basic ").ok_or_else(|| {
        actix_web::error::ErrorUnauthorized("Invalid authorization scheme")
    })?;

    let decoded = STANDARD.decode(encoded).map_err(|_| {
        actix_web::error::ErrorUnauthorized(
            "Invalid basic authorization encoding",
        )
    })?;

    let decoded = String::from_utf8(decoded).map_err(|_| {
        actix_web::error::ErrorUnauthorized(
            "Invalid basic authorization payload",
        )
    })?;

    let (username, access_key) = decoded.split_once(':').ok_or_else(|| {
        actix_web::error::ErrorUnauthorized(
            "Invalid basic authorization format",
        )
    })?;

    if username.is_empty() || access_key.is_empty() {
        return Err(actix_web::error::ErrorUnauthorized(
            "Username or access key is empty",
        ));
    }

    Ok((username.to_string(), access_key.to_string()))
}
