#pragma once

#include "IRegion.h"
#include <vector>
#include <memory>
#include <string>
#include <algorithm>
#include <cmath>

namespace warfactory {

class RegionManager {
private:
    std::vector<std::unique_ptr<IRegion>> regions;
    int next_region_id;

public:
    RegionManager();

    int createRegion(const std::string& region_type, float x, float y, float mass, float radius);

    void addRegion(std::unique_ptr<IRegion> region);

    void removeRegion(int region_id);

    IRegion* getRegion(int region_id);
    const IRegion* getRegion(int region_id) const;

    std::vector<IRegion*> getRegionsInRadius(float center_x, float center_y, float radius);

    std::vector<IRegion*> getRegionsByType(const std::string& region_type);

    void updateAllRegions(float delta_time);

    void processFusions();

    size_t getRegionCount() const { return regions.size(); }

    void clear();
};

// ========================================
// INLINE IMPLEMENTATIONS
// ========================================

inline RegionManager::RegionManager() : next_region_id(1) {
}

inline int RegionManager::createRegion(const std::string& region_type, float x, float y, float mass, float radius) {
    (void)region_type; (void)x; (void)y; (void)mass; (void)radius;
    const int region_id = next_region_id++;
    return region_id;
}

inline void RegionManager::addRegion(std::unique_ptr<IRegion> region) {
    if (region) {
        regions.push_back(std::move(region));
    }
}

inline void RegionManager::removeRegion(int region_id) {
    regions.erase(
        std::remove_if(regions.begin(), regions.end(),
            [region_id](const std::unique_ptr<IRegion>& region) {
                return region && region->getId() == region_id;
            }),
        regions.end()
    );
}

inline IRegion* RegionManager::getRegion(int region_id) {
    for (const std::unique_ptr<IRegion>& region : regions) {
        if (region && region->getId() == region_id) {
            return region.get();
        }
    }
    return nullptr;
}

inline const IRegion* RegionManager::getRegion(int region_id) const {
    for (const std::unique_ptr<IRegion>& region : regions) {
        if (region && region->getId() == region_id) {
            return region.get();
        }
    }
    return nullptr;
}

inline std::vector<IRegion*> RegionManager::getRegionsInRadius(float center_x, float center_y, float radius) {
    std::vector<IRegion*> result;
    const float radius_squared = radius * radius;

    for (const std::unique_ptr<IRegion>& region : regions) {
        if (region) {
            const float dx = region->getX() - center_x;
            const float dy = region->getY() - center_y;
            const float distance_squared = dx * dx + dy * dy;

            if (distance_squared <= radius_squared) {
                result.push_back(region.get());
            }
        }
    }

    return result;
}

inline std::vector<IRegion*> RegionManager::getRegionsByType(const std::string& region_type) {
    std::vector<IRegion*> result;

    for (const std::unique_ptr<IRegion>& region : regions) {
        if (region && region->getType() == region_type) {
            result.push_back(region.get());
        }
    }

    return result;
}

inline void RegionManager::updateAllRegions(float delta_time) {
    for (const std::unique_ptr<IRegion>& region : regions) {
        if (region) {
            region->update(delta_time);
        }
    }
}

inline void RegionManager::processFusions() {
    for (size_t i = 0; i < regions.size(); ++i) {
        if (!regions[i]) continue;

        for (size_t j = i + 1; j < regions.size(); ++j) {
            if (!regions[j]) continue;

            const IRegion* region_a = regions[i].get();
            const IRegion* region_b = regions[j].get();

            const float dx = region_a->getX() - region_b->getX();
            const float dy = region_a->getY() - region_b->getY();
            const float distance = std::sqrt(dx * dx + dy * dy);

            const float fusion_threshold = (region_a->getRadius() + region_b->getRadius()) * 0.5f;

            if (distance < fusion_threshold) {
                if (region_a->getType() == region_b->getType()) {
                    // TODO: Implement fusion logic
                }
            }
        }
    }
}

inline void RegionManager::clear() {
    regions.clear();
    next_region_id = 1;
}

} // namespace warfactory