#pragma once
// Step 600: Security Exception Review Board

#include <map>
#include <string>
#include <vector>

#include "ValidationErrorUtil.h"

enum class ExceptionDecision {
    Pending,
    Approved,
    Rejected
};

struct SecurityExceptionCase {
    std::string caseId;
    std::string operation;
    std::string requester;
    std::string justification;
    ExceptionDecision decision = ExceptionDecision::Pending;
    std::string reviewer;
};

class SecurityExceptionReviewBoard {
public:
    bool submit(const std::string& caseId,
                const std::string& operation,
                const std::string& requester,
                const std::string& justification,
                std::string* error) {
        if (!error) return false;
        error->clear();
        if (caseId.empty()) return failWith(error, "case_id_missing");
        if (operation.empty()) return failWith(error, "operation_missing");
        if (requester.empty()) return failWith(error, "requester_missing");
        if (justification.empty()) return failWith(error, "justification_missing");
        if (cases_.count(caseId) != 0) return failWith(error, "case_duplicate");
        cases_[caseId] = {caseId, operation, requester, justification, ExceptionDecision::Pending, ""};
        order_.push_back(caseId);
        return true;
    }

    bool decide(const std::string& caseId,
                ExceptionDecision decision,
                const std::string& reviewer,
                std::string* error) {
        if (!error) return false;
        error->clear();
        auto it = cases_.find(caseId);
        if (it == cases_.end()) return failWith(error, "case_missing");
        if (reviewer.empty()) return failWith(error, "reviewer_missing");
        if (decision == ExceptionDecision::Pending) return failWith(error, "decision_invalid");
        it->second.decision = decision;
        it->second.reviewer = reviewer;
        return true;
    }

    std::vector<SecurityExceptionCase> pending() const {
        std::vector<SecurityExceptionCase> out;
        for (const auto& id : order_) {
            const auto& c = cases_.at(id);
            if (c.decision == ExceptionDecision::Pending) out.push_back(c);
        }
        return out;
    }

    int approvedCount() const {
        int n = 0;
        for (const auto& id : order_) if (cases_.at(id).decision == ExceptionDecision::Approved) ++n;
        return n;
    }

    int rejectedCount() const {
        int n = 0;
        for (const auto& id : order_) if (cases_.at(id).decision == ExceptionDecision::Rejected) ++n;
        return n;
    }

private:
    std::map<std::string, SecurityExceptionCase> cases_;
    std::vector<std::string> order_;
};
