from typing import List, Optional, Dict
import logging
from ..interfaces import MetricProvider
from ..utils import convert_tags, get_logger


class ConsoleProvider(MetricProvider):
    def __init__(
        self,
        logger: Optional[logging.Logger] = None
    ):
        self.logger = logger or get_logger(__name__)

    def _format_tags(self, tags: Optional[Dict[str, str]]) -> str:
        if not tags:
            return ""
        return f" | Tags: {convert_tags(tags)}"

    def _log(self, type_name: str, content: str):
        self.logger.info(f"[CONSOLE] [{type_name.upper()}] {content}")

    def send(self, *args, **kwargs):
        method = kwargs.pop('method', 'unknown') # This seems to be a leftover or non-standard arg, mostly we rely on metric_type
        metric_type = kwargs.pop('metric_type', None)
        mode = kwargs.pop('mode', 'dogstatsd')

        if metric_type == 'count':
            self._count(*args, mode=mode, **kwargs)
        elif metric_type == 'increment':
            self._increment(*args, mode=mode, **kwargs)
        elif metric_type == 'decrement':
            self._decrement(*args, mode=mode, **kwargs)
        elif metric_type == 'gauge':
            self._gauge(*args, mode=mode, **kwargs)
        elif metric_type == 'histogram':
            self._histogram(*args, mode=mode, **kwargs)
        elif metric_type == 'event':
            self._log_event(*args, mode=mode, **kwargs)
        elif metric_type == 'rate':
            self._rate(*args, mode=mode, **kwargs)
        elif metric_type == 'distribution':
            self._distribution(*args, mode=mode, **kwargs)
        elif metric_type == 'set':
            self._set(*args, mode=mode, **kwargs)
        else:
            # Fallback/Inference
            if 'event_name' in kwargs and 'message' in kwargs:
                self._log_event(*args, mode=mode, **kwargs)
            else:
                # Default fallback if we can't determine type
                self._gauge(*args, mode=mode, **kwargs)

    def _count(self, metric: str, value: int = 1, tags: Optional[Dict[str, str]] = None, mode: str = 'dogstatsd'):
        self._log("COUNT", f"{metric} : {value}{self._format_tags(tags)}")

    def _increment(self, metric: str, value: int = 1, tags: Optional[Dict[str, str]] = None, mode: str = 'dogstatsd'):
        self._log("INCREMENT", f"{metric} : +{value}{self._format_tags(tags)}")

    def _decrement(self, metric: str, value: int = 1, tags: Optional[Dict[str, str]] = None, mode: str = 'dogstatsd'):
        self._log("DECREMENT", f"{metric} : -{value}{self._format_tags(tags)}")

    def _gauge(self, metric: str, value: float, tags: Optional[Dict[str, str]] = None, mode: str = 'dogstatsd'):
        self._log("GAUGE", f"{metric} : {value}{self._format_tags(tags)}")

    def _histogram(self, metric: str, value: float, tags: Optional[Dict[str, str]] = None, mode: str = 'dogstatsd'):
        self._log("HISTOGRAM", f"{metric} : {value}{self._format_tags(tags)}")

    def _distribution(self, metric: str, value: float, tags: Optional[Dict[str, str]] = None, mode: str = 'dogstatsd'):
        self._log("DISTRIBUTION", f"{metric} : {value}{self._format_tags(tags)}")

    def _set(self, metric: str, value: float, tags: Optional[Dict[str, str]] = None, mode: str = 'dogstatsd'):
        self._log("SET", f"{metric} : {value}{self._format_tags(tags)}")

    def _rate(self, metric: str, value: float, tags: Optional[Dict[str, str]] = None, mode: str = 'dogstatsd'):
        self._log("RATE", f"{metric} : {value}/s{self._format_tags(tags)}")

    def _log_event(self, event_name: str, message: str, tags: Optional[Dict[str, str]] = None, event_type: str = "info", mode: str = 'dogstatsd'):
        self._log("EVENT", f"Name: {event_name} | Type: {event_type} | Message: {message}{self._format_tags(tags)}")
