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

import { V3Fixtures } from "../helpers/V3Fixtures.sol";
import {
    BaseSepoliaRehearsalAccessControllerV3
} from "../../contracts/pilot/BaseSepoliaRehearsalAccessControllerV3.sol";
import { SafeBondFactoryV3 } from "../../contracts/bonds/SafeBondFactoryV3.sol";
import { PartnershipBondFactoryV3 } from "../../contracts/bonds/PartnershipBondFactoryV3.sol";
import { AccountabilityBondFactoryV3 } from "../../contracts/bonds/AccountabilityBondFactoryV3.sol";
import { PartnershipBondV3Safe } from "../../contracts/bonds/PartnershipBondV3Safe.sol";
import { AccountabilityBondV3Safe } from "../../contracts/bonds/AccountabilityBondV3Safe.sol";
import { ThresholdConsensusV3 } from "../../contracts/consensus/ThresholdConsensusV3.sol";
import { DisputeRegistryV3 } from "../../contracts/disputes/DisputeRegistryV3.sol";

/// @notice Exercises the shared controller interface against the actual named
/// Base Sepolia profile from factory binding through child registration.
contract SafeBondFactorySepoliaLifecycleV3Test is V3Fixtures {
    BaseSepoliaRehearsalAccessControllerV3 internal controller;
    SafeBondFactoryV3 internal factory;
    PartnershipBondFactoryV3 internal partnershipFactory;
    AccountabilityBondFactoryV3 internal accountabilityFactory;

    mapping(address => bool) internal guardianPauseTarget;

    function isGuardianPauseTarget(address target) external view returns (bool) {
        return guardianPauseTarget[target];
    }

    function setUp() external {
        vm.chainId(84532);
        _setUpDependencies();
        controller = new BaseSepoliaRehearsalAccessControllerV3(address(this), 1 ether, 0.5 ether);
        PartnershipBondV3Safe partnershipIdentity = new PartnershipBondV3Safe(
            owner,
            address(0),
            address(consensus),
            address(disputeRegistry),
            0.1 ether,
            0.2 ether,
            0.5 ether,
            address(controller)
        );
        AccountabilityBondV3Safe accountabilityIdentity = new AccountabilityBondV3Safe(
            owner, address(consensus), address(disputeRegistry), 0.2 ether, 0.5 ether, address(controller)
        );
        address predictedCoordinator = vm.computeCreateAddress(address(this), vm.getNonce(address(this)) + 2);
        partnershipFactory = new PartnershipBondFactoryV3(
            predictedCoordinator,
            owner,
            address(consensus),
            address(disputeRegistry),
            0.1 ether,
            0.2 ether,
            0.5 ether,
            address(controller)
        );
        accountabilityFactory = new AccountabilityBondFactoryV3(
            predictedCoordinator,
            owner,
            address(consensus),
            address(disputeRegistry),
            0.2 ether,
            0.5 ether,
            address(controller),
            _accountabilityInitCode(
                owner, address(consensus), address(disputeRegistry), 0.2 ether, 0.5 ether, address(controller)
            ),
            address(accountabilityIdentity).codehash
        );
        factory = new SafeBondFactoryV3(
            owner,
            address(consensus),
            address(disputeRegistry),
            address(controller),
            0.1 ether,
            0.2 ether,
            0.5 ether,
            0.2 ether,
            0.5 ether,
            address(partnershipFactory).codehash,
            address(accountabilityFactory).codehash,
            address(partnershipIdentity).codehash,
            address(accountabilityIdentity).codehash,
            keccak256(
                _accountabilityInitCode(
                    owner, address(consensus), address(disputeRegistry), 0.2 ether, 0.5 ether, address(controller)
                )
            )
        );
        assertEq(address(factory), predictedCoordinator);
    }

    function test_factoryRegistersSepoliaChildAndControllerReleasesWithdrawalAllocation() external {
        controller.setModule(address(factory), true);
        controller.setDesignPartner(partyA, true);
        controller.setCaps(1 ether, 0.5 ether);
        controller.setDeployEnabled(true);
        vm.prank(owner);
        factory.configureFactories(address(partnershipFactory), address(accountabilityFactory));
        vm.prank(owner);
        factory.setDeployAllowed(true);
        vm.prank(owner);
        PartnershipBondV3Safe bond = PartnershipBondV3Safe(factory.deployPartnership(partyA, address(0)));
        assertEq(controller.positionDesignPartner(address(bond)), partyA);
        assertEq(address(bond.pilotController()), address(controller));
        guardianPauseTarget[address(bond)] = true;
        controller.setWriteEnabled(true);

        PartnershipBondV3Safe.Terms memory terms = _partnershipTerms(808, 0.1 ether, 0.1 ether);
        // The Base pilot has no evidence-rule class; terms remain compatible
        // with the immutable signed struct but the legacy selectors are zero.
        terms.objectiveRuleClass = 0;
        terms.objectiveRuleSchemaVersion = 0;
        uint256 bondId = _createPartnership(bond, terms);
        _fundActivePartnership(bond, bondId, 0.1 ether, 0.1 ether);
        assertEq(controller.positionAllocated(address(bond)), 0.2 ether);
        vm.warp(terms.activePeriodEnd);
        bond.markExpired(bondId);
        bond.forceExit(bondId);
        vm.prank(partyA);
        bond.withdrawCredit(address(0));
        vm.prank(partyB);
        bond.withdrawCredit(address(0));
        assertEq(controller.positionAllocated(address(bond)), 0);
        assertEq(controller.requiredChainId(), 84532);
    }
}
