#pragma once

#include <algorithm>
#include <extra2d/core/service_interface.h>
#include <extra2d/core/types.h>
#include <functional>
#include <memory>
#include <mutex>
#include <typeindex>
#include <unordered_map>
#include <vector>

namespace extra2d {

/**
 * @brief 服务工厂函数类型
 */
template <typename T> using ServiceFactory = std::function<SharedPtr<T>()>;

/**
 * @brief 服务定位器
 * 实现依赖注入和服务发现模式，解耦模块间依赖
 *
 * 特性：
 * - 类型安全的服务注册和获取
 * - 支持服务工厂延迟创建
 * - 支持服务依赖声明
 * - 线程安全
 * - 支持 Mock 测试
 */
class ServiceLocator {
public:
  /**
   * @brief 获取单例实例
   * @return 服务定位器实例引用
   */
  static ServiceLocator &instance();

  ServiceLocator(const ServiceLocator &) = delete;
  ServiceLocator &operator=(const ServiceLocator &) = delete;

  /**
   * @brief 注册服务实例
   * @tparam T 服务接口类型
   * @param service 服务实例
   */
  template <typename T> void registerService(SharedPtr<T> service) {
    static_assert(std::is_base_of_v<IService, T>,
                  "T must derive from IService");

    std::lock_guard<std::mutex> lock(mutex_);
    auto typeId = std::type_index(typeid(T));
    services_[typeId] = std::static_pointer_cast<IService>(service);
    orderedServices_.push_back(service);
    sortServices();
  }

  /**
   * @brief 注册服务工厂
   * @tparam T 服务接口类型
   * @param factory 服务工厂函数
   */
  template <typename T> void registerFactory(ServiceFactory<T> factory) {
    static_assert(std::is_base_of_v<IService, T>,
                  "T must derive from IService");

    std::lock_guard<std::mutex> lock(mutex_);
    auto typeId = std::type_index(typeid(T));
    factories_[typeId] = [factory]() -> SharedPtr<IService> {
      return std::static_pointer_cast<IService>(factory());
    };

    // 立即创建服务实例并添加到有序列表
    auto service = factories_[typeId]();
    services_[typeId] = service;
    orderedServices_.push_back(service);
    sortServices();
  }

  /**
   * @brief 获取服务实例
   * @tparam T 服务接口类型
   * @return 服务实例，不存在返回 nullptr
   */
  template <typename T> SharedPtr<T> getService() const {
    static_assert(std::is_base_of_v<IService, T>,
                  "T must derive from IService");

    std::lock_guard<std::mutex> lock(mutex_);
    auto typeId = std::type_index(typeid(T));

    auto it = services_.find(typeId);
    if (it != services_.end()) {
      return std::static_pointer_cast<T>(it->second);
    }

    auto factoryIt = factories_.find(typeId);
    if (factoryIt != factories_.end()) {
      auto service = factoryIt->second();
      services_[typeId] = service;
      return std::static_pointer_cast<T>(service);
    }

    return nullptr;
  }

  /**
   * @brief 尝试获取服务实例（不创建）
   * @tparam T 服务接口类型
   * @return 服务实例，不存在返回 nullptr
   */
  template <typename T> SharedPtr<T> tryGetService() const {
    static_assert(std::is_base_of_v<IService, T>,
                  "T must derive from IService");

    std::lock_guard<std::mutex> lock(mutex_);
    auto typeId = std::type_index(typeid(T));
    auto it = services_.find(typeId);
    if (it != services_.end()) {
      return std::static_pointer_cast<T>(it->second);
    }
    return nullptr;
  }

  /**
   * @brief 检查服务是否已注册
   * @tparam T 服务接口类型
   * @return 已注册返回 true
   */
  template <typename T> bool hasService() const {
    std::lock_guard<std::mutex> lock(mutex_);
    auto typeId = std::type_index(typeid(T));
    return services_.find(typeId) != services_.end() ||
           factories_.find(typeId) != factories_.end();
  }

  /**
   * @brief 注销服务
   * @tparam T 服务接口类型
   */
  template <typename T> void unregisterService() {
    std::lock_guard<std::mutex> lock(mutex_);
    auto typeId = std::type_index(typeid(T));

    auto it = services_.find(typeId);
    if (it != services_.end()) {
      auto service = it->second;
      services_.erase(it);

      auto orderIt =
          std::find(orderedServices_.begin(), orderedServices_.end(), service);
      if (orderIt != orderedServices_.end()) {
        orderedServices_.erase(orderIt);
      }
    }

    factories_.erase(typeId);
  }

  /**
   * @brief 初始化所有已注册的服务
   * @return 所有服务初始化成功返回 true
   */
  bool initializeAll();

  /**
   * @brief 关闭所有服务
   */
  void shutdownAll();

  /**
   * @brief 更新所有服务
   * @param deltaTime 帧间隔时间
   */
  void updateAll(float deltaTime);

  /**
   * @brief 暂停所有服务
   */
  void pauseAll();

  /**
   * @brief 恢复所有服务
   */
  void resumeAll();

  /**
   * @brief 获取所有服务（按优先级排序）
   * @return 服务列表
   */
  std::vector<SharedPtr<IService>> getAllServices() const;

  /**
   * @brief 清空所有服务和工厂
   */
  void clear();

  /**
   * @brief 获取已注册服务数量
   * @return 服务数量
   */
  size_t size() const { return services_.size(); }

private:
  ServiceLocator() = default;
  ~ServiceLocator() = default;

  /**
   * @brief 按优先级排序服务
   */
  void sortServices();

  mutable std::unordered_map<std::type_index, SharedPtr<IService>> services_;
  std::unordered_map<std::type_index, std::function<SharedPtr<IService>()>>
      factories_;
  std::vector<SharedPtr<IService>> orderedServices_;
  mutable std::mutex mutex_;
};

/**
 * @brief 服务注册器
 * 用于静态注册服务
 */
template <typename Interface, typename Implementation> class ServiceRegistrar {
public:
  explicit ServiceRegistrar(ServiceFactory<Interface> factory = nullptr) {
    if (factory) {
      ServiceLocator::instance().registerFactory<Interface>(factory);
    } else {
      ServiceLocator::instance().registerFactory<Interface>(
          []() -> SharedPtr<Interface> {
            return makeShared<Implementation>();
          });
    }
  }
};

/**
 * @brief 服务注册元数据模板
 * 使用模板元编程实现编译期服务注册
 * 通过静态成员变量的初始化触发注册
 */
template <typename Interface, typename Implementation> struct ServiceAutoReg {
  /**
   * @brief 注册标记，访问此变量时触发服务注册
   */
  static const bool registered;

  /**
   * @brief 执行实际的服务注册
   * @return true 表示注册成功
   */
  static bool doRegister() {
    ::extra2d::ServiceLocator::instance().registerFactory<Interface>(
        []() -> ::extra2d::SharedPtr<Interface> {
          return ::extra2d::makeShared<Implementation>();
        });
    return true;
  }
};

// 静态成员定义，在此处触发注册
template <typename Interface, typename Implementation>
const bool ServiceAutoReg<Interface, Implementation>::registered =
    ServiceAutoReg<Interface, Implementation>::doRegister();

/**
 * @brief 服务注册元数据（带自定义工厂）
 */
template <typename Interface> struct ServiceAutoRegFactory {
  template <typename Factory> struct Impl {
    static const bool registered;

    static bool doRegister(Factory factory) {
      ::extra2d::ServiceLocator::instance().registerFactory<Interface>(factory);
      return true;
    }
  };
};

template <typename Interface>
template <typename Factory>
const bool ServiceAutoRegFactory<Interface>::Impl<Factory>::registered =
    ServiceAutoRegFactory<Interface>::Impl<Factory>::doRegister(Factory{});

/**
 * @brief 自动注册服务宏（元数据驱动）
 * 在服务实现类中使用，通过模板元编程实现自动注册
 * 比静态对象更可靠，不易被编译器优化
 */
#define E2D_AUTO_REGISTER_SERVICE(Interface, Implementation)                   \
  static inline const bool E2D_CONCAT(_service_reg_, __LINE__) =               \
      ServiceAutoReg<Interface, Implementation>::registered

/**
 * @brief 带自定义工厂的自动注册服务宏（元数据驱动）
 */
#define E2D_AUTO_REGISTER_SERVICE_FACTORY(Interface, Factory)                  \
  static inline const bool E2D_CONCAT(_service_factory_reg_, __LINE__) =       \
      ServiceAutoRegFactory<Interface>::Impl<Factory>::registered

} // namespace extra2d
