import re
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError

from django.core.exceptions import ValidationError as DjangoValidationError
from django.core.validators import validate_email
from rest_framework import serializers

from .models import ScheduledReportRecipient

_FROM_RE = re.compile(r'^\s*(?:[^<>]*<\s*([^<>\s]+)\s*>|([^<>\s]+))\s*$')


def split_emails(raw):
    """Accepts a list or a comma/semicolon/whitespace separated string; returns unique lowercase addresses in order."""
    if isinstance(raw, str):
        raw = re.split(r'[,;\s]+', raw)
    seen, result = set(), []
    for item in raw or []:
        email = str(item).strip().lower()
        if email and email not in seen:
            seen.add(email)
            result.append(email)
    return result


def is_valid_email(value):
    try:
        validate_email(value)
        return True
    except DjangoValidationError:
        return False


class ScheduledReportRecipientSerializer(serializers.ModelSerializer):
    send_hour = serializers.IntegerField(min_value=0, max_value=23)
    send_minute = serializers.IntegerField(min_value=0, max_value=59, default=0)

    class Meta:
        model = ScheduledReportRecipient
        fields = (
            'id', 'email', 'name', 'frequency', 'send_hour', 'send_minute', 'weekly_weekday',
            'max_emails_per_day', 'enabled', 'created_at',
        )
        extra_kwargs = {'weekly_weekday': {'min_value': 0, 'max_value': 6}, 'max_emails_per_day': {'min_value': 1, 'max_value': 20}}

    def validate_email(self, value):
        return value.strip().lower()


class BulkRecipientsSerializer(serializers.Serializer):
    """One schedule applied to several addresses at once."""

    emails = serializers.JSONField()
    name = serializers.CharField(required=False, allow_blank=True, default='', max_length=150)
    frequency = serializers.ChoiceField(choices=ScheduledReportRecipient.Frequency.choices)
    send_hour = serializers.IntegerField(min_value=0, max_value=23)
    send_minute = serializers.IntegerField(min_value=0, max_value=59, default=0)
    weekly_weekday = serializers.IntegerField(min_value=0, max_value=6, default=0)
    max_emails_per_day = serializers.IntegerField(min_value=1, max_value=20, default=1)
    enabled = serializers.BooleanField(default=True)

    def validate_emails(self, value):
        emails = split_emails(value)
        if not emails:
            raise serializers.ValidationError('Enter at least one email address.')
        if len(emails) > 50:
            raise serializers.ValidationError('Add at most 50 addresses at a time.')
        return emails


class EmailSettingsWriteSerializer(serializers.Serializer):
    resend_api_key = serializers.CharField(required=False, allow_blank=True, max_length=255, trim_whitespace=True)
    clear_api_key = serializers.BooleanField(required=False, default=False)
    from_email = serializers.CharField(required=False, allow_blank=True, max_length=255)
    time_zone = serializers.CharField(required=False, max_length=64)

    def validate_from_email(self, value):
        value = value.strip()
        if not value:
            return value
        match = _FROM_RE.match(value)
        address = (match.group(1) or match.group(2)) if match else None
        if not address or not is_valid_email(address):
            raise serializers.ValidationError('Use an address like reports@yourdomain.com or "Shop Name <reports@yourdomain.com>".')
        return value

    def validate_time_zone(self, value):
        try:
            ZoneInfo(value)
        except (ZoneInfoNotFoundError, ValueError):
            raise serializers.ValidationError('Unknown time zone. Use a name like Africa/Dar_es_Salaam.')
        return value
