#include "crow.h"
#include "routes.h"
#include <chrono>
#include <vector>
#include <mutex>
#include <algorithm>

namespace routes {

namespace {

struct Item {
    int         id;
    std::string name;
    std::string description;
};

std::mutex       g_mutex;
std::vector<Item> g_items = {
    {1, "Widget",  "A useful widget"},
    {2, "Gadget",  "A fancy gadget"},
    {3, "Gizmo",   "A mysterious gizmo"},
};
int g_next_id = 4;

crow::json::wvalue item_to_json(const Item& item) {
    crow::json::wvalue j;
    j["id"]          = item.id;
    j["name"]        = item.name;
    j["description"] = item.description;
    return j;
}

} // anonymous namespace

void register_api(crow::SimpleApp& app) {

    // Health check
    CROW_ROUTE(app, "/api/health")
    ([]() {
        crow::json::wvalue res;
        res["status"]  = "ok";
        auto now = std::chrono::system_clock::now();
        auto epoch = std::chrono::duration_cast<std::chrono::seconds>(
                         now.time_since_epoch())
                         .count();
        res["timestamp"] = epoch;
        return res;
    });

    // List all items
    CROW_ROUTE(app, "/api/items")
    ([]() {
        std::lock_guard<std::mutex> lock(g_mutex);
        crow::json::wvalue res;
        std::vector<crow::json::wvalue> arr;
        arr.reserve(g_items.size());
        for (const auto& item : g_items) {
            arr.push_back(item_to_json(item));
        }
        res["items"] = std::move(arr);
        res["count"] = static_cast<int>(g_items.size());
        return res;
    });

    // Get single item
    CROW_ROUTE(app, "/api/items/<int>")
    ([](int id) {
        std::lock_guard<std::mutex> lock(g_mutex);
        auto it = std::find_if(g_items.begin(), g_items.end(),
                               [id](const Item& i) { return i.id == id; });
        if (it == g_items.end()) {
            return crow::response(404, "Item not found");
        }
        return crow::response(item_to_json(*it));
    });

    // Create item
    CROW_ROUTE(app, "/api/items").methods(crow::HTTPMethod::POST)
    ([](const crow::request& req) {
        auto body = crow::json::load(req.body);
        if (!body || !body.has("name")) {
            return crow::response(400, R"({"error":"name is required"})");
        }
        std::lock_guard<std::mutex> lock(g_mutex);
        Item item;
        item.id          = g_next_id++;
        item.name        = body["name"].s();
        item.description = body.has("description") ? std::string(body["description"].s()) : "";
        g_items.push_back(item);
        auto resp = crow::response(201, item_to_json(item));
        resp.add_header("Content-Type", "application/json");
        return resp;
    });

    // Delete item
    CROW_ROUTE(app, "/api/items/<int>").methods(crow::HTTPMethod::DELETE)
    ([](int id) {
        std::lock_guard<std::mutex> lock(g_mutex);
        auto it = std::find_if(g_items.begin(), g_items.end(),
                               [id](const Item& i) { return i.id == id; });
        if (it == g_items.end()) {
            return crow::response(404, R"({"error":"not found"})");
        }
        g_items.erase(it);
        return crow::response(204);
    });
}

} // namespace routes
