#pragma once
#include <cstddef>
#include <cstdint>
#include <span>
#include <vector>
#include "Render_Plan.hpp"
#include "renderive/scene/base/Abstract_Frame.hpp"

struct Node_Frame_Analysis {
    Render_Node_Id node_id{};
    std::uint64_t duration_ns{};
    std::uint64_t start_offset_ns{};
    std::uint64_t end_offset_ns{};
    std::uint64_t dependency_ready_time_ns{};
    std::uint64_t scheduler_wait_ns{};
    double work_contribution{};
    double critical_path_contribution{};
    bool on_critical_path{};
};

struct Worker_Utilization {
    std::uint32_t worker_id{};
    std::uint64_t work_duration_ns{};
    double utilization{};
};

struct Frame_Analysis {
    std::uint64_t frame_id{};
    Render_Plan_Version render_plan_version{};
    std::uint64_t total_render_duration_ns{};
    std::uint64_t critical_path_duration_ns{};
    std::uint64_t total_work_duration_ns{};
    std::uint64_t parallel_overlap_ns{};
    std::size_t peak_parallelism{};
    double average_parallelism{};
    std::vector<Render_Node_Id> critical_path;
    std::vector<Render_Node_Id> bottleneck_nodes;
    std::vector<Node_Frame_Analysis> nodes;
    std::vector<Worker_Utilization> workers;
};

struct Node_Statistics {
    Render_Node_Id node_id{};
    std::size_t execution_count{};
    double average_ns{};
    double moving_average_ns{};
    double p50_ns{};
    double p95_ns{};
    double p99_ns{};
    std::uint64_t minimum_ns{};
    std::uint64_t maximum_ns{};
    std::size_t critical_path_frequency{};
    double average_scheduler_wait_ns{};
};

struct Plan_Version_Statistics {
    Render_Plan_Version render_plan_version{};
    std::size_t frame_count{};
    double render_average_ns{};
    double render_p50_ns{};
    double render_p95_ns{};
    std::uint64_t render_maximum_ns{};
    double average_parallelism{};
    std::size_t peak_parallelism{};
    double scheduler_wait_average_ns{};
    double scheduler_wait_p95_ns{};
    std::vector<Node_Statistics> nodes;
};

[[nodiscard]] Frame_Analysis analyze_frame(const Render_Plan& plan,
                                           const Frame_Snapshot& frame);
[[nodiscard]] std::vector<Node_Statistics> analyze_node_statistics(
    std::span<const Frame_Analysis> frames);
[[nodiscard]] std::vector<Plan_Version_Statistics> analyze_plan_versions(
    std::span<const Frame_Analysis> frames);
