from typing import Dict, Any
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Boolean
from sqlalchemy.orm import relationship

from db.models.base import Base, BaseMixin


class Sport(Base, BaseMixin):
    __tablename__ = "sport"
    __table_args__ = (
        UniqueConstraint("name"),
    )
    name = Column(String, nullable=False, index=True, unique=True)
    teams = relationship("Team")
    positions = relationship("FieldPosition")

    def __repr__(self):
        return f"Sport(id={self.id}, name={self.name}, created_date={self.created_date})"

    def import_dict(self, import_data: Dict[str, Any]):
        self.id = import_data['id']
        self.created_date = import_data['created_date']
        self.last_modified_date = import_data['last_modified_date']
        self.version = import_data['version']
        self.name = import_data['name']

    def export_dict(self) -> Dict[str, Any]:
        item: Dict[str, Any] = {}
        item['id'] = self.id
        item['created_date'] = str(self.created_date)
        item['last_modified_date'] = str(self.last_modified_date)
        item['version'] = self.version
        item['name'] = self.name
        return item

class Team(Base, BaseMixin):
    __tablename__ = "team"
    name = Column(String, nullable=False, index=True, unique=True)
    short_name = Column(String, nullable=False, )
    sport_id = Column(String, ForeignKey("sport.id"), nullable=False)
    sport = relationship("Sport", back_populates="teams")
    roosters = relationship("Rooster")

    def import_dict(self, import_data: Dict[str, Any]):
        self.id = import_data['id']
        self.created_date = import_data['created_date']
        self.last_modified_date = import_data['last_modified_date']
        self.version = import_data['version']
        self.name = import_data['name']
        self.short_name = import_data['short_name']
        self.sport_id = import_data['sport_id']

    def export_dict(self) -> Dict[str, Any]:
        item: Dict[str, Any] = {}
        item['id'] = self.id
        item['created_date'] = str(self.created_date)
        item['last_modified_date'] = str(self.last_modified_date)
        item['version'] = self.version
        item['name'] = self.name
        item['short_name'] = self.short_name
        item['sport_id'] = self.sport_id
        return item

class FieldPosition(Base, BaseMixin):
    __tablename__ = "field_position"
    __table_args__ = (
        UniqueConstraint("name", "sport_id"),
        UniqueConstraint("short_name", "sport_id"),
    )
    name = Column(String, nullable=False, index=True)
    short_name = Column(String, nullable=False)
    sport_id = Column(String, ForeignKey("sport.id"), nullable=False, index=True)
    sport = relationship("Sport", back_populates="positions")
    roosters = relationship("Rooster")

    def import_dict(self, import_data: Dict[str, Any]):
        self.id = import_data['id']
        self.created_date = import_data['created_date']
        self.last_modified_date = import_data['last_modified_date']
        self.version = import_data['version']
        self.name = import_data['name']
        self.short_name = import_data['short_name']
        self.sport_id = import_data['sport_id']

    def export_dict(self) -> Dict[str, Any]:
        item: Dict[str, Any] = {}
        item['id'] = self.id
        item['created_date'] = str(self.created_date)
        item['last_modified_date'] = str(self.last_modified_date)
        item['version'] = self.version
        item['name'] = self.name
        item['short_name'] = self.short_name
        item['sport_id'] = self.sport_id
        return item


class Player(Base, BaseMixin):
    __tablename__ = "player"
    __table_args__ = (
        UniqueConstraint("first_name", "last_name"),
    )
    first_name = Column(String, nullable=False, index=True)
    last_name = Column(String, nullable=False, index=True)
    roosters = relationship("Rooster")

    def get_full_name(self) -> str:
        return f"{self.last_name}, {self.first_name}"

    def import_dict(self, import_data: Dict[str, Any]):
        self.id = import_data['id']
        self.created_date = import_data['created_date']
        self.last_modified_date = import_data['last_modified_date']
        self.version = import_data['version']
        self.first_name = import_data['first_name']
        self.last_name = import_data['last_name']

    def export_dict(self) -> Dict[str, Any]:
        item: Dict[str, Any] = {}
        item['id'] = self.id
        item['created_date'] = str(self.created_date)
        item['last_modified_date'] = str(self.last_modified_date)
        item['version'] = self.version
        item['first_name'] = self.first_name
        item['last_name'] = self.last_name
        return item


class Rooster(Base, BaseMixin):
    __tablename__ = "rooster"
    __table_args__ = (
        UniqueConstraint("year", "team_id", "player_id", "position_id"),
    )
    year = Column(Integer)
    team_id = Column(String, ForeignKey("team.id"), nullable=False, index=True)
    team = relationship("Team", back_populates="roosters")
    player_id = Column(String, ForeignKey("player.id"), nullable=False, index=True)
    player = relationship("Player", back_populates="roosters")
    position_id = Column(String, ForeignKey("field_position.id"), nullable=False, index=True)
    position = relationship("FieldPosition", back_populates="roosters")
    cards = relationship("Card")

    def import_dict(self, import_data: Dict[str, Any]):
        self.id = import_data['id']
        self.created_date = import_data['created_date']
        self.last_modified_date = import_data['last_modified_date']
        self.version = import_data['version']
        self.year = import_data['year']
        self.team_id = import_data['team_id']
        self.player_id = import_data['player_id']
        self.position_id = import_data['position_id']

    def export_dict(self) -> Dict[str, Any]:
        item: Dict[str, Any] = {}
        item['id'] = self.id
        item['created_date'] = str(self.created_date)
        item['last_modified_date'] = str(self.last_modified_date)
        item['version'] = self.version
        item['year'] = self.year
        item['team_id'] = self.team_id
        item['player_id'] = self.player_id
        item['position_id'] = self.position_id
        return item


class Vendor(Base, BaseMixin):
    __tablename__ = "vendor"
    name = Column(String, nullable=False, unique=True, index=True)
    card_sets = relationship("CardSet")
    cards = relationship("Card")

    def import_dict(self, import_data: Dict[str, Any]):
        self.id = import_data['id']
        self.created_date = import_data['created_date']
        self.last_modified_date = import_data['last_modified_date']
        self.version = import_data['version']
        self.name = import_data['name']

    def export_dict(self) -> Dict[str, Any]:
        item: Dict[str, Any] = {}
        item['id'] = self.id
        item['created_date'] = str(self.created_date)
        item['last_modified_date'] = str(self.last_modified_date)
        item['version'] = self.version
        item['name'] = self.name
        return item


class CardSet(Base, BaseMixin):
    __tablename__ = "card_set"
    __table_args__ = (
        UniqueConstraint("name", "vendor_id"),
    )
    name = Column(String, index=True)
    parallel_set = Column(Boolean)
    insert_set = Column(Boolean)
    vendor_id = Column(String, ForeignKey("vendor.id"), nullable=False, index=True)
    vendor = relationship("Vendor", back_populates="card_sets")
    cards = relationship("Card")

    def import_dict(self, import_data: Dict[str, Any]):
        self.id = import_data['id']
        self.created_date = import_data['created_date']
        self.last_modified_date = import_data['last_modified_date']
        self.version = import_data['version']
        self.name = import_data['name']
        self.parallel_set = import_data['parallel_set']
        self.insert_set = import_data['insert_set']
        self.vendor_id = import_data['vendor_id']

    def export_dict(self) -> Dict[str, Any]:
        item: Dict[str, Any] = {}
        item['id'] = self.id
        item['created_date'] = str(self.created_date)
        item['last_modified_date'] = str(self.last_modified_date)
        item['version'] = self.version
        item['name'] = self.name
        item['parallel_set'] = self.parallel_set
        item['insert_set'] = self.insert_set
        item['vendor_id'] = self.vendor_id
        return item


class Card(Base, BaseMixin):
    __tablename__ = "card"
    __table_args__ = (
        UniqueConstraint("card_number", "year", "vendor_id", "card_set_id"),
    )
    card_number = Column(Integer, index=True)
    year = Column(Integer, index=True)
    card_set_id = Column(String, ForeignKey("card_set.id"), nullable=False)
    card_set = relationship("CardSet", back_populates="cards")
    rooster_id = Column(String, ForeignKey("rooster.id"), nullable=False)
    rooster = relationship("Rooster", back_populates="cards")
    vendor_id = Column(String, ForeignKey("vendor.id"), nullable=False)
    vendor = relationship("Vendor", back_populates="cards")

    def import_dict(self, import_data: Dict[str, Any]):
        self.id = import_data['id']
        self.created_date = import_data['created_date']
        self.last_modified_date = import_data['last_modified_date']
        self.version = import_data['version']
        self.card_number = import_data['card_number']
        self.year = import_data['year']
        self.card_set_id = import_data['card_set_id']
        self.rooster_id = import_data['rooster_id']
        self.vendor_id = import_data['vendor_id']

    def export_dict(self) -> Dict[str, Any]:
        item: Dict[str, Any] = {}
        item['id'] = self.id
        item['created_date'] = str(self.created_date)
        item['last_modified_date'] = str(self.last_modified_date)
        item['version'] = self.version
        item['card_number'] = self.card_number
        item['year'] = self.year
        item['card_set_id'] = self.card_set_id
        item['rooster_id'] = self.rooster_id
        item['vendor_id'] = self.vendor_id
        return item
