"""Base collector for CrowdStrike."""

import json
import logging
import time
from datetime import datetime, timedelta, timezone

from ..client import CrowdStrikeClient
from ..constants import BASE_SENSOR_REPO, DAY_WINDOW_SIZE, DELAY_BETWEEN_WINDOWS, QUERY_TAIL_LIMIT

logger = logging.getLogger(__name__)


class CrowdStrikeBaseCollector:
    """Base class for CrowdStrike event collectors."""

    def __init__(
        self,
        client: CrowdStrikeClient,
        query_string: str,
        event_type_name: str,
        days_back: int,
        repository: str = BASE_SENSOR_REPO,
    ):
        self.client = client
        self.query_string = query_string
        self.event_type_name = event_type_name
        self.repository = repository
        self.days_back = days_back

    def collect_events(self) -> list[str]:
        """Collect events across time windows, paginating within each.

        Returns:
            List of JSON-serialized events
        """
        now = datetime.now(timezone.utc)
        num_windows = (self.days_back + DAY_WINDOW_SIZE - 1) // DAY_WINDOW_SIZE
        logger.info(
            f"Starting {self.event_type_name} collection: "
            f"{self.days_back} days in {num_windows} windows of {DAY_WINDOW_SIZE} days"
        )

        events: list[str] = []

        for window_idx in range(num_windows):
            end = now - timedelta(days=window_idx * DAY_WINDOW_SIZE)
            start = end - timedelta(days=DAY_WINDOW_SIZE)
            start_ts = int(start.timestamp() * 1000)
            end_ts = int(end.timestamp() * 1000)

            logger.info(f"Window {window_idx + 1}/{num_windows} ({start.date()} to {end.date()})")

            try:
                count = 0
                for event in self.client.search(
                    query=self.query_string,
                    start_ts=start_ts,
                    end_ts=end_ts,
                    repo=self.repository,
                ):
                    events.append(json.dumps(event))
                    count += 1
                if count:
                    logger.info(f"  Collected {count} events")
                if count >= QUERY_TAIL_LIMIT:
                    logger.warning(
                        f"  Window returned {count} events (limit: {QUERY_TAIL_LIMIT}). "
                        "Results may be truncated -- consider reducing --days-back."
                    )
            except Exception as e:
                logger.warning(f"  Window failed: {e}")

            if window_idx < num_windows - 1:
                time.sleep(DELAY_BETWEEN_WINDOWS)

        logger.info(f"Total: {len(events)} {self.event_type_name} events")
        return events
