from dataclasses import dataclass, field
from dataclasses_json import config, dataclass_json
from datetime import datetime, timezone
from marshmallow import fields
from typing import Optional
import dataclasses_json


@dataclass_json
@dataclass
class Subscription:
    billing_code: str
    expires_at: Optional[datetime] = field(
        default=None,
        metadata=config(
            encoder=lambda datetime_instance: Subscription._iso_format(datetime_instance),
            decoder=lambda datetime_string: Subscription.from_iso_format(datetime_string),
            mm_field=fields.DateTime(format='iso'),
            undefined=dataclasses_json.Undefined.EXCLUDE,
            exclude=lambda value: value is None
        )
    )

    def get_sanitized_billing_code(self):
        return '-'.join(['****'] * 3 + [self.billing_code[-4:]])

    def has_been_activated(self):
        return self.expires_at is not None

    def is_active(self):
        return self.has_been_activated() and self.expires_at > datetime.now(timezone.utc)

    @staticmethod
    def from_iso_format(datetime_string: str):
        date_string = datetime_string.replace('Z', '+00:00')
        return datetime.fromisoformat(date_string)

    @staticmethod
    def _iso_format(datetime_instance: datetime):
        return datetime.isoformat(datetime_instance).replace('+00:00', 'Z')