// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2026 ndaal Gesellschaft für Sicherheit in der Informationstechnik mbH & Co KG, Cologne
// SPDX-FileCopyrightText: Author: Pierre Gronau <Pierre.Gronau@ndaal.eu>

//! Import-by-path page: read SARIF from a file or directory on disk, validate,
//! and admit the valid documents to the store.

use std::fmt::Write as _;
use std::path::Path;

use http::{Response, StatusCode};

use crate::app_state::AppState;
use crate::html::{self, alert, escape, Nav};
use crate::import;
use crate::router::{html_response, Body};

use super::{first, query_pairs};

/// The import form card.
fn form() -> String {
    "<h1 class=\"h3 mb-4\">Import SARIF</h1>\
     <div class=\"card shadow-sm mb-4\"><div class=\"card-body\">\
     <p class=\"text-body-secondary\">Enter an absolute path to a <span class=\"mono\">.sarif</span>/<span class=\"mono\">.json</span> \
     file, or a directory containing them. Each document is validated against its SARIF schema \
     (2.1.0 or 2.2) and only admitted if it passes.</p>\
     <form class=\"row g-2\" method=\"get\" action=\"/import/run\">\
     <div class=\"col\"><input type=\"text\" name=\"path\" class=\"form-control\" \
     placeholder=\"/absolute/path/to/report.sarif or a directory\" required></div>\
     <div class=\"col-auto\"><button class=\"btn btn-primary\" type=\"submit\">\
     <i class=\"bi bi-box-arrow-in-down me-1\"></i>Import &amp; validate</button></div>\
     </form></div></div>"
        .to_owned()
}

/// `GET /import` — the import form.
pub fn page(
    _state: AppState,
    _parts: http::request::Parts,
    _params: Vec<(String, String)>,
) -> Response<Body> {
    html_response(StatusCode::OK, html::page("Import", Nav::Import, &form()))
}

/// `GET /import/run?path=…` — perform the import and report the outcome.
pub fn run(
    state: AppState,
    parts: http::request::Parts,
    _params: Vec<(String, String)>,
) -> Response<Body> {
    let pairs = query_pairs(&parts.uri);
    let path = first(&pairs, "path").unwrap_or("").trim().to_owned();
    if path.is_empty() {
        let body = format!("{}{}", form(), alert("warning", "Please provide a path."));
        return html_response(StatusCode::OK, html::page("Import", Nav::Import, &body));
    }

    let outcome = import::import_path(Path::new(&path), state.store());

    let kind = if outcome.err_count() == 0 {
        "success"
    } else if outcome.ok_count() == 0 {
        "danger"
    } else {
        "warning"
    };
    let mut body = format!(
        "<h1 class=\"h3 mb-4\">Import result</h1>{}",
        alert(
            kind,
            &format!(
                "Imported <strong>{ok}</strong> file(s), <strong>{err}</strong> rejected from <span class=\"mono\">{path}</span>.",
                ok = outcome.ok_count(),
                err = outcome.err_count(),
                path = escape(&path),
            )
        )
    );

    if !outcome.imported.is_empty() {
        let mut items = String::new();
        for id in &outcome.imported {
            let _ = write!(
                items,
                "<li class=\"list-group-item\"><a href=\"/logs/{id}\" class=\"text-decoration-none\">{id}</a></li>",
                id = escape(id)
            );
        }
        let _ = write!(
            body,
            "<div class=\"card shadow-sm mb-4\"><div class=\"card-body\">\
             <h2 class=\"h5 card-title text-success\"><i class=\"bi bi-check-circle me-2\"></i>Admitted</h2>\
             <ul class=\"list-group list-group-flush\">{items}</ul></div></div>"
        );
    }

    if !outcome.errors.is_empty() {
        let mut items = String::new();
        for (source, error) in &outcome.errors {
            let _ = write!(
                items,
                "<li class=\"list-group-item\"><strong>{}</strong><pre class=\"json-block mt-2 mb-0\">{}</pre></li>",
                escape(source),
                escape(error)
            );
        }
        let _ = write!(
            body,
            "<div class=\"card shadow-sm mb-4\"><div class=\"card-body\">\
             <h2 class=\"h5 card-title text-danger\"><i class=\"bi bi-x-octagon me-2\"></i>Rejected</h2>\
             <ul class=\"list-group list-group-flush\">{items}</ul></div></div>"
        );
    }

    let _ = write!(
        body,
        "<a class=\"btn btn-outline-secondary\" href=\"/\"><i class=\"bi bi-arrow-left me-1\"></i>Dashboard</a>"
    );
    html_response(StatusCode::OK, html::page("Import result", Nav::Import, &body))
}
