from __future__ import annotations

import logging
import sys
from collections.abc import Hashable, Iterable, Sequence
from typing import TypeVar

T = TypeVar('T', bound=Hashable)


class _OperatorOutputHandler(logging.Handler):
    """Write operator-facing messages to the current stdout stream."""

    def emit(self, record: logging.LogRecord) -> None:
        try:
            sys.stdout.write(f'{self.format(record)}\n')
            sys.stdout.flush()
        except Exception:
            self.handleError(record)


output_logger = logging.getLogger('theHarvester.output')


def configure_logging(*, verbose: bool) -> None:
    """Configure CLI diagnostics without taking ownership from an embedding host."""
    if not any(isinstance(handler, _OperatorOutputHandler) for handler in output_logger.handlers):
        output_logger.addHandler(_OperatorOutputHandler())
    output_logger.setLevel(logging.INFO)
    output_logger.propagate = False

    root_logger = logging.getLogger()
    if not root_logger.handlers:
        handler = logging.StreamHandler()
        handler.setFormatter(logging.Formatter('%(levelname)s %(name)s: %(message)s'))
        root_logger.addHandler(handler)
        root_logger.setLevel(logging.WARNING)

    package_logger = logging.getLogger('theHarvester')
    logger_state = package_logger.__dict__
    if verbose and package_logger.level != logging.INFO:
        logger_state.setdefault('_theharvester_level_before_verbose', package_logger.level)
        package_logger.setLevel(logging.INFO)
    elif not verbose and '_theharvester_level_before_verbose' in logger_state:
        previous_level = logger_state.pop('_theharvester_level_before_verbose')
        if package_logger.level == logging.INFO:
            package_logger.setLevel(previous_level)


def sorted_unique[T: Hashable](items: Iterable[T]) -> list[T]:
    unique_items = list(dict.fromkeys(items))
    unique_items.sort(key=lambda item: str(item))
    return unique_items


def print_section(header: str, items: Iterable[str], separator: str) -> None:
    output_logger.info(header)
    output_logger.info(separator)
    for item in sorted_unique(items):
        output_logger.info(item)


def print_linkedin_people(engines: Sequence[str], people: Sequence[str], separator: str = '---------------------') -> None:
    if len(people) == 0 and 'linkedin' in engines:
        output_logger.info('\n[*] No LinkedIn users found.\n\n')
    elif len(people) >= 1:
        output_logger.info(f'\n[*] LinkedIn Users found: {len(people)}')
        output_logger.info(separator)
        for usr in sorted_unique(people):
            output_logger.info(usr)
