import asyncio
import aiocron
from async_timeout import timeout

import yaml
from yaml.loader import SafeLoader

import discord
import discord.utils
from discord import option
from discord.ext import commands

import mysql.connector
from mysql.connector import Error

import time
from datetime import date, datetime, tzinfo, timedelta

import os
import re

import flask

from easy_pil import Canvas, Editor, Font, Text, font, load_image_async
from PIL import Image, ImageDraw, ImageFont, ImageOps
import pytz
import socket

from cogs.messagebuilder import createembednoconf

zeit = datetime.now()

time_date = zeit.strftime("%Y/%m/%d")
time_year = zeit.strftime("%Y")
time_month = zeit.strftime("%m")
time_day = zeit.strftime("%d")

time_time = zeit.strftime("%H:%M:%S")
time_hour = zeit.strftime("%H")
time_minute = zeit.strftime("%M")
time_second = zeit.strftime("%S")

time_datetime = zeit.strftime("%Y/%m/%d " " %H:%M:%S")

time_datefile = zeit.strftime("%Y_%m_%d")

## Class

class Absences(commands.Cog):
    
    def __init__(self, bot):
        self.bot = bot
        global path
        path = bot.path


    @commands.slash_command(name="abwesenheiten", description="Zeigt alle Abwesenheiten der Teammitgleider an.")
    async def abwesenheiten(
        self, ctx: discord.ApplicationContext
        ):
        with open(fr'{path}/Configs/server.yaml', encoding='utf8') as f:
            data = yaml.load(f, Loader=SafeLoader)
            try:
                servername = next(item["name"] for item in data["Config.Server"] if str(ctx.guild.id) == str(item["guild"]))
            except StopIteration:
                await ctx.respond("Error in Syntax", ephemeral=True)
                return
            
            with open(fr'{path}/Configs/{servername}/absences.yaml', encoding='utf8') as f:
                data = yaml.load(f, Loader=SafeLoader)

            if data["Config.Enabled"] == True:
                pass

            else:
                await ctx.respond("Diese Funktion ist für diesen Server nicht Aktiviert!", ephemeral=True)
                return
            
            embed_fields = []
            today = datetime.now()
            last_week_start = today - timedelta(days=today.weekday() + 7)
            
            for file in os.listdir(fr'{path}/Configs/{servername}/absences/'):
                parsed_date = datetime.strptime(file, "%Y_%m_%d.absence.txt")
                
                if parsed_date >= last_week_start and len(embed_fields) < 25:
                    lines = []
                    with open(fr'{path}/Configs/{servername}/absences/{file}', encoding='utf8') as f:
                        for line in f:
                            if line is not None and line != "":
                                lines.append(line.strip())

                    EmbedText = ""
                    for entry in lines:
                        line_split = entry.split("$")
                        text = f"{line_split[0]} | Eintrag vom: {line_split[4]}\nGrund: {line_split[1]}\nZeitraum: {line_split[2]} - {line_split[3]}\n" 
                        EmbedText = EmbedText + text + "\n"

                    formatted_date = parsed_date.strftime("%d.%m.%Y")
                    embed_fields.append([formatted_date, f'```\n{EmbedText}```', False])

                else:
                    os.remove(fr'{path}/Configs/{servername}/absences/{file}')


            Embed = await createembednoconf(
                title = "24/7 - Abwesenheitsliste",
                description = "Hier sehen Sie alle eingetragegen Abwesenheiten der Teamler von 24/7",
                color = "113c97",
                url = None,
                fields = list(reversed(embed_fields)),
                footer = "Herzliche Grüße Ihr 24seven Team",
                thumbnail = None,
                picture = None,
                )

            await ctx.respond(embed=Embed, ephemeral=True)


    @commands.slash_command(name="neueabwesenheit", description="Erstellt einen Neuen Eintrag für Abwesenheiten.")
    @option("Grund", description="Geben Sie den Grund an, wesshalb Sie in dem angegeben Zeitraum abwesend sind.", required=True)
    @option("Startdatum", description="Geben Sie hier das Datum an, ab dem Sie abwesend sein werden.", required=True)
    @option("Enddatum", description="Geben Sie hier das Datum an, ab dem Sie wieder Anwesend sein werden.", required=True)
    @option("Startzeit", description="Geben Sie hier die Zeit an, ab dem Sie Abwesend sein werden.", required=False)
    @option("Endzeit", description="Geben Sie hier die Zeit an, ab dem Sie wieder Anwesend sein werden.", required=False)
    async def new_abwesenheiten(
        self, ctx: discord.ApplicationContext,
        reason: str,
        startdate: str,
        enddate: str,
        starttime: str = "",
        endtime: str = "",
        ):
        with open(fr'{path}/Configs/server.yaml', encoding='utf8') as f:
            data = yaml.load(f, Loader=SafeLoader)
            try:
                servername = next(item["name"] for item in data["Config.Server"] if str(ctx.guild.id) == str(item["guild"]))
            except StopIteration:
                await ctx.respond("Error in Syntax", ephemeral=True)
                return
            
            with open(fr'{path}/Configs/{servername}/absences.yaml', encoding='utf8') as f:
                data = yaml.load(f, Loader=SafeLoader)

            if data["Config.Enabled"] == True:
                pass

            else:
                await ctx.respond("Diese Funktion ist für diesen Server nicht Aktiviert!", ephemeral=True)
                return
            
            founder = ctx.guild.get_member(475256776296497153)
        
            double_entry_text = f"Ein oder mehr Abwesenheitseinträge sind bereits Vorhanden. Diese können derzeit nicht überschrieben werden. Bitte kontakitiere {founder.mention} um die Abwesenheitszeiten anzupassen. Folgende Zeiten sind bereits vorhanden:\n\n"
            double_entry = False
            count = 0
            count_double = 0
            
            if starttime is None or starttime == "":
                starttime = "00:00"

            if endtime is None or endtime == "":
                endtime = "00:00"

            start_date_obj = await check_date(startdate)
            end_date_obj = await check_date(enddate)
            start_time_obj = await check_time(starttime)
            end_time_obj = await check_time(endtime)

            if start_time_obj and end_time_obj == True and start_date_obj <= end_date_obj:
                current_date = start_date_obj
                while current_date <= end_date_obj:
                    count += 1
                    formatted_date = current_date.strftime("%Y_%m_%d")
                    formed_date = current_date.strftime("%d.%m.%Y")

                    if os.path.exists(fr'{path}/Configs/{servername}/absences/{formatted_date}.absence.txt'):
                        with open(fr'{path}/Configs/{servername}/absences/{formatted_date}.absence.txt', 'r') as file:
                            existing_lines = file.readlines()
                            for line in existing_lines:
                                if f"[{ctx.author.name}]$" in line:
                                    double_entry_text += str(formed_date) + "\n"
                                    double_entry = True
                                    count_double += 1
                                    break
                            else:
                                file.close()
                                with open(fr'{path}/Configs/{servername}/absences/{formatted_date}.absence.txt', 'a') as file:
                                    datetime_time = datetime.now().strftime("%Y/%m/%d " " %H:%M:%S")
                                    file.write(f"[{ctx.author.name}]${reason}${starttime}${endtime}${datetime_time}$\n")
                        file.close()
                    else:
                        with open(fr'{path}/Configs/{servername}/absences/{formatted_date}.absence.txt', 'w') as file:
                            datetime_time = datetime.now().strftime("%Y/%m/%d " " %H:%M:%S")
                            file.write(f"[{ctx.author.name}]${reason}${starttime}${endtime}${datetime_time}$\n")
                        file.close()

                    current_date += timedelta(days=1)

            else:
                await ctx.respond("Deine Angabe entspricht nicht den Anforderungen. Formate können nur wie folgt angegeben werden:\n\nDatum:\n01.01.1999 / 01-01-1999 / 01/01/1999\n\nZeit:\n10:40", ephemeral=True)
                return

            if double_entry == True and count > count_double:
                await ctx.respond("Ihre Abwesenheit wurde erfolgreich für alle Tage Ohne schon vorhandene Einträge eingetragen. Diese können Sie mit dem befehl /abwesenheiten einsehen", ephemeral=True)
                await ctx.respond(double_entry_text, ephemeral=True)
                return
            elif double_entry == True and count == count_double:
                return
            else:
                await ctx.respond("Ihre Abwesenheit wurde erfolgreich eingetragen. Diese können Sie mit dem befehl /abwesenheiten einsehen", ephemeral=True)
                return


async def check_date(date_str):
    match = re.match(r"(\d{2})[./-](\d{2})[./-](\d{4})", date_str)
    if match:
        day, month, year = map(int, match.groups())
        if 0 < day < 32 and 0 < month < 13 and year >= int(time_year):
            return datetime(year, month, day)
    return datetime(2000, 1, 1)

async def check_time(date_str):
    match = re.match(r"(\d{2})[:](\d{2})", date_str)
    if match:
        hour, minute = map(int, match.groups())
        if 0 <= hour < 24 and 0 <= minute < 60:
            return True
    return False


def setup(bot):
    bot.add_cog(Absences(bot))