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

import { PartnershipBondV3Safe } from "../../contracts/bonds/PartnershipBondV3Safe.sol";
import { AccountabilityBondV3Safe } from "../../contracts/bonds/AccountabilityBondV3Safe.sol";
import { V3Fixtures } from "../helpers/V3Fixtures.sol";

/// @notice Directed lifecycle regression for the reduced V3Safe state surface.
/// @dev The former threshold/dispute-driven state machine was removed. The
///      remaining custody state transitions are either typed mutual consent or
///      bounded permissionless principal recovery.
contract StatefulBondSafety is V3Fixtures {
    PartnershipBondV3Safe internal partnership;
    AccountabilityBondV3Safe internal accountability;
    uint256 internal partnershipBondId;
    uint256 internal accountabilityBondId;

    function setUp() public {
        _setUpDependencies();
        partnership = new PartnershipBondV3Safe(
            owner, address(0), address(consensus), address(disputeRegistry), 10 ether, 20 ether, 100 ether, address(0)
        );
        accountability = new AccountabilityBondV3Safe(
            owner, address(consensus), address(disputeRegistry), 10 ether, 100 ether, address(0)
        );
        partnershipBondId = _createPartnership(partnership, _partnershipTerms(1001, 1 ether, 2 ether));
        _fundActivePartnership(partnership, partnershipBondId, 1 ether, 2 ether);
        accountabilityBondId = _createAccountability(accountability, _accountabilityTerms(1002, 2 ether));
        _fundActiveAccountability(accountability, accountabilityBondId, 2 ether);
    }

    function test_directedLegacyCallsRemainFailClosedAcrossActiveBonds() external {
        vm.expectRevert(PartnershipBondV3Safe.PilotMutualConsentOnly.selector);
        partnership.requestSettlement(partnershipBondId);
        vm.expectRevert(PartnershipBondV3Safe.PilotMutualConsentOnly.selector);
        partnership.challengeSettlement(partnershipBondId, 1);
        (bool attestOk,) = address(accountability)
            .call(
                abi.encodeWithSignature(
                    "attestBreach(uint256,uint256,bytes32,uint96)",
                    accountabilityBondId,
                    1 ether,
                    keccak256("opaque evidence"),
                    1
                )
            );
        assertFalse(attestOk);
        (bool resolveOk,) =
            address(accountability).call(abi.encodeWithSignature("resolveChallenge(uint256)", accountabilityBondId));
        assertFalse(resolveOk);
        assertEq(partnership.creditOf(address(0), partyA) + partnership.creditOf(address(0), partyB), 0);
        assertEq(accountability.creditOf(address(0), company) + accountability.creditOf(address(0), counterparty), 0);
    }

    function test_directedExpiryRemainsPermissionlessAndPrincipalOnly() external {
        PartnershipBondV3Safe.BondData memory p = partnership.bondOf(partnershipBondId);
        AccountabilityBondV3Safe.BondData memory a = accountability.bondOf(accountabilityBondId);
        vm.warp(p.terms.activePeriodEnd > a.terms.activePeriodEnd ? p.terms.activePeriodEnd : a.terms.activePeriodEnd);
        partnership.markExpired(partnershipBondId);
        partnership.forceExit(partnershipBondId);
        accountability.markExpired(accountabilityBondId);
        accountability.forceExit(accountabilityBondId);
        assertEq(partnership.creditOf(address(0), partyA), 1 ether);
        assertEq(partnership.creditOf(address(0), partyB), 2 ether);
        assertEq(accountability.creditOf(address(0), company), 2 ether);
        assertEq(accountability.creditOf(address(0), counterparty), 0);
    }
}
