from app import db
from sqlalchemy.dialects.postgresql import JSONB, UUID
from sqlalchemy import ForeignKeyConstraint
from uuid import uuid4


class Ruleset(db.Model):
    __tablename__ = 'ruleset'
    uid = db.Column(UUID(as_uuid=True), primary_key=True, default=uuid4)
    data = db.Column(JSONB)
    created_date = db.Column(db.DateTime)
    modified_date = db.Column(db.DateTime)

    def __repr__(self):
        return f'<Ruleset {self.uid}>'

    def from_dict(self, dct):
        for field in ['data', 'created_date', 'modified_date']:
            if field in dct:
                setattr(self, field, dct[field])
        if 'rulegroups' in dct:
            self.rulegroups = [RuleGroup().from_dict(rg) for rg in dct]

    def to_dict(self, keys=['uid', 'created_date', 'modified_date', 'connection_string', 'query', 'rulegroups']):
        dct = {'uid': self.uid, 'created_date': self.created_date, 'connection_string': self.connection_string,
               'modified_date': self.modified_date, 'query': self.query}
        out = {}
        for key in keys:
            if key == 'rulegroups':
                if self.rulegroups:
                    out[key] = self.return_rulegroups()
                else:
                    out[key] = None
            else:
                out[key] = dct[key]
        return out

    def remove_rulegroups(self):
        self.rulegroups = []

    def add_rulegroup(self, rg):
        self.rulegroups = self.rulegroups + [RuleGroup().from_dict(rg)]

    def return_rulegroups(self):
        return [rg.to_dict() for rg in self.rulegroups]

    def return_rulegroup_names(self):
        return [rg.get_name() for rg in self.rulegroups]


class RuleGroup(db.Model):
    __tablename__ = 'rulegroup'
    uid = db.Column(UUID(as_uuid=True), primary_key=True, default=uuid4)
    rsid = db.Column(UUID(as_uuid=True), default=uuid4)
    name = db.Column(db.String)
    rules = db.Column(JSONB)
    created_date = db.Column(db.DateTime)
    modified_date = db.Column(db.DateTime)

    __table_args__ = (ForeignKeyConstraint([rsid], [Ruleset.uid]),)

    def __repr__(self):
        return f'<RuleGroup {self.uid}>'

    def from_dict(self, dct):
        for field in ['name', 'rules', 'created_date', 'modified_date']:
            if field in dct:
                setattr(self, field, dct[field])
        return self

    def to_dict(self):
        dct = {'uid': self.uid, 'rsid': self.rsid, 'name': self.name, 'created_date': self.created_date,
               'modified_date': self.modified_date, 'rules': self.rules}
        return dct

    def get_name(self):
        return self.name


Ruleset.rulegroups = db.relationship('RuleGroup', foreign_keys=[RuleGroup.rsid], cascade='all, delete, delete-orphan',
                                     order_by=[RuleGroup.rsid, RuleGroup.created_date], backref='table')


class Validation(db.Model):
    __tablename__ = 'validation'
    uid = db.Column(UUID(as_uuid=True), primary_key=True, default=uuid4)
    rid = db.Column(db.String)
    rgid = db.Column(UUID(as_uuid=True), default=uuid4)
    responsible = db.Column(JSONB)
    created_date = db.Column(db.DateTime)
    modified_date = db.Column(db.DateTime)

    __table_args__ = (ForeignKeyConstraint([rgid], [RuleGroup.uid]),)

    def __repr__(self):
        return f'<Validation {self.uid}>'
