"""
Batch sizing + pacing helpers for g-gremlin integrations.
"""

from __future__ import annotations

import time
from dataclasses import dataclass
from typing import Iterable, Iterator, List, TypeVar

T = TypeVar("T")


@dataclass
class PacingProfile:
    name: str
    batch_size: int
    inter_batch_delay: float
    rate_limit_headroom: float


@dataclass
class AmplemarketPacingProfile:
    name: str
    leads_per_request: int
    inter_call_delay: float


SAFE_PROFILE = PacingProfile(
    name="safe",
    batch_size=50,
    inter_batch_delay=1.0,
    rate_limit_headroom=0.5,
)

TURBO_PROFILE = PacingProfile(
    name="turbo",
    batch_size=100,
    inter_batch_delay=0.1,
    rate_limit_headroom=0.9,
)


# ~24 calls/min
AMPLEMARKET_SAFE_PROFILE = AmplemarketPacingProfile(
    name="safe",
    leads_per_request=10,
    inter_call_delay=60.0 / 24.0,
)

# ~28 calls/min
AMPLEMARKET_TURBO_PROFILE = AmplemarketPacingProfile(
    name="turbo",
    leads_per_request=25,
    inter_call_delay=60.0 / 28.0,
)


def get_profile(name: str) -> PacingProfile:
    normalized = (name or "safe").strip().lower()
    if normalized == "turbo":
        return TURBO_PROFILE
    return SAFE_PROFILE


def get_hubspot_profile(name: str) -> PacingProfile:
    base = get_profile(name)
    return PacingProfile(
        name=base.name,
        batch_size=min(base.batch_size, 100),
        inter_batch_delay=base.inter_batch_delay,
        rate_limit_headroom=base.rate_limit_headroom,
    )


def get_outreach_profile(name: str) -> PacingProfile:
    return get_profile(name)


def get_amplemarket_profile(name: str) -> AmplemarketPacingProfile:
    normalized = (name or "safe").strip().lower()
    if normalized == "turbo":
        return AMPLEMARKET_TURBO_PROFILE
    return AMPLEMARKET_SAFE_PROFILE


class BatchPacer:
    def __init__(self, profile: PacingProfile) -> None:
        self.profile = profile
        self.is_downshifted = False

    def chunk(self, items: List[T], size: int | None = None) -> Iterator[List[T]]:
        batch_size = size or self.profile.batch_size
        for i in range(0, len(items), batch_size):
            yield items[i : i + batch_size]

    def pace(self) -> None:
        if self.profile.inter_batch_delay > 0:
            time.sleep(self.profile.inter_batch_delay)

    def downshift(self) -> None:
        if self.profile.name != SAFE_PROFILE.name:
            self.profile = SAFE_PROFILE
            self.is_downshifted = True
