// This file is auto-generated by @hey-api/openapi-ts

export type ClientOptions = {
    baseUrl: `${string}://${string}/publishers/seren-bounty` | (string & {});
};

/**
 * Attribute predicates support a small, fixed set of operators.
 * Intentionally kept narrow — extend only when a bounty actually needs it.
 */
export type AttributePredicate = {
    operator: PredicateOperator;
    /**
     * JSON path into `affiliate_events.attributes` (dotted, no array syntax).
     */
    path: string;
    value: unknown;
};

export type AttributionRule = {
    field: string;
    kind: 'referral_code';
} | {
    field: string;
    kind: 'wallet_address';
};

/**
 * Full bounty row.
 */
export type Bounty = {
    created_at: string;
    created_by_user_id: string;
    customer_slug: string;
    deadline?: string | null;
    description?: string | null;
    escrow_ref?: string | null;
    health_status: BountyHealth;
    hold_days: number;
    id: string;
    max_pool_atomic: number;
    organization_id: string;
    pool_remaining_atomic: number;
    status: BountyStatus;
    submission_instructions?: string | null;
    submission_mode: SubmissionMode;
    tiers: Array<Tier>;
    title: string;
    updated_at: string;
    verifier_failure_count: number;
    verifier_last_error?: string | null;
    verifier_last_success_at?: string | null;
    verifier_spec: {
        [key: string]: unknown;
    };
};

/**
 * `GET /bounties/{id}` full state.
 */
export type BountyDetail = Bounty & {
    earnings_count: number;
    progress: BountyProgress;
};

/**
 * Runtime health flag surfaced on `GET /bounties/{id}`.
 */
export type BountyHealth = 'healthy' | 'degraded' | 'failing';

export type BountyList = {
    bounties: Array<BountyListItem>;
    next_page_cursor?: string | null;
};

/**
 * Paginated bounty list entry (lighter than `BountyDetail`).
 */
export type BountyListItem = Bounty & {
    cumulative_qualifying_count: number;
    current_tier_index: number;
};

/**
 * Progress tracker row (1:1 with bounties).
 */
export type BountyProgress = {
    bounty_id: string;
    cumulative_qualifying_count: number;
    current_tier_index: number;
    last_event_at?: string | null;
    poll_cursor: {
        [key: string]: unknown;
    };
    updated_at: string;
};

/**
 * Per-bounty rollup.
 */
export type BountyStats = {
    bounty_id: string;
    clawed_back_count: number;
    created_at: string;
    cumulative_qualifying_count: number;
    current_tier_index: number;
    deadline?: string | null;
    earned_count: number;
    earner_count: number;
    earning_count: number;
    health_status: string;
    max_pool_atomic: number;
    paid_count: number;
    participant_count: number;
    pool_consumed_atomic: number;
    pool_remaining_atomic: number;
    released_count: number;
    status: string;
    title: string;
    total_clawed_back_atomic: number;
    total_earned_atomic: number;
    total_paid_atomic: number;
};

/**
 * Bounty lifecycle state. See spec §3.
 */
export type BountyStatus = 'draft' | 'funding' | 'open' | 'exhausted' | 'expired' | 'cancelled';

export type ClawbackRequest = {
    reason: string;
};

/**
 * Request body for `POST /bounties`.
 */
export type CreateBountyRequest = {
    customer_slug: string;
    deadline?: string | null;
    description?: string | null;
    hold_days: number;
    max_pool_atomic: number;
    submission_instructions?: string | null;
    submission_mode?: SubmissionMode;
    tiers: Array<Tier>;
    title: string;
    verifier_spec: VerifierSpec;
};

/**
 * Response for `POST /bounties`.
 */
export type CreateBountyResponse = Bounty & {
    /**
     * Address / escrow handle the customer deposits into via `POST /bounties/{id}/fund`.
     */
    funding_address: string;
};

/**
 * One day of activity.
 */
export type DailyActivity = {
    accrued_amount_atomic: number;
    accrued_count: number;
    /**
     * ISO-8601 date (YYYY-MM-DD), UTC.
     */
    date: string;
    paid_amount_atomic: number;
    paid_count: number;
};

export type Earning = {
    bounty_id: string;
    clawback_reason?: string | null;
    clawed_back_at?: string | null;
    earned_at: string;
    event_id: string;
    id: string;
    paid_at?: string | null;
    payout_due_at: string;
    payout_error?: string | null;
    payout_tx_ref?: string | null;
    released_at?: string | null;
    status: EarningStatus;
    tier_index: number;
    tier_rate_atomic: number;
    user_id: string;
};

/**
 * Earning lifecycle. `earned → released → paid` on the happy path,
 * `earned → clawed_back` otherwise.
 */
export type EarningStatus = 'earned' | 'released' | 'paid' | 'clawed_back';

export type EarningsList = {
    earnings: Array<Earning>;
    next_page_cursor?: string | null;
};

/**
 * Filter predicates evaluated against an `affiliate_events` row.
 */
export type EventMatch = {
    attributes?: Array<AttributePredicate>;
    event_type: string;
};

/**
 * Event-driven verifier: matches rows landing in `affiliate_events`.
 */
export type EventVerifierSpec = {
    /**
     * Customer namespace (must match `affiliate_events.customer_slug`).
     */
    customer_slug: string;
    /**
     * Event-match filter. `event_type` is required; `attributes` is a list
     * of predicates AND-ed together.
     */
    event_match: EventMatch;
};

/**
 * Request body for `POST /bounties/{id}/fund`.
 */
export type FundBountyRequest = {
    amount_atomic: number;
    idempotency_key?: string | null;
};

export type FundBountyResponse = {
    bounty_id: string;
    escrow_balance_atomic: number;
    payment_request_id: string;
    status: BountyStatus;
};

export type JoinBountyResponse = {
    bounty_id: string;
    joined_at: string;
    left_at?: string | null;
    referral_code: string;
    user_id: string;
};

/**
 * Ranking entry for the global leaderboard.
 */
export type LeaderboardEntry = {
    bounty_count: number;
    earning_count: number;
    last_earned_at?: string | null;
    total_earned_atomic: number;
    total_paid_atomic: number;
    user_id: string;
};

/**
 * Platform-wide rollup.
 */
export type Overview = {
    /**
     * Bounties that were cancelled.
     */
    cancelled_bounties: number;
    /**
     * Bounties that hit pool exhaustion.
     */
    exhausted_bounties: number;
    /**
     * Bounties that expired past their deadline.
     */
    expired_bounties: number;
    /**
     * Currently open bounties.
     */
    open_bounties: number;
    /**
     * Per-status rollup.
     */
    status_summary: Array<StatusSummary>;
    /**
     * Total bounties across all statuses.
     */
    total_bounties: number;
    /**
     * Total earnings that were clawed back.
     */
    total_clawed_back_atomic: number;
    /**
     * Total earning accruals, counted by status of `'earned' | 'released' | 'paid'`.
     */
    total_earned_atomic: number;
    /**
     * Distinct users who have earned something in any bounty.
     */
    total_earners: number;
    /**
     * Total earnings in `'paid'` status.
     */
    total_paid_atomic: number;
    /**
     * Distinct users who have ever joined any bounty.
     */
    total_participants: number;
    /**
     * Sum of `max_pool_atomic` across all bounties.
     */
    total_pool_max_atomic: number;
    /**
     * Sum of remaining pool capacity across bounties that are still open.
     */
    total_pool_remaining_atomic: number;
};

export type Participant = {
    bounty_id: string;
    joined_at: string;
    left_at?: string | null;
    referral_code: string;
    user_id: string;
};

/**
 * Request body for `PATCH /bounties/{id}`.
 */
export type PatchBountyRequest = {
    /**
     * Additional atomic SerenBucks to add to the pool. Requires separate
     * escrow top-up via `POST /bounties/{id}/fund` to be credited.
     */
    additional_max_pool_atomic?: number | null;
    deadline?: string | null;
    submission_instructions?: string | null;
    submission_mode?: null | SubmissionMode;
    tiers?: Array<Tier> | null;
};

export type PollPredicate = {
    /**
     * Per-item filters (AND-ed together).
     */
    filters?: Array<AttributePredicate>;
    /**
     * JSON path into the response body that yields the iterable match set.
     */
    items_path: string;
};

/**
 * Poll-driven verifier: calls a publisher every `cadence_seconds` and
 * evaluates a predicate over the response body.
 */
export type PollVerifierSpec = {
    /**
     * How to turn a matching response item into a bounty participant `user_id`.
     */
    attribution_rule: AttributionRule;
    /**
     * Schedule cadence. Bounded to `[60, 86400]` seconds by validation.
     */
    cadence_seconds: number;
    /**
     * Predicate evaluated against each item in the publisher response.
     */
    predicate: PollPredicate;
    /**
     * Seren publisher slug (validated against a supported-publisher list).
     */
    publisher: string;
    /**
     * HTTP request template. `{{cursor}}` is the only supported
     * interpolation for this service.
     */
    request_template: RequestTemplate;
};

export type PredicateOperator = 'eq' | 'not_eq' | 'gt' | 'gte' | 'lt' | 'lte' | 'in' | 'contains';

export type RequestTemplate = {
    body?: unknown;
    method: string;
    path: string;
    query?: Array<[
        string,
        string
    ]>;
};

/**
 * Per-status rollup entry.
 */
export type StatusSummary = {
    count: number;
    status: string;
    total_pool_max_atomic: number;
    total_pool_remaining_atomic: number;
};

export type Submission = {
    attachment?: null | SubmissionAttachment;
    bounty_id: string;
    content_prosemirror: {
        [key: string]: unknown;
    };
    content_text: string;
    created_at: string;
    id: string;
    status: SubmissionStatus;
    updated_at: string;
    user_id: string;
};

export type SubmissionAttachment = {
    content_type: string;
    created_at: string;
    filename: string;
    id: string;
    size_bytes: number;
    submission_id: string;
    updated_at: string;
};

export type SubmissionAttachmentInput = {
    content_type: string;
    /**
     * Base64-encoded attachment bytes.
     */
    data_base64: string;
    filename: string;
};

export type SubmissionList = {
    submissions: Array<Submission>;
};

export type SubmissionMode = 'disabled' | 'optional' | 'required';

export type SubmissionStatus = 'submitted' | 'withdrawn';

/**
 * A reward tier: when `cumulative_qualifying_count` crosses `threshold`, any
 * subsequent earnings accrue at `rate_atomic` (frozen at accrual time onto
 * `bounty_earnings.tier_rate_atomic`).
 */
export type Tier = {
    rate_atomic: number;
    threshold: number;
};

export type UpsertSubmissionRequest = {
    attachment?: null | SubmissionAttachmentInput;
    content_prosemirror?: {
        [key: string]: unknown;
    } | null;
    content_text?: string | null;
    remove_attachment?: boolean;
};

/**
 * Per-user rollup.
 */
export type UserStats = {
    bounty_count: number;
    clawed_back_count: number;
    earned_count: number;
    earning_count: number;
    first_earned_at?: string | null;
    joined_bounty_count: number;
    last_earned_at?: string | null;
    paid_count: number;
    released_count: number;
    total_clawed_back_atomic: number;
    total_earned_atomic: number;
    total_paid_atomic: number;
    user_id: string;
};

/**
 * The two verifier flavors. `event` is webhook-driven (affiliate_events);
 * `poll` calls a seren publisher on a cadence.
 */
export type VerifierSpec = (EventVerifierSpec & {
    type: 'event';
}) | (PollVerifierSpec & {
    type: 'poll';
});

export type ListBountiesData = {
    body?: never;
    path?: never;
    query?: {
        status?: null | BountyStatus;
        customer_slug?: string | null;
        limit?: number | null;
        cursor?: string | null;
    };
    url: '/bounties';
};

export type ListBountiesResponses = {
    /**
     * Public bounty list
     */
    200: BountyList;
};

export type ListBountiesResponse = ListBountiesResponses[keyof ListBountiesResponses];

export type CreateBountyData = {
    body: CreateBountyRequest;
    path?: never;
    query?: never;
    url: '/bounties';
};

export type CreateBountyErrors = {
    /**
     * Invalid request
     */
    400: unknown;
};

export type CreateBountyResponses = {
    /**
     * Bounty created
     */
    201: CreateBountyResponse;
};

export type CreateBountyResponse2 = CreateBountyResponses[keyof CreateBountyResponses];

export type GetBountyData = {
    body?: never;
    path: {
        /**
         * Bounty id
         */
        id: string;
    };
    query?: never;
    url: '/bounties/{id}';
};

export type GetBountyResponses = {
    /**
     * Bounty detail
     */
    200: BountyDetail;
};

export type GetBountyResponse = GetBountyResponses[keyof GetBountyResponses];

export type PatchBountyData = {
    body: PatchBountyRequest;
    path: {
        /**
         * Bounty id
         */
        id: string;
    };
    query?: never;
    url: '/bounties/{id}';
};

export type PatchBountyResponses = {
    /**
     * Bounty patched
     */
    200: Bounty;
};

export type PatchBountyResponse = PatchBountyResponses[keyof PatchBountyResponses];

export type CancelBountyData = {
    body?: never;
    path: {
        /**
         * Bounty id
         */
        id: string;
    };
    query?: never;
    url: '/bounties/{id}/cancel';
};

export type CancelBountyResponses = {
    /**
     * Bounty cancelled
     */
    200: Bounty;
};

export type CancelBountyResponse = CancelBountyResponses[keyof CancelBountyResponses];

export type ListBountyEarningsData = {
    body?: never;
    path: {
        /**
         * Bounty id
         */
        id: string;
    };
    query?: {
        status?: null | EarningStatus;
        user_id?: string | null;
        since?: string | null;
        limit?: number | null;
        cursor?: string | null;
    };
    url: '/bounties/{id}/earnings';
};

export type ListBountyEarningsResponses = {
    /**
     * Earnings list
     */
    200: EarningsList;
};

export type ListBountyEarningsResponse = ListBountyEarningsResponses[keyof ListBountyEarningsResponses];

export type ClawbackEarningData = {
    body: ClawbackRequest;
    path: {
        /**
         * Bounty id
         */
        id: string;
        /**
         * Earning id
         */
        earning_id: string;
    };
    query?: never;
    url: '/bounties/{id}/earnings/{earning_id}/clawback';
};

export type ClawbackEarningResponses = {
    /**
     * Clawback applied
     */
    200: Earning;
};

export type ClawbackEarningResponse = ClawbackEarningResponses[keyof ClawbackEarningResponses];

export type FundBountyData = {
    body: FundBountyRequest;
    path: {
        /**
         * Bounty id
         */
        id: string;
    };
    query?: never;
    url: '/bounties/{id}/fund';
};

export type FundBountyResponses = {
    /**
     * Funding applied
     */
    200: FundBountyResponse;
};

export type FundBountyResponse2 = FundBountyResponses[keyof FundBountyResponses];

export type LeaveBountyData = {
    body?: never;
    path: {
        /**
         * Bounty id
         */
        id: string;
    };
    query?: never;
    url: '/bounties/{id}/join';
};

export type LeaveBountyResponses = {
    /**
     * Left bounty
     */
    204: void;
};

export type LeaveBountyResponse = LeaveBountyResponses[keyof LeaveBountyResponses];

export type JoinBountyData = {
    body?: never;
    path: {
        /**
         * Bounty id
         */
        id: string;
    };
    query?: never;
    url: '/bounties/{id}/join';
};

export type JoinBountyResponses = {
    /**
     * Join result
     */
    200: JoinBountyResponse;
};

export type JoinBountyResponse2 = JoinBountyResponses[keyof JoinBountyResponses];

export type GetBountyLeaderboardData = {
    body?: never;
    path: {
        /**
         * Bounty id
         */
        id: string;
    };
    query?: {
        sort_by?: string | null;
        limit?: number | null;
        offset?: number | null;
    };
    url: '/bounties/{id}/leaderboard';
};

export type GetBountyLeaderboardResponses = {
    /**
     * Leaderboard entries
     */
    200: Array<LeaderboardEntry>;
};

export type GetBountyLeaderboardResponse = GetBountyLeaderboardResponses[keyof GetBountyLeaderboardResponses];

export type GetBountyStatsData = {
    body?: never;
    path: {
        /**
         * Bounty id
         */
        id: string;
    };
    query?: never;
    url: '/bounties/{id}/stats';
};

export type GetBountyStatsErrors = {
    /**
     * Bounty not found
     */
    404: unknown;
};

export type GetBountyStatsResponses = {
    /**
     * Bounty rollup
     */
    200: BountyStats;
};

export type GetBountyStatsResponse = GetBountyStatsResponses[keyof GetBountyStatsResponses];

export type WithdrawMySubmissionData = {
    body?: never;
    path: {
        /**
         * Bounty id
         */
        id: string;
    };
    query?: never;
    url: '/bounties/{id}/submission';
};

export type WithdrawMySubmissionResponses = {
    /**
     * Submission withdrawn
     */
    204: void;
};

export type WithdrawMySubmissionResponse = WithdrawMySubmissionResponses[keyof WithdrawMySubmissionResponses];

export type GetMySubmissionData = {
    body?: never;
    path: {
        /**
         * Bounty id
         */
        id: string;
    };
    query?: never;
    url: '/bounties/{id}/submission';
};

export type GetMySubmissionResponses = {
    /**
     * Submission detail
     */
    200: Submission;
};

export type GetMySubmissionResponse = GetMySubmissionResponses[keyof GetMySubmissionResponses];

export type UpsertMySubmissionData = {
    body: UpsertSubmissionRequest;
    path: {
        /**
         * Bounty id
         */
        id: string;
    };
    query?: never;
    url: '/bounties/{id}/submission';
};

export type UpsertMySubmissionResponses = {
    /**
     * Submission upserted
     */
    200: Submission;
};

export type UpsertMySubmissionResponse = UpsertMySubmissionResponses[keyof UpsertMySubmissionResponses];

export type ListBountySubmissionsData = {
    body?: never;
    path: {
        /**
         * Bounty id
         */
        id: string;
    };
    query?: {
        status?: null | SubmissionStatus;
        user_id?: string | null;
        limit?: number | null;
    };
    url: '/bounties/{id}/submissions';
};

export type ListBountySubmissionsResponses = {
    /**
     * Submission list
     */
    200: SubmissionList;
};

export type ListBountySubmissionsResponse = ListBountySubmissionsResponses[keyof ListBountySubmissionsResponses];

export type GetBountySubmissionData = {
    body?: never;
    path: {
        /**
         * Bounty id
         */
        id: string;
        /**
         * Submission id
         */
        submission_id: string;
    };
    query?: never;
    url: '/bounties/{id}/submissions/{submission_id}';
};

export type GetBountySubmissionResponses = {
    /**
     * Submission detail
     */
    200: Submission;
};

export type GetBountySubmissionResponse = GetBountySubmissionResponses[keyof GetBountySubmissionResponses];

export type DownloadSubmissionAttachmentData = {
    body?: never;
    path: {
        /**
         * Bounty id
         */
        id: string;
        /**
         * Submission id
         */
        submission_id: string;
    };
    query?: never;
    url: '/bounties/{id}/submissions/{submission_id}/attachment';
};

export type DownloadSubmissionAttachmentResponses = {
    /**
     * Attachment binary
     */
    200: unknown;
};

export type GetLeaderboardData = {
    body?: never;
    path?: never;
    query?: {
        sort_by?: string | null;
        limit?: number | null;
        offset?: number | null;
    };
    url: '/leaderboard';
};

export type GetLeaderboardResponses = {
    /**
     * Leaderboard entries
     */
    200: Array<LeaderboardEntry>;
};

export type GetLeaderboardResponse = GetLeaderboardResponses[keyof GetLeaderboardResponses];

export type ListOrganizationBountiesData = {
    body?: never;
    path?: never;
    query?: {
        status?: null | BountyStatus;
        customer_slug?: string | null;
        limit?: number | null;
        cursor?: string | null;
    };
    url: '/organizations/me/bounties';
};

export type ListOrganizationBountiesResponses = {
    /**
     * Bounty list
     */
    200: BountyList;
};

export type ListOrganizationBountiesResponse = ListOrganizationBountiesResponses[keyof ListOrganizationBountiesResponses];

export type GetOverviewData = {
    body?: never;
    path?: never;
    query?: never;
    url: '/overview';
};

export type GetOverviewResponses = {
    /**
     * Platform overview
     */
    200: Overview;
};

export type GetOverviewResponse = GetOverviewResponses[keyof GetOverviewResponses];

export type GetDailyActivityData = {
    body?: never;
    path?: never;
    query?: {
        /**
         * Number of days to return, counting back from today. Default 30, max 365.
         */
        days?: number | null;
    };
    url: '/stats/daily';
};

export type GetDailyActivityResponses = {
    /**
     * Daily activity
     */
    200: Array<DailyActivity>;
};

export type GetDailyActivityResponse = GetDailyActivityResponses[keyof GetDailyActivityResponses];

export type ListMyEarningsData = {
    body?: never;
    path?: never;
    query?: {
        status?: null | EarningStatus;
        bounty_id?: string | null;
        limit?: number | null;
    };
    url: '/users/me/earnings';
};

export type ListMyEarningsResponses = {
    /**
     * Earnings list
     */
    200: EarningsList;
};

export type ListMyEarningsResponse = ListMyEarningsResponses[keyof ListMyEarningsResponses];

export type GetMyUserStatsData = {
    body?: never;
    path?: never;
    query?: never;
    url: '/users/me/stats';
};

export type GetMyUserStatsResponses = {
    /**
     * User rollup
     */
    200: UserStats;
};

export type GetMyUserStatsResponse = GetMyUserStatsResponses[keyof GetMyUserStatsResponses];

export type GetUserStatsData = {
    body?: never;
    path: {
        /**
         * User id
         */
        user_id: string;
    };
    query?: never;
    url: '/users/{user_id}/stats';
};

export type GetUserStatsResponses = {
    /**
     * User rollup
     */
    200: UserStats;
};

export type GetUserStatsResponse = GetUserStatsResponses[keyof GetUserStatsResponses];
