# standard
from datetime import datetime
from functools import lru_cache
from pathlib import Path

# Pyqgis
from qgis.core import QgsSettings
from qgis.PyQt.QtCore import QCoreApplication, QDateTime, QLocale, QMimeData, Qt


# -- Classes --


class TranslatableMixin:
    """A class intended to be inherited as a mixin to add Qt's translation method to
    classes and objects that need it but are not derived from QWidget."""

    def tr(self, message: str) -> str:
        """Get the translation for a string using Qt translation API.

        :param message: string to be translated.
        :type message: str

        :returns: Translated version of message.
        :rtype: str
        """
        return QCoreApplication.translate(self.__class__.__name__, message)


# -- Functions --


@lru_cache(maxsize=254)
def get_locale() -> QLocale:
    """Returns the user locale as a QLocale object. Defaults to the system locale if
    the QGIS setting is not available.

    :return: A PyQt5.QtCore.QLocale object representing the user's locale.
    :rtype: QLocale
    """
    return QLocale(QgsSettings().value("locale/userLocale", QLocale().name()))


@lru_cache
def to_qdatetime(in_datetime: datetime | str) -> QDateTime:
    """Transform a python datetime to a QDateTime.

    :param in_datetime: _description_
    :type in_datetime: Union[datetime, str]

    :return: datetime in a Qt friendly format.
    :rtype: QDateTime
    """
    if isinstance(in_datetime, datetime):
        return QDateTime(
            in_datetime.year,
            in_datetime.month,
            in_datetime.day,
            in_datetime.hour,
            in_datetime.minute,
            in_datetime.second,
            in_datetime.microsecond // 1000,  # QDateTime uses milliseconds
        )
    elif isinstance(in_datetime, str):
        return QDateTime.fromString(in_datetime, Qt.DateFormat.ISODateWithMs)
    else:
        raise TypeError(f"Unsupported datetime type: {type(in_datetime)}")


@lru_cache
def localize_qdatetime(in_qdatetime: QDateTime, date_format: str = "short") -> str:
    """Localize a QDateTime using the QGIS locale.

    :param in_qdatetime: QDateTime
    :type in_qdatetime: QDateTime
    :return: localized date
    :rtype: str
    """
    if date_format == "short":
        return get_locale().toString(in_qdatetime, get_locale().FormatType.ShortFormat)
    else:
        return get_locale().toString(in_qdatetime, QLocale.FormatType.LongFormat)


def current_datetime_str(date_format: str = "short") -> str:
    """Return current datetime as str with QGIS locale

    :return: current datetime as str
    :rtype: str
    """
    # Get current date
    current_date_time = QDateTime.currentDateTime()
    return localize_qdatetime(current_date_time, date_format)


def _get_local_files_from_mimedata(source: QMimeData) -> list[Path]:
    """Get list of local file from a QMimeData

    :param source: mimedata
    :type source: QMimeData
    :return: list of local file available in source
    :rtype: List[Path]
    """
    return [Path(url.toLocalFile()) for url in source.urls() if url.isLocalFile()]
