// Tests para la logica pura de dod_evidence_panel (issue 0117).
//
// El render real con ImGui no se testea aqui (requiere context). Cubrimos:
// - count_status: tally por status + missing_required.
// - find_evidence: lookup por item_id.
// - status_icon_id: mapeo a icon key.
// - status_color_token: mapeo a token semantico.

#define CATCH_CONFIG_MAIN
#include "catch_amalgamated.hpp"

#include "viz/dod_evidence_panel_helpers.h"

using namespace fn_viz;
using namespace fn_viz::dod_panel;

namespace {

DodItem mk_item(std::string id, std::string kind, std::string status, bool required = true) {
    DodItem it;
    it.id = std::move(id);
    it.kind = std::move(kind);
    it.status = std::move(status);
    it.required = required;
    it.expected = "expected_" + it.id;
    return it;
}

DodEvidence mk_evidence(std::string item_id, std::string kind = "screenshot") {
    DodEvidence ev;
    ev.item_id = std::move(item_id);
    ev.kind = std::move(kind);
    ev.payload_path = "/tmp/" + ev.item_id + ".png";
    return ev;
}

}  // namespace

TEST_CASE("count_status: total = items.size", "[dod_panel]") {
    DodPanelState s;
    s.items.push_back(mk_item("a", "screenshot", "pending"));
    s.items.push_back(mk_item("b", "log", "done"));
    s.items.push_back(mk_item("c", "url", "validated"));
    s.items.push_back(mk_item("d", "cmd", "failed"));

    auto c = count_status(s);
    REQUIRE(c.total == 4);
    REQUIRE(c.pending == 1);
    REQUIRE(c.done == 1);
    REQUIRE(c.validated == 1);
    REQUIRE(c.failed == 1);
}

TEST_CASE("count_status: unknown status counts as pending", "[dod_panel]") {
    DodPanelState s;
    s.items.push_back(mk_item("a", "log", "weird"));
    s.items.push_back(mk_item("b", "log", "pending"));

    auto c = count_status(s);
    REQUIRE(c.total == 2);
    REQUIRE(c.pending == 2);
}

TEST_CASE("count_status: missing_required only when required+no evidence+unresolved", "[dod_panel]") {
    DodPanelState s;
    // required + no evidence + pending -> missing
    s.items.push_back(mk_item("missing_one", "screenshot", "pending", /*required*/ true));
    // required + no evidence + done -> resolved, no missing
    s.items.push_back(mk_item("done_no_ev", "log", "done", true));
    // required + evidence + pending -> no missing
    s.items.push_back(mk_item("has_ev", "url", "pending", true));
    s.evidences.push_back(mk_evidence("has_ev", "url"));
    // optional + no evidence + pending -> no missing
    s.items.push_back(mk_item("optional", "log", "pending", /*required*/ false));

    auto c = count_status(s);
    REQUIRE(c.missing_required == 1);
}

TEST_CASE("find_evidence: returns matching evidence", "[dod_panel]") {
    DodPanelState s;
    s.items.push_back(mk_item("a", "log", "done"));
    s.evidences.push_back(mk_evidence("a", "log"));
    s.evidences.push_back(mk_evidence("b", "screenshot"));

    const DodEvidence* a = find_evidence(s, "a");
    REQUIRE(a != nullptr);
    REQUIRE(a->item_id == "a");
    REQUIRE(a->kind == "log");

    const DodEvidence* b = find_evidence(s, "b");
    REQUIRE(b != nullptr);
    REQUIRE(b->kind == "screenshot");

    REQUIRE(find_evidence(s, "missing") == nullptr);
}

TEST_CASE("find_evidence: empty state returns nullptr", "[dod_panel]") {
    DodPanelState s;
    REQUIRE(find_evidence(s, "anything") == nullptr);
}

TEST_CASE("status_icon_id: mapping per status", "[dod_panel]") {
    REQUIRE(status_icon_id("pending")   == "circle-dashed");
    REQUIRE(status_icon_id("done")      == "circle-dot");
    REQUIRE(status_icon_id("validated") == "circle-check");
    REQUIRE(status_icon_id("failed")    == "circle-x");
    REQUIRE(status_icon_id("")          == "circle-dashed");
    REQUIRE(status_icon_id("garbage")   == "circle-dashed");
}

TEST_CASE("status_color_token: mapping per status", "[dod_panel]") {
    REQUIRE(status_color_token("pending")   == 0);
    REQUIRE(status_color_token("done")      == 1);
    REQUIRE(status_color_token("validated") == 2);
    REQUIRE(status_color_token("failed")    == 3);
    REQUIRE(status_color_token("")          == 0);
    REQUIRE(status_color_token("garbage")   == 0);
}
