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

import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";

/**
 * @title BaseDignityBond
 * @notice Base contract for all Universal Dignity Bonds
 * @dev Provides common functionality: pausability, ownership, score validation
 *
 * Mission Alignment: Emergency protection for workers/communities.
 * Can pause if exploit detected, protecting real people from harm.
 */
abstract contract BaseDignityBond is ReentrancyGuard, Pausable {

    // ============ State Variables ============

    /// @notice Contract owner (can pause in emergency)
    address public owner;

    /// @notice Pending owner for two-step ownership transfer
    /// @dev Prevents accidental ownership loss from typos in address
    address public pendingOwner;

    /// @notice Timelock period for distributions (7 days)
    uint256 public constant DISTRIBUTION_TIMELOCK = 7 days;

    // ============ Events ============

    /// @notice Emitted when contract is paused
    event ContractPaused(address indexed by, uint256 timestamp);

    /// @notice Emitted when contract is unpaused
    event ContractUnpaused(address indexed by, uint256 timestamp);

    /// @notice Emitted when ownership transfer is initiated
    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);

    /// @notice Emitted when ownership is transferred
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    // ============ Constructor ============

    constructor() {
        owner = msg.sender;
    }

    // ============ Modifiers ============

    /**
     * @notice Restricts function to contract owner
     */
    modifier onlyOwner() {
        require(msg.sender == owner, "Only owner can call");
        _;
    }

    // ============ Owner Functions ============

    /**
     * @notice Pause contract in case of emergency
     * @dev Only owner can pause. Prevents all bond creation and distributions.
     *
     * Mission Alignment: Emergency stop to protect workers/communities if exploit found.
     * Humanity over control - use sparingly, only for actual emergencies.
     */
    function pause() external onlyOwner {
        _pause();
        emit ContractPaused(msg.sender, block.timestamp);
    }

    /**
     * @notice Unpause contract after emergency is resolved
     * @dev Only owner can unpause. Restores normal operations.
     */
    function unpause() external onlyOwner {
        _unpause();
        emit ContractUnpaused(msg.sender, block.timestamp);
    }

    /**
     * @notice Transfer ownership to new address (step 1 of 2)
     * @dev Use for governance transitions or emergency handoff
     * @param newOwner Address of new owner
     *
     * @custom:security HIGH-005 FIX: Two-step ownership transfer
     * Prevents accidental loss of ownership due to typos. New owner must accept.
     *
     * Mission Alignment: Ownership should be transferable to community governance.
     */
    function transferOwnership(address newOwner) external onlyOwner {
        require(newOwner != address(0), "New owner cannot be zero address");
        require(newOwner != owner, "Already the owner");

        pendingOwner = newOwner;
        emit OwnershipTransferStarted(owner, newOwner);
    }

    /**
     * @notice Accept ownership transfer (step 2 of 2)
     * @dev New owner must call this to complete transfer
     *
     * @custom:security HIGH-005 FIX: Two-step ownership transfer
     * Only pending owner can accept. Prevents typo-based ownership loss.
     */
    function acceptOwnership() external {
        require(msg.sender == pendingOwner, "Only pending owner can accept");
        require(pendingOwner != address(0), "No pending ownership transfer");

        address previousOwner = owner;
        owner = pendingOwner;
        pendingOwner = address(0);

        emit OwnershipTransferred(previousOwner, owner);
    }

    /**
     * @notice Cancel pending ownership transfer
     * @dev Current owner can cancel if transfer was initiated by mistake
     */
    function cancelOwnershipTransfer() external onlyOwner {
        require(pendingOwner != address(0), "No pending transfer to cancel");

        pendingOwner = address(0);
        emit OwnershipTransferStarted(owner, address(0)); // Signal cancellation
    }

    // ============ Validation Helpers ============

    /**
     * @notice Validate score is in valid range (0-10000)
     * @dev Internal helper for score validation
     * @param score Score to validate
     * @param paramName Parameter name for error message
     *
     * Mission Alignment: Prevents data manipulation through invalid scores.
     */
    function _validateScore(uint256 score, string memory paramName) internal pure {
        require(score <= 10000, string(abi.encodePacked(paramName, " must be 0-10000")));
    }

    /**
     * @notice Validate multiple scores at once
     * @dev More gas efficient than individual validation
     * @param scores Array of scores to validate
     */
    function _validateScores(uint256[] memory scores) internal pure {
        uint256 length = scores.length;
        for (uint256 i = 0; i < length;) {
            require(scores[i] <= 10000, "Score must be 0-10000");
            unchecked { ++i; }
        }
    }

    /**
     * @notice Validate address is not zero
     * @param addr Address to validate
     * @param paramName Parameter name for error message
     */
    function _validateAddress(address addr, string memory paramName) internal pure {
        require(addr != address(0), string(abi.encodePacked(paramName, " cannot be zero address")));
    }

    /**
     * @notice Validate amount is greater than zero
     * @param amount Amount to validate
     * @param paramName Parameter name for error message
     */
    function _validateNonZero(uint256 amount, string memory paramName) internal pure {
        require(amount > 0, string(abi.encodePacked(paramName, " must be greater than zero")));
    }

    // ============ View Functions ============

    /**
     * @notice Check if contract is currently paused
     * @return bool True if paused, false otherwise
     */
    function isPaused() external view returns (bool) {
        return paused();
    }
}
