import type { VenueEventWithMarkets, VenueMarket } from "@agg-build/hooks";
export declare const SPORTS_SECTION_TAB_KEYS: readonly ["game_lines", "halves", "exact_score", "corners", "goals", "assists", "shots", "other"];
export type SportsSectionTabKey = (typeof SPORTS_SECTION_TAB_KEYS)[number];
export declare const SPORTS_MARKET_TYPE_KEYS: readonly ["to_advance", "moneyline", "spread", "total", "prop", "completion", "other"];
export type SportsMarketTypeKey = (typeof SPORTS_MARKET_TYPE_KEYS)[number];
export declare const SPORTS_PERIOD_KEYS: readonly ["full", "1h", "2h", "q1", "q2", "q3", "q4", "ot", "first_inning", "second_inning", "third_inning", "first_5_innings", "other"];
/**
 * Known named periods plus the documented open grammar (`set_N`, `map_N`,
 * `game_N`, `period_N`, `inning_N`, `first_N_innings` — see the sports
 * recipe's period vocabulary). Grammar tokens pass through verbatim so
 * tennis sets / esports maps / hockey periods group under their own named
 * period instead of collapsing into "other" (prod 2026-07: set_1 ×1,741,
 * inning_1 ×144 were all landing in the Other bucket).
 */
export type SportsPeriodKey = (typeof SPORTS_PERIOD_KEYS)[number] | (string & {});
export declare const SPORTS_MARKET_CATEGORY_KEYS: readonly ["game_lines", "exact_score", "corners", "goals", "assists", "shots", "other"];
export type SportsMarketCategoryKey = (typeof SPORTS_MARKET_CATEGORY_KEYS)[number];
export declare const SPORTS_MARKET_GROUP_KEYS: readonly ["game_lines", "spreads", "totals", "period_lines", "exact_score", "team_props", "player_props", "specials", "completion", "other"];
export type SportsMarketGroupKey = (typeof SPORTS_MARKET_GROUP_KEYS)[number];
export type SportsSectionTabDefinition = {
    key: SportsSectionTabKey;
    /** Preferred section filter — supersedes `marketCategory`. */
    marketGroup?: readonly SportsMarketGroupKey[];
    /** Legacy compatibility filter (soccer prop tabs without a marketGroup). */
    marketCategory?: SportsMarketCategoryKey;
    sportsMarketType?: readonly SportsMarketTypeKey[];
    period?: readonly SportsPeriodKey[];
};
export declare const SPORTS_SECTION_TAB_DEFINITIONS: readonly [{
    readonly key: "game_lines";
    readonly marketGroup: readonly ["game_lines", "spreads", "totals"];
}, {
    readonly key: "exact_score";
    readonly marketGroup: readonly ["exact_score"];
}, {
    readonly key: "halves";
    readonly marketGroup: readonly ["period_lines"];
    readonly period: readonly ["1h", "2h"];
}, {
    readonly key: "corners";
    readonly marketCategory: "corners";
}, {
    readonly key: "goals";
    readonly marketCategory: "goals";
}, {
    readonly key: "assists";
    readonly marketCategory: "assists";
}, {
    readonly key: "shots";
    readonly marketCategory: "shots";
}, {
    readonly key: "other";
    readonly marketGroup: readonly ["other", "team_props", "specials", "completion"];
}];
export type SportsMarketCardVariant = "outcome" | "line" | "yes_no";
export type SportsMarketDisplayGroup = {
    id: string;
    title: string;
    questionKey: string;
    sportsMarketType: SportsMarketTypeKey | null;
    marketCategory: SportsMarketCategoryKey | null;
    period: SportsPeriodKey;
    sectionRank: number;
    markets: VenueMarket[];
    hasLineVariants: boolean;
};
export type SportsPeriodGroup = {
    key: SportsPeriodKey;
    markets: VenueMarket[];
    groups: SportsMarketDisplayGroup[];
};
export declare const resolveSportsSectionDefinition: (key: SportsSectionTabKey) => SportsSectionTabDefinition;
export declare const normalizeSportsPeriod: (value: string | null | undefined) => SportsPeriodKey;
export declare const normalizeSportsMarketType: (value: string | null | undefined) => SportsMarketTypeKey | null;
export declare const normalizeSportsMarketCategory: (value: string | null | undefined) => SportsMarketCategoryKey | null;
export declare const normalizeSportsMarketGroup: (value: string | null | undefined) => SportsMarketGroupKey | null;
/**
 * Map a market to the sports section tab it belongs to — marketGroup-first, with
 * marketCategory as the documented compatibility fallback (see the
 * sports-market-detail recipe). Returns null when a market carries no
 * recognizable grouping metadata, so the page can fall back to the default,
 * ungrouped market list instead of inventing an empty tab.
 */
export declare const resolveMarketSectionTabKey: (market: Pick<VenueMarket, "marketGroup" | "marketCategory" | "marketSubtype" | "question" | "sportsMarketType">) => SportsSectionTabKey | null;
export declare const resolveSportsSectionFilters: (key: SportsSectionTabKey) => {
    marketGroup?: SportsMarketGroupKey[];
    marketCategory?: SportsMarketCategoryKey[];
    sportsMarketType?: SportsMarketTypeKey[];
    period?: SportsPeriodKey[];
};
/**
 * Resolve the markets a sports section tab should display and group.
 *
 * Section markets are fetched by `aggKey`, which intentionally spans every
 * sibling venue-event for the same real-world game (so cross-venue line ladders
 * and prop categories aggregate together). For the Game Lines MONEYLINE
 * (match-result) group, that aggregation is wrong: it can surface duplicate
 * draws sourced from sibling events, props mis-classified as `moneyline`, and —
 * because a sibling's market often wins the cross-venue collapse — it can omit
 * THIS event's own outcome markets entirely (e.g. show two "Draw"s and drop the
 * "Australia" win).
 *
 * The event's own curated `venueMarkets` are the authoritative N-way result for
 * this event (the same source the non-sports event page renders correctly). So
 * on the Game Lines tab we take the moneyline markets from the event and keep
 * only the line markets (spread/total) from the aggKey fetch. Every other tab —
 * and the spread/total ladders within Game Lines — use the fetched markets
 * unchanged.
 */
export declare const resolveSportsSectionMarkets: ({ tabKey, eventMarkets, sectionMarkets, }: {
    tabKey: SportsSectionTabKey;
    eventMarkets: VenueMarket[];
    sectionMarkets: VenueMarket[];
}) => VenueMarket[];
export declare const resolveSportsMarketCardVariant: (market: VenueMarket) => SportsMarketCardVariant;
export declare const isBinarySportsMoneylineMarket: (market: VenueMarket) => boolean;
export declare const isSpreadTeamTitle: (title: string | null | undefined) => boolean;
/**
 * Resolve favored/dog team display names for a spread market's two outcomes,
 * consistent across whichever venue anchors the ladder stop.
 *
 * A kalshi/limitless anchor stores `Yes`/`No` labels with no clean team title,
 * so the pill would read "Yes +1.5". But the same signed line has cross-venue
 * twins (identical `_sp_{fav}_{line}` aggKey) from poly/predict that DO carry the
 * team name as the outcome title. Outcome index 0 is the favored side (covers
 * the spread) on every venue keyed `_sp_{fav}`. So borrow the fullest clean
 * title at each index. Returns `null` for a side when no twin has a team title
 * (→ caller falls back to the raw `Yes`/`No` label). Null-aggKey spreads can't
 * be matched to twins, so only the market's own titles are considered.
 */
export declare const resolveSpreadOutcomeTeamNames: (activeMarket: VenueMarket, groupMarkets: VenueMarket[]) => {
    favored: string | null;
    dog: string | null;
};
/** The per-leg pill label for a combined (decomposed) moneyline group. */
export declare const resolveCombinedMoneylineLegLabel: (market: VenueMarket) => string;
/**
 * Combined per-leg moneyline pills are only meaningful when every leg carries a
 * DISTINCT label. Cross-venue duplicates of the SAME 2-way single that never
 * merged (e.g. poly + predict "… (BO5) - Match Winner") collapse to identical
 * labels — rendering them as separate pills shows the same Yes price twice as
 * if it were two different options. Non-distinct → the card falls back to the
 * standard single-market rendering (team-title pills).
 */
export declare const areCombinedMoneylineLegsDistinct: (markets: VenueMarket[]) => boolean;
export declare const buildSportsMarketDisplayGroups: (markets: VenueMarket[]) => SportsMarketDisplayGroup[];
export declare const groupSportsMarketsByPeriod: (markets: VenueMarket[]) => SportsPeriodGroup[];
export type SportsGameLineSlideKind = "to_advance" | "moneyline" | "spread" | "total" | "other";
export type SportsGameLineSlideStop = {
    /** Display value for the ladder chip, e.g. "1.5", "216.5". */
    value: string;
    /** Venue ids offering this line (cast to VenueLogoName at the render site). */
    venues: string[];
    market: VenueMarket;
};
export type SportsGameLineSlide = {
    id: string;
    kind: SportsGameLineSlideKind;
    group: SportsMarketDisplayGroup;
    /** False for moneyline / single-market groups → no line ladder. */
    hasLadder: boolean;
    stops: SportsGameLineSlideStop[];
    /** Marquee line on first render — the highest-volume line in the group. */
    defaultStopIndex: number;
};
export declare const resolveSelectedSportsLineValue: (lineValue: number | null | undefined) => string;
export declare const collectVenueNames: (market: VenueMarket) => string[];
export declare const resolveTotalGroupVolume: (markets: VenueMarket[]) => number;
export declare const resolveSportsExpandedMarkets: (markets: VenueMarket[]) => VenueMarket[];
export declare const resolveSportsExpandedMarketsVolume: (markets: VenueMarket[]) => number;
export declare const buildSportsSlideFromGroup: (group: SportsMarketDisplayGroup) => SportsGameLineSlide;
/**
 * Derive the Moneyline / Spreads / Total game-line slides (in that order) from a
 * flat list of venue markets. Reuses {@link buildSportsMarketDisplayGroups} so
 * line variants collapse into one slide with the per-line ladder.
 */
export declare const buildSportsGameLineSlides: (markets: VenueMarket[], period?: SportsPeriodKey) => SportsGameLineSlide[];
export type SportsTeam = {
    name: string;
    abbr: string;
};
export type SportsTeams = {
    away: SportsTeam;
    home: SportsTeam;
};
export declare const resolveSportsTeams: (event: Pick<VenueEventWithMarkets, "title">, moneylineMarket?: VenueMarket | null) => SportsTeams | null;
export declare const resolveSportsLeagueLabel: (event: Pick<VenueEventWithMarkets, "categories" | "aggKey">) => string | null;
/**
 * Human label for an open-grammar period token (`set_2` → "Set 2",
 * `inning_4` → "Inning 4", `first_5_innings` → "First 5 Innings").
 * Returns null for anything outside the documented grammar.
 */
export declare const formatSportsPeriodGrammarLabel: (period: string) => string | null;
export declare const isNonStandardSportsLikeEvent: (event: Pick<VenueEventWithMarkets, "categories" | "title" | "venueMarkets">) => boolean;
export declare const resolveVisibleSportsSectionTabDefinitions: (event: Pick<VenueEventWithMarkets, "categories" | "title" | "venueMarkets">) => SportsSectionTabDefinition[];
export declare const mergeSportsSectionMarketsIntoEvent: ({ event, sectionMarketsByKey, }: {
    event: import("@agg-build/hooks").VenueEventWithMarkets;
    sectionMarketsByKey: Partial<Record<SportsSectionTabKey, VenueMarket[]>>;
}) => import("@agg-build/hooks").VenueEventWithMarkets;
