package io.synor.governance;

import java.util.List;

/**
 * Governance SDK Types for Java.
 */
public class Types {
    // Organizational class
}

// ==================== Enums ====================

enum ProposalStatus { draft, active, passed, rejected, executed, cancelled }
enum VoteChoice { yes, no, abstain }
enum DaoType { token, multisig, hybrid }
enum VestingStatus { pending, active, paused, completed, revoked }

// ==================== Config ====================

class GovernanceConfig {
    private final String apiKey;
    private final String endpoint;
    private final int timeoutSecs;
    private final int retries;
    private final boolean debug;

    public GovernanceConfig(String apiKey) {
        this(apiKey, "https://governance.synor.io/v1", 60, 3, false);
    }

    public GovernanceConfig(String apiKey, String endpoint, int timeoutSecs, int retries, boolean debug) {
        this.apiKey = apiKey;
        this.endpoint = endpoint;
        this.timeoutSecs = timeoutSecs;
        this.retries = retries;
        this.debug = debug;
    }

    public String getApiKey() { return apiKey; }
    public String getEndpoint() { return endpoint; }
    public int getTimeoutSecs() { return timeoutSecs; }
    public int getRetries() { return retries; }
    public boolean isDebug() { return debug; }
}

// ==================== Proposal Types ====================

class ProposalAction {
    private String target;
    private String method;
    private String data;
    private String value;

    public String getTarget() { return target; }
    public String getMethod() { return method; }
    public String getData() { return data; }
    public String getValue() { return value; }

    public void setTarget(String target) { this.target = target; }
    public void setMethod(String method) { this.method = method; }
    public void setData(String data) { this.data = data; }
    public void setValue(String value) { this.value = value; }
}

class ProposalDraft {
    private String title;
    private String description;
    private String discussionUrl;
    private Long votingStartTime;
    private Long votingEndTime;
    private List<ProposalAction> actions;
    private String daoId;

    public String getTitle() { return title; }
    public String getDescription() { return description; }
    public String getDiscussionUrl() { return discussionUrl; }
    public Long getVotingStartTime() { return votingStartTime; }
    public Long getVotingEndTime() { return votingEndTime; }
    public List<ProposalAction> getActions() { return actions; }
    public String getDaoId() { return daoId; }

    public void setTitle(String title) { this.title = title; }
    public void setDescription(String description) { this.description = description; }
    public void setDiscussionUrl(String discussionUrl) { this.discussionUrl = discussionUrl; }
    public void setVotingStartTime(Long votingStartTime) { this.votingStartTime = votingStartTime; }
    public void setVotingEndTime(Long votingEndTime) { this.votingEndTime = votingEndTime; }
    public void setActions(List<ProposalAction> actions) { this.actions = actions; }
    public void setDaoId(String daoId) { this.daoId = daoId; }
}

class VoteBreakdown {
    private String yes;
    private String no;
    private String abstain;
    private String quorum;
    private double quorumPercent;
    private boolean quorumReached;

    public String getYes() { return yes; }
    public String getNo() { return no; }
    public String getAbstain() { return abstain; }
    public String getQuorum() { return quorum; }
    public double getQuorumPercent() { return quorumPercent; }
    public boolean isQuorumReached() { return quorumReached; }
}

class Proposal {
    private String id;
    private String title;
    private String description;
    private String proposer;
    private ProposalStatus status;
    private long createdAt;
    private long votingStartTime;
    private long votingEndTime;
    private VoteBreakdown votes;
    private String discussionUrl;
    private List<ProposalAction> actions;
    private String daoId;
    private String snapshotBlock;
    private Long executedAt;
    private String executedTxHash;

    public String getId() { return id; }
    public String getTitle() { return title; }
    public String getDescription() { return description; }
    public String getProposer() { return proposer; }
    public ProposalStatus getStatus() { return status; }
    public long getCreatedAt() { return createdAt; }
    public long getVotingStartTime() { return votingStartTime; }
    public long getVotingEndTime() { return votingEndTime; }
    public VoteBreakdown getVotes() { return votes; }
    public String getDiscussionUrl() { return discussionUrl; }
    public List<ProposalAction> getActions() { return actions; }
    public String getDaoId() { return daoId; }
    public String getSnapshotBlock() { return snapshotBlock; }
    public Long getExecutedAt() { return executedAt; }
    public String getExecutedTxHash() { return executedTxHash; }
}

class ProposalFilter {
    private ProposalStatus status;
    private String proposer;
    private String daoId;
    private Integer limit;
    private Integer offset;

    public ProposalStatus getStatus() { return status; }
    public String getProposer() { return proposer; }
    public String getDaoId() { return daoId; }
    public Integer getLimit() { return limit; }
    public Integer getOffset() { return offset; }

    public void setStatus(ProposalStatus status) { this.status = status; }
    public void setProposer(String proposer) { this.proposer = proposer; }
    public void setDaoId(String daoId) { this.daoId = daoId; }
    public void setLimit(Integer limit) { this.limit = limit; }
    public void setOffset(Integer offset) { this.offset = offset; }
}

// ==================== Voting Types ====================

class Vote {
    private VoteChoice choice;
    private String reason;

    public VoteChoice getChoice() { return choice; }
    public String getReason() { return reason; }

    public void setChoice(VoteChoice choice) { this.choice = choice; }
    public void setReason(String reason) { this.reason = reason; }
}

class VoteReceipt {
    private String id;
    private String proposalId;
    private String voter;
    private VoteChoice choice;
    private String weight;
    private long timestamp;
    private String txHash;
    private String reason;

    public String getId() { return id; }
    public String getProposalId() { return proposalId; }
    public String getVoter() { return voter; }
    public VoteChoice getChoice() { return choice; }
    public String getWeight() { return weight; }
    public long getTimestamp() { return timestamp; }
    public String getTxHash() { return txHash; }
    public String getReason() { return reason; }
}

class VotingPower {
    private String address;
    private String balance;
    private String delegatedTo;
    private String delegatedFrom;
    private String totalPower;
    private long blockNumber;

    public String getAddress() { return address; }
    public String getBalance() { return balance; }
    public String getDelegatedTo() { return delegatedTo; }
    public String getDelegatedFrom() { return delegatedFrom; }
    public String getTotalPower() { return totalPower; }
    public long getBlockNumber() { return blockNumber; }
}

class DelegationReceipt {
    private String id;
    private String delegator;
    private String delegatee;
    private String amount;
    private long timestamp;
    private String txHash;

    public String getId() { return id; }
    public String getDelegator() { return delegator; }
    public String getDelegatee() { return delegatee; }
    public String getAmount() { return amount; }
    public long getTimestamp() { return timestamp; }
    public String getTxHash() { return txHash; }
}

// ==================== DAO Types ====================

class DaoConfig {
    private String name;
    private String description;
    private DaoType type;
    private String tokenAddress;
    private String quorumPercent;
    private int votingPeriodDays;
    private int timelockDays;
    private Integer proposalThreshold;
    private List<String> multisigMembers;
    private Integer multisigThreshold;

    public String getName() { return name; }
    public String getDescription() { return description; }
    public DaoType getType() { return type; }
    public String getTokenAddress() { return tokenAddress; }
    public String getQuorumPercent() { return quorumPercent; }
    public int getVotingPeriodDays() { return votingPeriodDays; }
    public int getTimelockDays() { return timelockDays; }
    public Integer getProposalThreshold() { return proposalThreshold; }
    public List<String> getMultisigMembers() { return multisigMembers; }
    public Integer getMultisigThreshold() { return multisigThreshold; }

    public void setName(String name) { this.name = name; }
    public void setDescription(String description) { this.description = description; }
    public void setType(DaoType type) { this.type = type; }
    public void setTokenAddress(String tokenAddress) { this.tokenAddress = tokenAddress; }
    public void setQuorumPercent(String quorumPercent) { this.quorumPercent = quorumPercent; }
    public void setVotingPeriodDays(int votingPeriodDays) { this.votingPeriodDays = votingPeriodDays; }
    public void setTimelockDays(int timelockDays) { this.timelockDays = timelockDays; }
    public void setProposalThreshold(Integer proposalThreshold) { this.proposalThreshold = proposalThreshold; }
    public void setMultisigMembers(List<String> multisigMembers) { this.multisigMembers = multisigMembers; }
    public void setMultisigThreshold(Integer multisigThreshold) { this.multisigThreshold = multisigThreshold; }
}

class DaoTreasury {
    private String address;
    private String balance;
    private String currency;
    private List<TreasuryAsset> assets;

    public String getAddress() { return address; }
    public String getBalance() { return balance; }
    public String getCurrency() { return currency; }
    public List<TreasuryAsset> getAssets() { return assets; }
}

class TreasuryAsset {
    private String address;
    private String symbol;
    private String balance;
    private String valueUsd;

    public String getAddress() { return address; }
    public String getSymbol() { return symbol; }
    public String getBalance() { return balance; }
    public String getValueUsd() { return valueUsd; }
}

class Dao {
    private String id;
    private String name;
    private String description;
    private DaoType type;
    private String tokenAddress;
    private String governorAddress;
    private String timelockAddress;
    private DaoTreasury treasury;
    private String quorumPercent;
    private int votingPeriodDays;
    private int timelockDays;
    private int proposalCount;
    private int memberCount;
    private long createdAt;

    public String getId() { return id; }
    public String getName() { return name; }
    public String getDescription() { return description; }
    public DaoType getType() { return type; }
    public String getTokenAddress() { return tokenAddress; }
    public String getGovernorAddress() { return governorAddress; }
    public String getTimelockAddress() { return timelockAddress; }
    public DaoTreasury getTreasury() { return treasury; }
    public String getQuorumPercent() { return quorumPercent; }
    public int getVotingPeriodDays() { return votingPeriodDays; }
    public int getTimelockDays() { return timelockDays; }
    public int getProposalCount() { return proposalCount; }
    public int getMemberCount() { return memberCount; }
    public long getCreatedAt() { return createdAt; }
}

// ==================== Vesting Types ====================

class VestingSchedule {
    private String beneficiary;
    private String totalAmount;
    private long startTime;
    private long cliffDuration;
    private long vestingDuration;
    private boolean revocable;

    public String getBeneficiary() { return beneficiary; }
    public String getTotalAmount() { return totalAmount; }
    public long getStartTime() { return startTime; }
    public long getCliffDuration() { return cliffDuration; }
    public long getVestingDuration() { return vestingDuration; }
    public boolean isRevocable() { return revocable; }

    public void setBeneficiary(String beneficiary) { this.beneficiary = beneficiary; }
    public void setTotalAmount(String totalAmount) { this.totalAmount = totalAmount; }
    public void setStartTime(long startTime) { this.startTime = startTime; }
    public void setCliffDuration(long cliffDuration) { this.cliffDuration = cliffDuration; }
    public void setVestingDuration(long vestingDuration) { this.vestingDuration = vestingDuration; }
    public void setRevocable(boolean revocable) { this.revocable = revocable; }
}

class VestingContract {
    private String id;
    private String contractAddress;
    private String beneficiary;
    private String totalAmount;
    private String releasedAmount;
    private String releasableAmount;
    private long startTime;
    private long cliffEnd;
    private long vestingEnd;
    private VestingStatus status;
    private long createdAt;
    private String txHash;

    public String getId() { return id; }
    public String getContractAddress() { return contractAddress; }
    public String getBeneficiary() { return beneficiary; }
    public String getTotalAmount() { return totalAmount; }
    public String getReleasedAmount() { return releasedAmount; }
    public String getReleasableAmount() { return releasableAmount; }
    public long getStartTime() { return startTime; }
    public long getCliffEnd() { return cliffEnd; }
    public long getVestingEnd() { return vestingEnd; }
    public VestingStatus getStatus() { return status; }
    public long getCreatedAt() { return createdAt; }
    public String getTxHash() { return txHash; }
}

class ClaimReceipt {
    private String vestingContractId;
    private String amount;
    private String txHash;
    private long timestamp;
    private String remainingAmount;

    public String getVestingContractId() { return vestingContractId; }
    public String getAmount() { return amount; }
    public String getTxHash() { return txHash; }
    public long getTimestamp() { return timestamp; }
    public String getRemainingAmount() { return remainingAmount; }
}

// ==================== Error ====================

class GovernanceException extends RuntimeException {
    private final String code;
    private final int statusCode;

    public GovernanceException(String message) {
        super(message);
        this.code = null;
        this.statusCode = 0;
    }

    public GovernanceException(String message, String code, int statusCode) {
        super(message);
        this.code = code;
        this.statusCode = statusCode;
    }

    public String getCode() { return code; }
    public int getStatusCode() { return statusCode; }
}
