import uuid
import secrets

from sqlalchemy import Column, BigInteger, Boolean, Integer, Unicode

from .meta import (
    Base,
    RBase,
    UUIDType,
    now_timestamp,
    foreign_key,
)

FREQUENCY_DAILY = 0
FREQUENCY_WEEKLY = 1
FREQUENCY_IMMEDIATE = 2

FREQUENCY_HUMAN = {
    FREQUENCY_DAILY: "Daily",
    FREQUENCY_WEEKLY: "Weekly",
    FREQUENCY_IMMEDIATE: "Immediate",
}


class ShopSubscription(RBase, Base):
    """Tracks email digest subscriptions to a shop."""

    id = Column(UUIDType, primary_key=True, index=True)
    shop_id = Column(UUIDType, foreign_key("Shop", "id"), nullable=False, index=True)
    user_id = Column(UUIDType, foreign_key("User", "id"), nullable=True, index=True)
    email = Column(Unicode(64), nullable=False)
    frequency = Column(Integer, nullable=False, default=FREQUENCY_DAILY)
    verified = Column(Boolean, nullable=False, default=False)
    unsubscribe_token = Column(Unicode(64), nullable=False, unique=True)
    verify_token = Column(Unicode(64), nullable=True)
    last_digest_timestamp = Column(BigInteger, nullable=False)
    created_timestamp = Column(BigInteger, nullable=False)
    disabled = Column(Boolean, nullable=False, default=False)

    def __init__(self, email, shop_id, user_id=None):
        self.id = uuid.uuid1()
        self.email = email
        self.shop_id = shop_id
        self.user_id = user_id
        self.frequency = FREQUENCY_DAILY
        self.disabled = False
        self.unsubscribe_token = secrets.token_urlsafe(32)
        self.created_timestamp = now_timestamp()
        self.last_digest_timestamp = now_timestamp()

        if user_id:
            # Logged-in users are auto-verified
            self.verified = True
            self.verify_token = None
        else:
            self.verified = False
            self.verify_token = secrets.token_urlsafe(32)

    @property
    def human_frequency(self):
        return FREQUENCY_HUMAN.get(self.frequency, "Daily")


def get_subscription_for_email_and_shop(dbsession, email, shop_id):
    """Get subscription by email and shop_id, or None."""
    return (
        dbsession.query(ShopSubscription)
        .filter(
            ShopSubscription.email == email,
            ShopSubscription.shop_id == shop_id,
        )
        .one_or_none()
    )


def get_subscription_by_unsubscribe_token(dbsession, token):
    """Get subscription by unsubscribe_token, or None."""
    return (
        dbsession.query(ShopSubscription)
        .filter(ShopSubscription.unsubscribe_token == token)
        .one_or_none()
    )


def get_subscription_by_verify_token(dbsession, token):
    """Get subscription by verify_token, or None."""
    return (
        dbsession.query(ShopSubscription)
        .filter(ShopSubscription.verify_token == token)
        .one_or_none()
    )


def get_verified_subscriptions_for_shop(dbsession, shop_id, frequency=None):
    """Get all verified, non-disabled subscriptions for a shop."""
    query = dbsession.query(ShopSubscription).filter(
        ShopSubscription.shop_id == shop_id,
        ShopSubscription.verified == True,
        ShopSubscription.disabled == False,
    )
    if frequency is not None:
        query = query.filter(ShopSubscription.frequency == frequency)
    return query.all()
