namespace Synor.Sdk.Governance;

public enum ProposalStatus { Pending, Active, Passed, Rejected, Executed, Cancelled }
public enum VoteChoice { For, Against, Abstain }
public enum DaoType { Token, Multisig, Hybrid }
public enum VestingStatus { Active, Completed, Revoked }

public record GovernanceConfig(
    string ApiKey,
    string Endpoint = "https://governance.synor.io/v1",
    TimeSpan? Timeout = null,
    int Retries = 3,
    bool Debug = false
) {
    public TimeSpan Timeout { get; init; } = Timeout ?? TimeSpan.FromSeconds(30);
}

public record ProposalAction(
    string Target,
    string Method,
    string Data,
    string? Value = null
);

public record ProposalDraft(
    string Title,
    string Description,
    string? DiscussionUrl = null,
    long? VotingStartTime = null,
    long? VotingEndTime = null,
    string? DaoId = null,
    List<ProposalAction>? Actions = null
);

public record VoteTally(
    string ForVotes,
    string AgainstVotes,
    string AbstainVotes,
    string Quorum,
    string QuorumRequired,
    int TotalVoters
);

public record Proposal(
    string Id,
    string Title,
    string Description,
    string? DiscussionUrl,
    string Proposer,
    ProposalStatus Status,
    long CreatedAt,
    long VotingStartTime,
    long VotingEndTime,
    long? ExecutionTime,
    VoteTally VoteTally,
    List<ProposalAction> Actions,
    string? DaoId = null
);

public record ProposalFilter(
    ProposalStatus? Status = null,
    string? Proposer = null,
    string? DaoId = null,
    int? Limit = null,
    int? Offset = null
);

public record Vote(VoteChoice Choice, string? Reason = null);

public record VoteReceipt(
    string Id,
    string ProposalId,
    string Voter,
    VoteChoice Choice,
    string Weight,
    string? Reason,
    long VotedAt,
    string TxHash
);

public record VotingPower(
    string Address,
    string DelegatedPower,
    string OwnPower,
    string TotalPower,
    List<string> Delegators
);

public record DelegationReceipt(
    string Id,
    string From,
    string To,
    string Amount,
    long DelegatedAt,
    string TxHash
);

public record DaoConfig(
    string Name,
    string Description,
    DaoType Type,
    int VotingPeriodDays,
    int TimelockDays,
    string? TokenAddress = null,
    double? QuorumPercent = null,
    string? ProposalThreshold = null,
    List<string>? MultisigMembers = null,
    int? MultisigThreshold = null
);

public record Dao(
    string Id,
    string Name,
    string Description,
    DaoType Type,
    string? TokenAddress,
    int VotingPeriodDays,
    int TimelockDays,
    double QuorumPercent,
    string ProposalThreshold,
    int TotalProposals,
    int ActiveProposals,
    string TreasuryValue,
    int MemberCount,
    long CreatedAt
);

public record TreasuryToken(
    string Address,
    string Balance,
    string Name,
    string Symbol
);

public record DaoTreasury(
    string DaoId,
    string TotalValue,
    List<TreasuryToken> Tokens,
    long LastUpdated
);

public record VestingSchedule(
    string Beneficiary,
    string TotalAmount,
    long StartTime,
    long CliffDuration,
    long VestingDuration,
    bool Revocable
);

public record VestingContract(
    string Id,
    string Beneficiary,
    string Grantor,
    string TotalAmount,
    string ReleasedAmount,
    string ReleasableAmount,
    long StartTime,
    long CliffTime,
    long EndTime,
    VestingStatus Status,
    bool Revocable,
    long CreatedAt
);

public record ClaimReceipt(
    string Id,
    string ContractId,
    string Amount,
    string TxHash,
    long ClaimedAt
);

// Response wrappers
internal record ProposalsResponse(List<Proposal>? Proposals);
internal record VotesResponse(List<VoteReceipt>? Votes);
internal record DaosResponse(List<Dao>? Daos);
internal record MembersResponse(List<string>? Members);
internal record DelegationsResponse(List<DelegationReceipt>? Delegations);
internal record VestingContractsResponse(List<VestingContract>? Contracts);
internal record ReleasableResponse(string Amount);
internal record GovernanceHealthResponse(string Status);

public class GovernanceException : Exception
{
    public string? Code { get; }
    public int StatusCode { get; }

    public GovernanceException(string message, string? code = null, int statusCode = 0)
        : base(message)
    {
        Code = code;
        StatusCode = statusCode;
    }
}
