
"""
**********************************************************************************
EventWithDateBase

* This is the base class for:
    - EventCompletions 
    - EventCancaleations

* The only difference between the 2 are the table names.

**********************************************************************************
"""
from __future__ import annotations
import datetime
from enum import Enum
from mysql.connector.cursor import MySQLCursor
from mysql.connector.errors import IntegrityError
from ..db import DB, DbCursorTypes

#----------------------------------------------------------
# Possible table names for the sub-classes
#----------------------------------------------------------
class EventTableNames(str, Enum):
    Completions = 'Event_Completions'
    Cancelations = 'Event_Cancelations'

#----------------------------------------------------------
# Base class for Completions and Cancelations
#----------------------------------------------------------
class EventWithDateBase:

    #----------------------------------------------------------
    # Constructor
    #
    # Parms:
    #   user_id - the client's user id
    #   database_table_name - name of the sql database name to query
    #----------------------------------------------------------
    def __init__(self, user_id: str, event_table_name: EventTableNames):
        self.user_id = user_id
        self.event_table_name = event_table_name
        self.db = DB()


    #----------------------------------------------------------
    # Get all the cancelations for a user
    #----------------------------------------------------------
    def getAll(self) -> list[dict]:
        sql = F'''
            SELECT * FROM {self.event_table_name.value} c
            WHERE c.event_id in (SELECT e.id FROM Events e WHERE e.user_id = %s)
            ORDER BY date DESC
        '''
        parms = (self.user_id,)
        cancelation_records = self._getSelectCursor(sql, parms).fetchall()
        self.db.close()
        return cancelation_records

    #----------------------------------------------------------
    # Get all the cancelations for the specified event
    #
    # Parms:
    #   event_id - event id
    #----------------------------------------------------------
    def getAllForEvent(self, event_id) -> list[dict]:
        sql = F'''
            SELECT * FROM {self.event_table_name.value} c
            WHERE c.event_id = %s
            ORDER BY date DESC
        '''
        parms = (event_id,)
        cancelation_records = self._getSelectCursor(sql, parms).fetchall()
        self.db.close()
        return cancelation_records


    #----------------------------------------------------------
    # Get a single event cancelation
    #
    # Parms:
    #   event_id - event id
    #   date - the date of the cancelation
    #----------------------------------------------------------
    def getSingle(self, event_id: str, date: datetime.date) -> dict:
        sql = F'''
            SELECT * FROM {self.event_table_name.value} c
            WHERE 
                c.event_id = %s AND
                c.date = %s
            LIMIT 1
        '''

        parms = (event_id, date)
        cancelation_records = self._getSelectCursor(sql, parms).fetchone()
        self.db.close()
        return cancelation_records

    #----------------------------------------------------------
    # Return a cursor from a database connection for a select statement.
    #
    # Parms:
    #   event_id - event id
    #   parms - parms for the sql statement
    # 
    # Returns the MySQLCursor
    #----------------------------------------------------------
    def _getSelectCursor(self, sqlStmt: str, parms: tuple=None) -> MySQLCursor:
        self.db.connect()
        cursor = self.db.getCursor(DbCursorTypes.NamedTuple)
        cursor.execute(sqlStmt, params=parms)
        return cursor

    #----------------------------------------------------------
    # Insert a new cancelation
    #
    # Parms:
    #   event_id - event id
    #   date - the date of the cancelation
    #
    # Returns a bool:
    #   true - successful insert
    #   false - something fucked up
    #----------------------------------------------------------
    def insert(self, event_id: str, date: datetime.date):
        sql = F'INSERT INTO {self.event_table_name.value} (event_id, date) VALUES (%s, %s)'

        self.db.connect()
        cursor = self.db.getCursor(DbCursorTypes.Prepared)
        
        success = False

        try:
            cursor.execute(sql, params=(event_id, date))
            self.db.commit()
            success = True
        except IntegrityError:
            success = False
        finally:
            self.db.close()

        if not success:
            return False
        
        if cursor.rowcount != 1:
            success = False

        return success

    #----------------------------------------------------------
    # Delete a cancelation
    #
    # Parms:
    #   event_id - event id
    #   date - the date of the cancelation
    #
    # Returns a bool:
    #   true - successfully deleted
    #   false - something fucked up
    #----------------------------------------------------------
    def delete(self, event_id: str, date: datetime.date):
        sql = F'DELETE FROM {self.event_table_name.value} WHERE event_id = %s AND date = %s'
        success = False

        try:
            self.db.connect()
            cursor = self.db.getCursor(DbCursorTypes.Prepared)
            cursor.execute(sql, params=(event_id, date))
            self.db.commit()
            success = True
        except IntegrityError:
            success = False
        finally:
            self.db.close()

        return success


# **********************************************************************************
# Completions
#
# * This is a sub-type of the EventWithDateBase class.
#
# * Completion records are comprised of the following fields:
#     - event_id
#     - date
#     - marked_completed
#
# **********************************************************************************
class Completions(EventWithDateBase):

    #----------------------------------------------------------
    # Constructor
    #
    # Parms:
    #   user_id - the client's user id
    #----------------------------------------------------------
    def __init__(self, user_id):
        super().__init__(user_id, EventTableNames.Completions)




#**********************************************************************************
# Cancelations
#
# * Cancelations is a sub-class of EventWithDateBase
# 
# * Records are comprised of the following fields:
#     - event_id
#     - date
#     - recorded_on
#
#**********************************************************************************
class Cancelations(EventWithDateBase):

    #----------------------------------------------------------
    # Constructor
    #
    # Parms:
    #   user_id - the client's user id
    #   database_table_name - name of the sql database name to query
    #----------------------------------------------------------
    def __init__(self, user_id):
        super().__init__(user_id, EventTableNames.Cancelations)

"""
**********************************************************************************
EventWithDateBase

* This is the base class for:
    - EventCompletions 
    - EventCancaleations

* The only difference between the 2 are the table names.

**********************************************************************************
"""
from __future__ import annotations
import datetime
from enum import Enum
from mysql.connector.cursor import MySQLCursor
from mysql.connector.errors import IntegrityError
from ..db import DB, DbCursorTypes

#----------------------------------------------------------
# Possible table names for the sub-classes
#----------------------------------------------------------
class EventTableNames(str, Enum):
    Completions = 'Event_Completions'
    Cancelations = 'Event_Cancelations'

#----------------------------------------------------------
# Base class for Completions and Cancelations
#----------------------------------------------------------
class EventWithDateBase:

    #----------------------------------------------------------
    # Constructor
    #
    # Parms:
    #   user_id - the client's user id
    #   database_table_name - name of the sql database name to query
    #----------------------------------------------------------
    def __init__(self, user_id: str, event_table_name: EventTableNames):
        self.user_id = user_id
        self.event_table_name = event_table_name
        self.db = DB()


    #----------------------------------------------------------
    # Get all the cancelations for a user
    #----------------------------------------------------------
    def getAll(self) -> list[dict]:
        sql = F'''
            SELECT * FROM {self.event_table_name.value} c
            WHERE c.event_id in (SELECT e.id FROM Events e WHERE e.user_id = %s)
            ORDER BY date DESC
        '''
        parms = (self.user_id,)
        cancelation_records = self._getSelectCursor(sql, parms).fetchall()
        self.db.close()
        return cancelation_records

    #----------------------------------------------------------
    # Get all the cancelations for the specified event
    #
    # Parms:
    #   event_id - event id
    #----------------------------------------------------------
    def getAllForEvent(self, event_id) -> list[dict]:
        sql = F'''
            SELECT * FROM {self.event_table_name.value} c
            WHERE c.event_id = %s
            ORDER BY date DESC
        '''
        parms = (event_id,)
        cancelation_records = self._getSelectCursor(sql, parms).fetchall()
        self.db.close()
        return cancelation_records


    #----------------------------------------------------------
    # Get a single event cancelation
    #
    # Parms:
    #   event_id - event id
    #   date - the date of the cancelation
    #----------------------------------------------------------
    def getSingle(self, event_id: str, date: datetime.date) -> dict:
        sql = F'''
            SELECT * FROM {self.event_table_name.value} c
            WHERE 
                c.event_id = %s AND
                c.date = %s
            LIMIT 1
        '''

        parms = (event_id, date)
        cancelation_records = self._getSelectCursor(sql, parms).fetchone()
        self.db.close()
        return cancelation_records

    #----------------------------------------------------------
    # Return a cursor from a database connection for a select statement.
    #
    # Parms:
    #   event_id - event id
    #   parms - parms for the sql statement
    # 
    # Returns the MySQLCursor
    #----------------------------------------------------------
    def _getSelectCursor(self, sqlStmt: str, parms: tuple=None) -> MySQLCursor:
        self.db.connect()
        cursor = self.db.getCursor(DbCursorTypes.NamedTuple)
        cursor.execute(sqlStmt, params=parms)
        return cursor

    #----------------------------------------------------------
    # Insert a new cancelation
    #
    # Parms:
    #   event_id - event id
    #   date - the date of the cancelation
    #
    # Returns a bool:
    #   true - successful insert
    #   false - something fucked up
    #----------------------------------------------------------
    def insert(self, event_id: str, date: datetime.date):
        sql = F'INSERT INTO {self.event_table_name.value} (event_id, date) VALUES (%s, %s)'

        self.db.connect()
        cursor = self.db.getCursor(DbCursorTypes.Prepared)
        
        success = False

        try:
            cursor.execute(sql, params=(event_id, date))
            self.db.commit()
            success = True
        except IntegrityError:
            success = False
        finally:
            self.db.close()

        if not success:
            return False
        
        if cursor.rowcount != 1:
            success = False

        return success

    #----------------------------------------------------------
    # Delete a cancelation
    #
    # Parms:
    #   event_id - event id
    #   date - the date of the cancelation
    #
    # Returns a bool:
    #   true - successfully deleted
    #   false - something fucked up
    #----------------------------------------------------------
    def delete(self, event_id: str, date: datetime.date):
        sql = F'DELETE FROM {self.event_table_name.value} WHERE event_id = %s AND date = %s'
        success = False

        try:
            self.db.connect()
            cursor = self.db.getCursor(DbCursorTypes.Prepared)
            cursor.execute(sql, params=(event_id, date))
            self.db.commit()
            success = True
        except IntegrityError:
            success = False
        finally:
            self.db.close()

        return success


# **********************************************************************************
# Completions
#
# * This is a sub-type of the EventWithDateBase class.
#
# * Completion records are comprised of the following fields:
#     - event_id
#     - date
#     - marked_completed
#
# **********************************************************************************
class Completions(EventWithDateBase):

    #----------------------------------------------------------
    # Constructor
    #
    # Parms:
    #   user_id - the client's user id
    #----------------------------------------------------------
    def __init__(self, user_id):
        super().__init__(user_id, EventTableNames.Completions)




#**********************************************************************************
# Cancelations
#
# * Cancelations is a sub-class of EventWithDateBase
# 
# * Records are comprised of the following fields:
#     - event_id
#     - date
#     - recorded_on
#
#**********************************************************************************
class Cancelations(EventWithDateBase):

    #----------------------------------------------------------
    # Constructor
    #
    # Parms:
    #   user_id - the client's user id
    #   database_table_name - name of the sql database name to query
    #----------------------------------------------------------
    def __init__(self, user_id):
        super().__init__(user_id, EventTableNames.Cancelations)
********************************************************************************** EventWithDateBase  * This is the base class for:     - EventCompletions      - EventCancaleations  * The only difference between the 2 are the table names.  ********************************************************************************** #---------------------------------------------------------- # Possible table names for the sub-classes #---------------------------------------------------------- #---------------------------------------------------------- # Base class for Completions and Cancelations #---------------------------------------------------------- #---------------------------------------------------------- # Constructor # # Parms: #   user_id - the client's user id #   database_table_name - name of the sql database name to query #---------------------------------------------------------- #---------------------------------------------------------- # Get all the cancelations for a user #---------------------------------------------------------- SELECT * FROM {self.event_table_name.value} c             WHERE c.event_id in (SELECT e.id FROM Events e WHERE e.user_id = %s)             ORDER BY date DESC #---------------------------------------------------------- # Get all the cancelations for the specified event # # Parms: #   event_id - event id #---------------------------------------------------------- SELECT * FROM {self.event_table_name.value} c             WHERE c.event_id = %s             ORDER BY date DESC #---------------------------------------------------------- # Get a single event cancelation # # Parms: #   event_id - event id #   date - the date of the cancelation #---------------------------------------------------------- SELECT * FROM {self.event_table_name.value} c             WHERE                  c.event_id = %s AND                 c.date = %s             LIMIT 1 #---------------------------------------------------------- # Return a cursor from a database connection for a select statement. # # Parms: #   event_id - event id #   parms - parms for the sql statement # # Returns the MySQLCursor #---------------------------------------------------------- #---------------------------------------------------------- # Insert a new cancelation # # Parms: #   event_id - event id #   date - the date of the cancelation # # Returns a bool: #   true - successful insert #   false - something fucked up #---------------------------------------------------------- #---------------------------------------------------------- # Delete a cancelation # # Parms: #   event_id - event id #   date - the date of the cancelation # # Returns a bool: #   true - successfully deleted #   false - something fucked up #---------------------------------------------------------- # ********************************************************************************** # Completions # # * This is a sub-type of the EventWithDateBase class. # # * Completion records are comprised of the following fields: #     - event_id #     - date #     - marked_completed # # ********************************************************************************** #---------------------------------------------------------- # Constructor # # Parms: #   user_id - the client's user id #---------------------------------------------------------- #********************************************************************************** # Cancelations # # * Cancelations is a sub-class of EventWithDateBase # # * Records are comprised of the following fields: #     - event_id #     - date #     - recorded_on # #********************************************************************************** #---------------------------------------------------------- # Constructor # # Parms: #   user_id - the client's user id #   database_table_name - name of the sql database name to query #----------------------------------------------------------