import re
from datetime import datetime, timezone

from .utils import is_bare_gravatar_root_url, is_valid_gravatar_email_hash


_DATE_FIELDS = ('created_at', 'updated_at', 'latest_activity_at', 'birthday')

# Human-readable formats found in the wild (e.g. XVideos "January 14, 2016")
_DATE_FORMATS = (
    '%B %d, %Y',
    '%b %d, %Y',
    '%d %B %Y',
    '%d %b %Y',
    '%a, %d %b %Y %H:%M:%S %Z',  # RFC-822 (Medium RSS lastBuildDate)
    '%a, %d %b %Y %H:%M:%S GMT',
)


class NormalizeDates:
    """Convert human-readable date strings to UTC `YYYY-MM-DD HH:MM:SS UTC`.

    Skips values that already match a numeric/ISO/UTC pattern so existing
    extractors keep their formatting.
    """

    def __init__(self, data):
        self.data = data

    def process(self):
        out = {}
        for k in _DATE_FIELDS:
            v = self.data.get(k)
            if not isinstance(v, str) or not v.strip():
                continue
            v = v.strip()
            # Skip if already normalized or in ISO / numeric form
            if 'UTC' in v or re.match(r'^\d{4}-\d{2}-\d{2}', v) or v.isdigit():
                continue
            for fmt in _DATE_FORMATS:
                try:
                    dt = datetime.strptime(v, fmt).replace(tzinfo=timezone.utc)
                    out[k] = dt.strftime('%Y-%m-%d %H:%M:%S %Z')
                    break
                except ValueError:
                    continue
        return out


class StripInvalidGravatarUrls:
    """Remove bare https://gravatar.com homepage values mistaken for avatars (see Maigret improvement log)."""

    def __init__(self, data):
        self.data = data

    def process(self):
        out = {}
        for k in ('gravatar_url', 'image'):
            v = self.data.get(k)
            if isinstance(v, str) and is_bare_gravatar_root_url(v):
                out[k] = ''
        return out


class Gravatar:
    def __init__(self, data):
        if not 'image' in data:
            self.username = None
            return

        self.username = data.get('username')
        self.url = data['image']
        self.email_hash = self.extract_email_hash()

        # old workaround
        if self.email_hash and self.username == self.email_hash:
            self.username = self.get_username_from_url()

    def extract_email_hash(self):
        gravatar_re = re.search(r'gravatar\.com/avatar/(\w{32})', self.url)
        if gravatar_re:
            return gravatar_re.group(1)
        return ''

    def make_main_url(self):
        return f'https://gravatar.com/{self.email_hash}'

    def make_en_url(self):
        return f'https://en.gravatar.com/{self.email_hash}'

    def get_username_from_url(self):
        import requests
        gravatar_account_location = requests.head(self.make_en_url())
        username = gravatar_account_location.headers.get('location', '').strip('/')
        if username == 'profiles/no-such-user':
            username = ''

        return username

    def process(self):
        output = {}

        if self.username and is_valid_gravatar_email_hash(self.email_hash):
            output = {
                'gravatar_url': self.make_main_url(),
                'gravatar_username': self.username,
                'gravatar_email_md5_hash': self.email_hash,
            }

        return output


class EmailToUsername:
    def __init__(self, data):
        self.data = data

    def process(self):
        output = {}

        for k, v in self.data.items():
            if v and v[0] in "'[{\"":
                continue
            if 'email' in k and '@' in v:
                new_k = k + '_username'
                supposed_username = v.split('@')[0]
                output[new_k] = supposed_username

        return output


class YandexUsernameToEmail:
    def __init__(self, data):
        self.data = data

    def process(self):
        output = {}
        email = None

        if 'yandex_uid' in self.data or 'yandex_public_id' in self.data:
            if 'username' in self.data and self.data['username']:
                email = self.data['username'] + '@yandex.ru'
                output['email'] = email

        return output


POSTPROCESSORS = [StripInvalidGravatarUrls, Gravatar, EmailToUsername, YandexUsernameToEmail, NormalizeDates]
