from __future__ import absolute_import
from flask_sqlalchemy.query import Query as BaseQuery
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy import func
from dostadmin import db
from dostadmin.mixins import TimestampMixin


class UserQuery(BaseQuery):
    def get_user_by_id(self, user_id):
        return self.filter(User.id == user_id).first()

    def get_users_by_name(self, name):
        users = (
            self.get_users_log()
            if name == ""
            else self.filter(func.lower(User.name) == func.lower(name)).all()
        )
        return users

    def get_users_by_partner(self, partner_id):
        return self.filter(User.partner_id == partner_id).all()

    def get_users_log(self):
        return self.all()

    def get_users_by_ids(self, user_ids):
        self.filter(User.id.in_(user_ids)).all()


class User(TimestampMixin, db.Model):
    __tablename__ = "users"
    query_class = UserQuery

    class Status:
        INCOMPLETE = "incomplete"
        COMPLETE = "complete"

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(50), unique=False)
    partner_id = db.Column(db.Integer, db.ForeignKey("partner.id"))
    user_type_id = db.Column(db.Integer, db.ForeignKey("usertype.id"))
    program_order = db.Column(JSONB, server_default="{}")
    signup_status = db.Column(db.String(50), unique=False)
    max_retries = db.Column(db.Integer, nullable=False, server_default="0")

    experiences = db.relationship(
        "Experience", back_populates="user", primaryjoin="Experience.user_id == User.id"
    )
    campaigns = db.relationship(
        "Campaign", backref="user", primaryjoin="Campaign.user_id == User.id"
    )
    schoolleader = db.relationship(
        "SchoolLeader",
        uselist=False,
        backref="user",
        primaryjoin="SchoolLeader.user_id == User.id",
    )
    teacher = db.relationship(
        "Teacher",
        uselist=False,
        backref="user",
        primaryjoin="Teacher.user_id == User.id",
    )
    parent = db.relationship(
        "Parent", uselist=False, backref="user", primaryjoin="Parent.user_id == User.id"
    )
    cohorts = db.relationship(
        "CohortDetails", backref="user", primaryjoin="User.id == CohortDetails.user_id"
    )
    registration = db.relationship(
        "Registration",
        back_populates="user",
        primaryjoin="User.id == Registration.user_id",
    )

    def __repr__(self):
        return (
            "\n User: id_"
            + str(self.id)
            + " "
            + self.name
            + ", partner:"
            + str(self.partner_id)
        )

    @classmethod
    def add_new_user(cls, name, partner_name=None):
        from dostadmin.db_model import Partner, UserType

        if partner_name:
            partner = Partner.query.get_by_name(partner_name)
            partner_id = partner.id
        else:
            partner_id = Partner.query.get_id_with_name("callin")
        user = User(
            name=name,
            partner_id=partner_id,
            user_type_id=UserType.query.get_user_type_id_by_name(UserType.Type.PARENT),
            signup_status=User.Status.INCOMPLETE,
        )
        db.session.add(user)
        db.session.commit()
        return user

    def get_phone_number(self):
        phone = None
        if self.experiences:
            is_active = any(ex.status == "active" for ex in self.experiences)
            if is_active:
                for ex in self.experiences:
                    phone = ex.phone if ex.status == "active" else None
            else:
                max_date = max(ex.start_date for ex in self.experiences)
                for ex in self.experiences:
                    phone = ex.phone if ex.start_date == max_date else None
        return phone

    @classmethod
    def update_signup_status(cls, user, status):
        user.signup_status = status

        registration = user.registration

        if registration:
            registration[0].signup_status = status

        db.session.commit()
