import logging
import os
from datetime import datetime as dt

from sqlmodel import Field, Session, SQLModel, create_engine, select, text, Relationship


DATE_FORMAT = '%Y-%m-%d'

def today():
    return dt.now().strftime(DATE_FORMAT)


logger = logging.getLogger(__name__)
logging.basicConfig(filename='goals.log', encoding='utf-8', level=logging.DEBUG)


class Vision(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    name: str = Field(default=None, unique=True)
    complete_date: dt | None = Field(default=None)
    goals: list["Goal"] = Relationship(back_populates="vision")
    def __str__(self):
        return f'{self.name} (Vision {self.id})'


class Goal(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    name: str = Field(default=None, unique=True)
    complete_date: dt | None = Field(default=None)
    vision_id: int | None = Field(default=None, foreign_key="vision.id")
    notes: str | None = Field(default=None)
    tasks: list["Task"] = Relationship(back_populates="goal")
    vision: Vision = Relationship(back_populates="goals")
    def __str__(self):
        return f'{self.name} (Goal {self.id})'

class Task(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    name: str = Field(default=None, unique=True)
    goal_id: int | None = Field(default=None, foreign_key="goal.id")
    complete_date: dt | None = Field(default=None)
    goal: Goal = Relationship(back_populates="tasks")
    def __str__(self):
        return f'{self.name} ({self.id})'


def pretty_print(goal, tasks):
    results = []
    results.append(f' ## {goal}')
    if not tasks:
        results.append('-- Nothing to list --')

    for task in tasks:
        if(task.complete_date):
            results.append(f' - [x] {task}')
        else:
            results.append(f' - [ ] {task}')
    return results


class Data():
    def __init__(self, db_file=None):
        if not db_file:
            db_file = os.path.join(os.environ.get('MATRIX_DATA_DIR', ''), 'goals.db')

        self.file = db_file
        self.engine = self.get_engine()


    def get_engine(self):
        return create_engine(f"sqlite:///{self.file}")

    def setup(self):
        SQLModel.metadata.create_all(self.engine)
        return 'Success'


    def get_all_visions(self):
        with Session(self.engine) as session:
            cmd = select(Vision).where(Vision.complete_date == None)
            return session.exec(cmd).all()

    def print_ophan_tasks(self):
        pass

    def get_all_goals(self):
        '''List all goals'''
        with Session(self.engine) as session:
            cmd = select(Goal).where(Goal.complete_date == None)
            return session.exec(cmd).all()


    def get_done_goals(self):
        '''List all goals'''
        with Session(self.engine) as session:
            cmd = select(Goal).where(Goal.complete_date != None)
            return session.exec(cmd).all()


    def get_goal(self, id):
        with Session(self.engine) as session:
            cmd = select(Goal).where(Goal.id == id)
            goal = session.exec(cmd).first()
            return (goal, goal.tasks)

    def get_vision(self, id):
        with Session(self.engine) as session:
            cmd = select(Vision).where(Vision.id == id)
            vision = session.exec(cmd).first()
            if vision:
                return (vision, vision.goals)
            else:
                return ('Not found', [])


    def complete_vision(self, id):
        with Session(self.engine) as session:
            cmd = select(Vision).where(Vision.id == id)
            vision = session.exec(cmd).first()
            vision.complete_date = dt.today()
            session.commit()


    def complete_goal(self, id):
        vision_id = -1
        with Session(self.engine) as session:
            cmd = select(Goal).where(Goal.id == id)
            goal = session.exec(cmd).first()
            goal.complete_date = dt.today()
            vision_id = goal.vision_id
            session.commit()
        return vision_id

    def complete_task(self, id):
        with Session(self.engine) as session:
            cmd = select(Task).where(Task.id == id)
            task = session.exec(cmd).first()
            task.complete_date = dt.today()
            goal_id = task.goal_id
            session.commit()
        return goal_id

    def add_with_name(self, cls, name):
        id = -1
        with Session(self.engine) as session:
            new = cls(name=name)
            session.add(new)
            session.commit()
            id = new.id
        return id

    def add_vision(self, name):
        return self.add_with_name(Vision, name)
            
    def add_goal(self, name):
        return self.add_with_name(Goal, name)

    def add_task(self, goal_id, name):
        result = self.add_with_name(Task, name)
        with Session(self.engine) as session:
            cmd = select(Task).where(Task.name == name)
            new = session.exec(cmd).first()
            new.goal_id = goal_id
            session.commit()
        return result

    def assign_vision(self, goal_id, vision_id):
        '''Goals may move between visions'''
        with Session(self.engine) as session:
            cmd = select(Goal).where(Goal.id == goal_id)
            goal = session.exec(cmd).first()
            goal.vision_id = vision_id
            session.commit()

    def add_note(self, note, goal):
        '''Notes print with the goal.'''
        pass

    # Someday: Notes on each

    def list(self):
        results = []
        with Session(self.engine) as session:
            cmd = select(Chore)
            chores = session.exec(cmd).all()
            if(not chores):
                retuls.append('None Found')

            for chore in chores:
                results.append(Data.check_chore(session, chore.id))
        return results

