# -*- encoding: utf-8 -*-
"""
Copyright (c) 2019 - present AppSeed.us
"""

from flask_login import UserMixin

from sqlalchemy.orm import relationship
from flask_dance.consumer.storage.sqla import OAuthConsumerMixin

from apps import db, login_manager

from apps.authentication.util import hash_pass

from datetime import datetime

from sqlalchemy.types import TypeDecorator, Text

class Users(db.Model, UserMixin):

    __tablename__ = 'Users'

    id            = db.Column(db.Integer, primary_key=True)
    username      = db.Column(db.String(64), unique=True)
    email         = db.Column(db.String(64), unique=True)
    password      = db.Column(db.LargeBinary)
    oauth_github  = db.Column(db.String(100), nullable=True)
    interaction_count = db.Column(db.Integer, default=0)


    def __init__(self, **kwargs):
        for property, value in kwargs.items():
            # depending on whether value is an iterable or not, we must
            # unpack it's value (when **kwargs is request.form, some values
            # will be a 1-element list)
            if hasattr(value, '__iter__') and not isinstance(value, str):
                # the ,= unpack of a singleton fails PEP8 (travis flake8 test)
                value = value[0]

            if property == 'password':
                value = hash_pass(value)  # we need bytes here (not plain str)

            setattr(self, property, value)

    def __repr__(self):
        return str(self.username) 

class ConfigUpdates(db.Model):
    __tablename__ = 'ConfigUpdates'

    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('Users.id'), nullable=False)
    user = db.relationship('Users', backref='ConfigUpdates')
    insta_username = db.Column(db.String(64), nullable=False)
    followers_count = db.Column(db.String(64), nullable=True)
    following_count = db.Column(db.String(64), nullable=True)
    posts_count = db.Column(db.String(64), nullable=True)
    app_id = db.Column(db.String(64), nullable=True)
    speed_multiplier = db.Column(db.String(64), default="1")
    use_cloned_app = db.Column(db.Boolean, default=False)
    allow_untested_ig_version = db.Column(db.Boolean, default=False)
    screen_sleep = db.Column(db.Boolean, default=False)
    screen_record = db.Column(db.Boolean, default=False)
    debug = db.Column(db.Boolean, default=False)
    close_apps = db.Column(db.Boolean, default=False)
    kill_atx_agent = db.Column(db.Boolean, default=False)
    restart_atx_agent = db.Column(db.Boolean, default=False)
    disable_block_detection = db.Column(db.Boolean, default=False)
    disable_filters = db.Column(db.Boolean, default=False)
    dont_type = db.Column(db.Boolean, default=False)

    total_crashes_limit = db.Column(db.String(64), default="5")
    truncate_sources = db.Column(db.String(64), default="2-5")
    count_app_crashes = db.Column(db.Boolean, default=False)
    shuffle_jobs = db.Column(db.Boolean, default=True)
    
    blogger_followers = db.Column(db.JSON, nullable=True)
    blogger_following = db.Column(db.JSON, nullable=True)
    blogger_post_likers = db.Column(db.JSON, nullable=True)
    blogger = db.Column(db.JSON, nullable=True)
    hashtag_likers_top = db.Column(db.JSON, nullable=True)
    hashtag_likers_recent = db.Column(db.JSON, nullable=True)
    hashtag_posts_top = db.Column(db.JSON, nullable=True)
    hashtag_posts_recent = db.Column(db.JSON, nullable=True)
    place_posts_top = db.Column(db.JSON, nullable=True)
    place_posts_recent = db.Column(db.JSON, nullable=True)
    place_likers_top = db.Column(db.JSON, nullable=True)
    place_likers_recent = db.Column(db.JSON, nullable=True)
    interact_from_file = db.Column(db.JSON, nullable=True)
    posts_from_file = db.Column(db.JSON, nullable=True)
    delete_interacted_users = db.Column(db.Boolean, default=True)
    working_hours = db.Column(db.JSON, nullable=True)

    watch_video_time = db.Column(db.String(64), default="15-35")
    watch_photo_time = db.Column(db.String(64), default="3-4")
    
    feed_likes = db.Column(db.String(64), default="2-5")
    unfollow = db.Column(db.String(64), default="10-20")
    unfollow_any = db.Column(db.String(64), default="10-20")
    unfollow_non_followers = db.Column(db.String(64), default="10-20")
    unfollow_any_non_followers = db.Column(db.String(64), default="10-20")
    unfollow_any_followers = db.Column(db.String(64), default="10-20")
    unfollow_from_file = db.Column(db.JSON, nullable=True)
    sort_followers = db.Column(db.Boolean, default=False)
    unfollow_delay = db.Column(db.String(64), default="15")
    remove_followers_from_file = db.Column(db.JSON, nullable=True)
    delete_removed_followers = db.Column(db.Boolean, default=True)
    interactions_count = db.Column(db.String(64), default="30-40")
    likes_count = db.Column(db.String(64), default="1-2")
    likes_percentage = db.Column(db.String(64), default="100")
    stories_count = db.Column(db.String(64), default="1-2")
    stories_percentage = db.Column(db.String(64), default="100")
    max_comments_pro_user = db.Column(db.String(64), default="1-2")
    interact_percentage = db.Column(db.String(64), default="30-40")
    follow_percentage = db.Column(db.String(64), default="30-40")
    follow_limit = db.Column(db.String(64), default="50")
    skipped_list_limit = db.Column(db.String(64), default="10-15")
    skipped_posts_limit = db.Column(db.String(64), default="5")
    
    min_following = db.Column(db.String(64), default="100")
    total_likes_limit = db.Column(db.String(64), default="120-150")
    total_follows_limit = db.Column(db.String(64), default="40-50")
    total_unfollows_limit = db.Column(db.String(64), default="40-50")
    total_watches_limit = db.Column(db.String(64), default="120-150")
    total_successful_interactions_limit = db.Column(db.String(64), default="120-150")
    total_interactions_limit = db.Column(db.String(64), default="280-300")
    total_comments_limit = db.Column(db.String(64), default="3-5")
    total_pm_limit = db.Column(db.String(64), default="3-5")
    end_if_likes_limit_reached = db.Column(db.Boolean, default=True)
    end_if_follows_limit_reached = db.Column(db.Boolean, default=False)
    end_if_watches_limit_reached = db.Column(db.Boolean, default=False)
    end_if_comments_limit_reached = db.Column(db.Boolean, default=False)
    end_if_pm_limit_reached = db.Column(db.Boolean, default=False)
    repeat = db.Column(db.String(64), default="280-320")
    total_sessions = db.Column(db.String(64), default="1")
    time_delta = db.Column(db.String(64), default="10-15")
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

    def __repr__(self):
        return f"<ConfigUpdates {self.insta_username}>"

@login_manager.user_loader
def user_loader(id):
    return Users.query.filter_by(id=id).first()


@login_manager.request_loader
def request_loader(request):
    username = request.form.get('username')
    user = Users.query.filter_by(username=username).first()
    return user if user else None

class OAuth(OAuthConsumerMixin, db.Model):
    user_id = db.Column(db.Integer, db.ForeignKey("Users.id", ondelete="cascade"), nullable=False)
    user = db.relationship(Users)
