#pragma once

#include "types.h"

#include <mutex>
#include <set>
#include <string>
#include <vector>
#include <unordered_map>
#include <chrono>

#include <authdb/client.h>
#include <uuidp.h>

namespace mediadb {

// ---- Group Policy Object UUIDs (static, deterministic) ----

static constexpr const char* GPO_STORE_CREATE  = "c7a3e1b0-9f21-4d6a-8b3c-1a2f4e6d8c01";
static constexpr const char* GPO_STORE_DELETE  = "d8b4f2c1-a032-4e7b-9c4d-2b3a5f7e9d02";
static constexpr const char* GPO_STORE_EDIT    = "e9c5a3d2-b143-4f8c-ad5e-3c4b6a8f0e03";
static constexpr const char* GPO_ALBUM_CREATE  = "f0d6b4e3-c254-4a9d-be6f-4d5c7b9a1f04";
static constexpr const char* GPO_ALBUM_DELETE  = "a1e7c5f4-d365-4bae-8f70-5e6d8c0b2a05";
static constexpr const char* GPO_ALBUM_EDIT    = "b2f8d6a5-e476-4cbf-9081-6f7e9d1c3b06";
static constexpr const char* GPO_MEDIA_ADD     = "c3a9e7b6-f587-4dc0-a192-708fae2d4c07";
static constexpr const char* GPO_MEDIA_DELETE  = "d4b0f8c7-a698-4ed1-b2a3-819abf3e5d08";
static constexpr const char* GPO_EXPORT        = "e5c1a9d8-b7a9-4fe2-83b4-92abc04f6e09";
static constexpr const char* GPO_IMPORT        = "f6d2b0e9-c8ba-4af3-94c5-a3bcd15a7f0a";

struct GpoDefinition {
    const char* id;
    const char* name;
    const char* description;
};

static constexpr GpoDefinition ALL_GPOS[] = {
    { GPO_STORE_CREATE,  "mediadb.store.create",  "Media DB - Create new stores" },
    { GPO_STORE_DELETE,  "mediadb.store.delete",  "Media DB - Delete stores" },
    { GPO_STORE_EDIT,    "mediadb.store.edit",    "Media DB - Rename/edit stores" },
    { GPO_ALBUM_CREATE,  "mediadb.album.create",  "Media DB - Create new albums" },
    { GPO_ALBUM_DELETE,  "mediadb.album.delete",  "Media DB - Delete albums" },
    { GPO_ALBUM_EDIT,    "mediadb.album.edit",    "Media DB - Edit albums (public toggle)" },
    { GPO_MEDIA_ADD,     "mediadb.media.add",     "Media DB - Add/upload media" },
    { GPO_MEDIA_DELETE,  "mediadb.media.delete",  "Media DB - Delete media" },
    { GPO_EXPORT,        "mediadb.db.export",     "Media DB - Export database" },
    { GPO_IMPORT,        "mediadb.db.import",     "Media DB - Import database" },
};

class AuthService {
public:
    AuthService(const std::string& authdb_url,
                const std::string& client_name,
                const std::string& client_secret);

    void try_init_policies(authdb::client::Client& client, const std::string& domain_key = {});
    bool is_authorized(const HttpRequest& req) const;
    bool check_gpo(const HttpRequest& req, const char* gpo_id) const;

    const std::string& url() const { return authdb_url_; }
    const std::string& client_name() const { return client_name_; }
    const std::string& client_secret() const { return client_secret_; }
    authdb::client::ConnectionPool& pool() const { return pool_; }

private:
    std::string authdb_url_;
    std::string client_name_;
    std::string client_secret_;
    mutable std::mutex gpo_mutex_;
    std::set<std::string> gpo_initialized_domains_;
    mutable authdb::client::ConnectionPool pool_;

    // Session cache: token -> expiry time
    static constexpr int CACHE_TTL_SECONDS = 300; // 5 minutes
    mutable std::mutex cache_mutex_;
    mutable std::unordered_map<std::string,
        std::chrono::steady_clock::time_point> auth_cache_;
    bool check_cache(const std::string& token) const;
    void cache_token(const std::string& token) const;
};

} // namespace mediadb
