// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import { PartnershipBondV3Safe } from "./PartnershipBondV3Safe.sol";
import { IPilotAccessControllerV3 } from "../pilot/IPilotAccessControllerV3.sol";

/// @title PartnershipBondFactoryV3
/// @notice Coordinator-only deployer for partnership bonds.
/// @dev Splitting each deployment path into its own factory keeps the runtime
///      bytecode of every production factory below the EIP-170 size limit.
///      `bondOwner` is supplied to the child constructor, so the coordinator
///      never owns a partnership bond, even transiently.
contract PartnershipBondFactoryV3 {
    uint256 private constant BASE_CHAIN_ID = 8453;
    uint256 private constant BASE_SEPOLIA_CHAIN_ID = 84532;
    error NotCoordinator();
    error ZeroAddress();

    address public immutable coordinator;
    address public immutable bondOwner;
    address public immutable consensus;
    address public immutable disputeRegistry;
    address public immutable pilotController;
    uint256 public immutable maxPartyNativePrincipal;
    uint256 public immutable maxBondNativePrincipal;
    uint256 public immutable maxAggregateNativeLiability;

    constructor(
        address _coordinator,
        address _bondOwner,
        address _consensus,
        address _disputeRegistry,
        uint256 _maxPartyNativePrincipal,
        uint256 _maxBondNativePrincipal,
        uint256 _maxAggregateNativeLiability,
        address _pilotController
    ) {
        if (
            _coordinator == address(0) || _bondOwner == address(0) || _consensus == address(0)
                || ((block.chainid == BASE_CHAIN_ID || block.chainid == BASE_SEPOLIA_CHAIN_ID)
                    && _pilotController == address(0))
        ) revert ZeroAddress();
        if (
            _pilotController != address(0)
                && IPilotAccessControllerV3(_pilotController).requiredChainId() != block.chainid
        ) {
            revert ZeroAddress();
        }
        if (
            _maxPartyNativePrincipal == 0 || _maxBondNativePrincipal == 0 || _maxAggregateNativeLiability == 0
                || _maxPartyNativePrincipal > _maxBondNativePrincipal
                || _maxBondNativePrincipal > _maxAggregateNativeLiability
        ) revert ZeroAddress();
        coordinator = _coordinator;
        bondOwner = _bondOwner;
        consensus = _consensus;
        _disputeRegistry;
        disputeRegistry = address(0);
        pilotController = _pilotController;
        maxPartyNativePrincipal = _maxPartyNativePrincipal;
        maxBondNativePrincipal = _maxBondNativePrincipal;
        maxAggregateNativeLiability = _maxAggregateNativeLiability;
    }

    modifier onlyCoordinator() {
        if (msg.sender != coordinator) revert NotCoordinator();
        _;
    }

    /// @dev `rewardProgram` is an ABI-compatibility parameter and must be
    ///      zero for the initial pilot. PartnershipBondV3Safe enforces this.
    function deploy(address rewardProgram) external onlyCoordinator returns (address bond) {
        bond = address(
            new PartnershipBondV3Safe(
                bondOwner,
                rewardProgram,
                consensus,
                disputeRegistry,
                maxPartyNativePrincipal,
                maxBondNativePrincipal,
                maxAggregateNativeLiability,
                pilotController
            )
        );
    }
}
