// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import "../vendor/openzeppelin/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "../registry/UniversalAssetRegistry.sol";

/**
 * @title PoolManager
 * @notice Manages pool creation, configuration, and lifecycle
 * @dev Auto-creates pools when new assets are registered
 */
contract PoolManager is 
    Initializable,
    AccessControlUpgradeable,
    UUPSUpgradeable
{
    bytes32 public constant POOL_ADMIN_ROLE = keccak256("POOL_ADMIN_ROLE");
    bytes32 public constant UPGRADER_ROLE = keccak256("UPGRADER_ROLE");

    struct PoolInfo {
        address pool;
        address provider;       // DODO, Uniswap, etc.
        address tokenA;
        address tokenB;
        uint256 liquidityUSD;
        uint256 volume24h;
        uint256 createdAt;
        uint256 lastUpdateTime;
        bool isActive;
    }

    // Storage
    UniversalAssetRegistry public assetRegistry;
    mapping(address => PoolInfo[]) public tokenPools; // token => pools
    mapping(address => PoolInfo) public poolRegistry; // pool address => info
    address[] public allPools;
    
    // Provider addresses
    address public dodoProvider;
    address public uniswapV3Provider;
    address public curveProvider;

    event PoolCreated(
        address indexed pool,
        address indexed token,
        address provider,
        UniversalAssetRegistry.AssetType assetType
    );
    
    event PoolHealthChecked(
        address indexed pool,
        bool isHealthy,
        string reason
    );
    
    event PoolLiquidityUpdated(
        address indexed pool,
        uint256 newLiquidityUSD
    );

    /// @custom:oz-upgrades-unsafe-allow constructor
    constructor() {
        _disableInitializers();
    }

    function initialize(
        address _assetRegistry,
        address admin
    ) external initializer {
        __AccessControl_init();
        __UUPSUpgradeable_init();
        
        require(_assetRegistry != address(0), "Zero registry");
        
        assetRegistry = UniversalAssetRegistry(_assetRegistry);
        
        _grantRole(DEFAULT_ADMIN_ROLE, admin);
        _grantRole(POOL_ADMIN_ROLE, admin);
        _grantRole(UPGRADER_ROLE, admin);
    }

    function _authorizeUpgrade(address newImplementation)
        internal override onlyRole(UPGRADER_ROLE) {}

    /**
     * @notice Auto-create pool when new asset registered
     */
    function onAssetRegistered(
        address token,
        UniversalAssetRegistry.AssetType assetType
    ) external onlyRole(POOL_ADMIN_ROLE) returns (address pool) {
        // Determine optimal pool type based on asset type
        if (assetType == UniversalAssetRegistry.AssetType.Stablecoin || 
            assetType == UniversalAssetRegistry.AssetType.ISO4217W ||
            assetType == UniversalAssetRegistry.AssetType.GRU) {
            // Create DODO PMM pool (optimal for stable / GRU c* pairs)
            pool = _createDODOPool(token);
        } else if (assetType == UniversalAssetRegistry.AssetType.ERC20Standard ||
                   assetType == UniversalAssetRegistry.AssetType.GovernanceToken) {
            // Create Uniswap V3 pool (optimal for volatile pairs)
            pool = _createUniswapV3Pool(token);
        } else {
            // For other types (Security, Commodity), manual pool creation
            return address(0);
        }
        
        emit PoolCreated(pool, token, dodoProvider, assetType);
        
        return pool;
    }

    /**
     * @notice Create DODO PMM pool
     */
    function _createDODOPool(address token) internal returns (address) {
        // In production, this would call DODOPMMIntegration to create actual pool
        // For now, placeholder
        return address(0);
    }

    /**
     * @notice Create Uniswap V3 pool
     */
    function _createUniswapV3Pool(address token) internal returns (address) {
        // In production, this would deploy Uniswap V3 pool
        // For now, placeholder
        return address(0);
    }

    /**
     * @notice Register existing pool
     */
    function registerPool(
        address pool,
        address provider,
        address tokenA,
        address tokenB,
        uint256 liquidityUSD
    ) external onlyRole(POOL_ADMIN_ROLE) {
        require(pool != address(0), "Zero address");
        require(!poolRegistry[pool].isActive, "Already registered");
        
        PoolInfo memory info = PoolInfo({
            pool: pool,
            provider: provider,
            tokenA: tokenA,
            tokenB: tokenB,
            liquidityUSD: liquidityUSD,
            volume24h: 0,
            createdAt: block.timestamp,
            lastUpdateTime: block.timestamp,
            isActive: true
        });
        
        poolRegistry[pool] = info;
        tokenPools[tokenA].push(info);
        if (tokenB != tokenA) {
            tokenPools[tokenB].push(info);
        }
        allPools.push(pool);
    }

    /**
     * @notice Check pool health
     */
    function checkPoolHealth(address pool) external view returns (
        bool isHealthy,
        string memory reason
    ) {
        PoolInfo memory info = poolRegistry[pool];
        
        if (!info.isActive) {
            return (false, "Pool inactive");
        }
        
        if (info.liquidityUSD < 1000e18) {
            return (false, "Insufficient liquidity");
        }
        
        if (block.timestamp - info.lastUpdateTime > 7 days) {
            return (false, "Stale data");
        }
        
        return (true, "Healthy");
    }

    /**
     * @notice Update pool liquidity
     */
    function updatePoolLiquidity(
        address pool,
        uint256 liquidityUSD
    ) external onlyRole(POOL_ADMIN_ROLE) {
        require(poolRegistry[pool].isActive, "Pool not registered");
        
        poolRegistry[pool].liquidityUSD = liquidityUSD;
        poolRegistry[pool].lastUpdateTime = block.timestamp;
        
        emit PoolLiquidityUpdated(pool, liquidityUSD);
    }

    /**
     * @notice Set provider addresses
     */
    function setProviders(
        address _dodoProvider,
        address _uniswapV3Provider,
        address _curveProvider
    ) external onlyRole(DEFAULT_ADMIN_ROLE) {
        dodoProvider = _dodoProvider;
        uniswapV3Provider = _uniswapV3Provider;
        curveProvider = _curveProvider;
    }

    // View functions
    
    function getPoolsForToken(address token) external view returns (PoolInfo[] memory) {
        return tokenPools[token];
    }

    function getPoolInfo(address pool) external view returns (PoolInfo memory) {
        return poolRegistry[pool];
    }

    function getAllPools() external view returns (address[] memory) {
        return allPools;
    }

    function getPoolCount() external view returns (uint256) {
        return allPools.length;
    }
}
