# (c) cavaliba.com - data - field - datetime

"""
FieldDatetime: dataformat "datetime", canonical stored/displayed format is
'YYYY-MM-DD hh:mm:ss'. Input also accepts ISO 8601 (T separator, optional
Z/offset, optional fractional seconds); it is normalized to the canonical
format on merge (offset/Z converted to UTC, fractional seconds truncated).

Method inventory: merge_request, merge_import, is_valid.
"""

import datetime

from .field import Field

CANONICAL_FORMAT = "%Y-%m-%d %H:%M:%S"

# tried in order; %z also matches a trailing 'Z' (Python treats it as +00:00)
ACCEPTED_FORMATS = [
    CANONICAL_FORMAT,
    "%Y-%m-%dT%H:%M:%S",
    "%Y-%m-%dT%H:%M:%S.%f",
    "%Y-%m-%dT%H:%M:%S%z",
    "%Y-%m-%dT%H:%M:%S.%f%z",
]


def _normalize_datetime(value):
    """Parse value against ACCEPTED_FORMATS (canonical or ISO 8601 with optional
    Z/offset and fractional seconds); return the canonical 'YYYY-MM-DD HH:MM:SS'
    string (offset/Z converted to UTC, fractional seconds truncated), or None if
    value doesn't match any accepted format."""

    if type(value) is not str:
        return None

    for fmt in ACCEPTED_FORMATS:
        try:
            parsed = datetime.datetime.strptime(value, fmt)
        except ValueError:
            continue
        if parsed.tzinfo is not None:
            parsed = parsed.astimezone(datetime.UTC).replace(tzinfo=None)
        return parsed.strftime(CANONICAL_FORMAT)

    return None


# -------------
# DATETIME
# -------------
class FieldDatetime(Field):
    # canonical: 'YYYY-MM-DD hh:mm:ss' ; ISO 8601 also accepted on input, see _normalize_datetime

    def merge_request(self, request):
        """Set self.value from request.POST.getlist(fieldname), normalizing each
        entry via _normalize_datetime (canonical or ISO 8601 input)."""
        data = request.POST.getlist(self.fieldname, default=[])
        self.value = []
        for i in data:
            v = _normalize_datetime(i)
            if v:
                self.value.append(v)

    def merge_import(self, data):
        """Set self.value from an import/API payload, normalizing each entry via
        _normalize_datetime (no split_composite)."""
        # no split composite !
        self.value = []
        if type(data) is str:
            v = _normalize_datetime(data)
            if v:
                self.value = [v]
        elif type(data) is list:
            for i in data:
                v = _normalize_datetime(i)
                if v:
                    self.value.append(v)

    def is_valid(self):
        """Cardinality check (super) plus: every value must match one of
        ACCEPTED_FORMATS (canonical or ISO 8601)."""
        r = super().is_valid()
        for v in self.value:
            if _normalize_datetime(v) is None:
                return False
        return r
