# διάφορες μικρές βοηθητικές συναρτήσεις
import datetime, time, configparser
from pathlib import Path
import argparse
import logging
from babel.dates import format_datetime, format_date
from openpyxl.utils.cell import range_boundaries
from openpyxl import load_workbook
from pandas import read_excel
from io import BytesIO
from collections import Counter
from beaupy import confirm, prompt, select, select_multiple
from beaupy.spinners import Spinner, DOTS
from rich.console import Console
from importlib.metadata import version, PackageNotFoundError

try:
    version = version("gr_sch_helper")
except PackageNotFoundError:
    version = "unknown"

_config = configparser.ConfigParser()
console = Console()
logger = None
GRADES = ['Α','Β','Γ']

def load_config(path):
    global _config 
    _config.read(path, 'UTF-8')

def set_config(section, name, value):
    global _config
    if not _config.has_section(section):
        _config.add_section(section)
    _config.set(section, name, value)

def get_config(section, option, fallback=None):
    return _config.get(section, option, fallback=fallback)

def set_rconfig(name, value):
    set_config('runtime', name, value)
    
def get_rconfig(name, fallback=None):
    return get_config('runtime',name, fallback=fallback)

def test_fun():
    print(f"Howdy shortM!")

def standard_args(arglist=[]):
    parser = argparse.ArgumentParser(add_help=False, formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('-h', '--help', action="help", help="εμφανίζει το παρόν μήνυμα βοήθειας και σταματά")
    parser.add_argument('-v', '--version', action='version', version=f'%(prog)s - έκδοση:{version}', help="εμφανίζει την έκδοση του προγράμματος και σταματά")
    parser.add_argument('-b', '--batch', action='store_true', help="αυτόματη λειτουργία")
    parser.add_argument('-d', '--debug', action='store_true', help='εμφάνιση μυνημάτων αποσφαλμάτωσης και παράθυρου firefox')
    return parser   

def standard_logging(name, args):
    logger = logging.getLogger(name)
    logger.propagate = False  # avoid double logging if root logger exists

    # Create a single stream handler
    handler = logging.StreamHandler()
    formatter = logging.Formatter('%(message)s')
    handler.setFormatter(formatter)
    logger.addHandler(handler)

    if args.batch and not args.debug:
        logger.setLevel(logging.WARNING)
        handler.setLevel(logging.WARNING)
        set_rconfig("show_spinner", "False")
    else:
        logger.setLevel(logging.INFO)
        handler.setLevel(logging.INFO)
        set_rconfig("show_spinner", "True")
        
        # Σε λειτουργία διόρθωσης προβλημάτων εμφανίζουμε το παράθυρο του firefox                                                                   
    headless = False if args.debug else True
    global schlogger
    schlogger = logger
    return logger, headless

def get_school_year():
    month = datetime.datetime.now().month
    year = datetime.datetime.now().year
    if month < 9:
        return f"{year-1} - {year}"
    else:
        return f"{year} - {year+1}"

def get_date_long():
    date = datetime.datetime.now().date()
    return format_date(date, 'EEEE, d MMMM yyyy', locale='el_GR')

def get_date_filename():
    date = datetime.datetime.now()
    return format_datetime(date, 'yyyy.MM.dd-HH-mm', locale='el_GR')

class ShortCode:
    report_base = "https://app.myschool.sch.gr/Report.bas.aspx?rpt="
    def __init__(self,url,basename):
        self.url = self.report_base + url
        self.basename = basename

def get_folder_files(ext_list):
    file_list = []
    for workfilepath in Path.cwd().iterdir():
        workfile = workfilepath.name
        ext = workfilepath.suffix
        if ext in ext_list:
            file_list.append(workfile)
    file_list.sort(reverse=True)
    return file_list

def set_option_select(msg,option,choice_list):
    if type(choice_list[0]) == type("string"):
        descriptions = choice_list
        choices = choice_list
    elif type(choice_list[0]) == type(("tup","le")):
        descriptions = [x[0] for x in choice_list]
        choices =   [x[1] for x in choice_list]
    console.print(msg)
    ind = select (descriptions, cursor="->", cursor_style="cyan", return_index = True)
    return choices[ind]
    
def load_orologio(path):
    wb = load_workbook(path)
    ws = wb.active
    for cell_group in list(ws.merged_cells.ranges):
        min_col, min_row, max_col, max_row = range_boundaries(str(cell_group))
        top_left_cell_value = ws.cell(row=min_row, column=min_col).value
        ws.unmerge_cells(str(cell_group))
        for row in ws.iter_rows(min_col=min_col, min_row=min_row, max_col=max_col, max_row=max_row):
            for cell in row:
                cell.value = top_left_cell_value
    buffer = BytesIO()
    wb.save(buffer)
    buffer.seek(0)
    return read_excel(buffer,na_filter=False)

        
# όνομα αναφοράς - αριθμός url - όνομα αρχείου (χωρίς κατάληξη)
report_shortcodes = {
    "Γενικά στοιχεία εργαζόμενων":ShortCode("25","rptList"),
    "Γενικά στοιχεία μαθητών":ShortCode("64","rptList"),
    "Κατάσταση Παιδαγωγικών μέτρων":ShortCode("8","rptList"),
    "Τμήματα μαθητή":ShortCode("178","rptList"),
    "Δελτίο κίνησης - 1":ShortCode("175","175"),
    "Αναλυτική κατάσταση απουσιών":ShortCode("2","rptList")
}

def countme(list):
    return Counter(list)

def expand_lessons(lessons):
    expanded = []
    for lesson, n in zip(lessons[0::2], lessons[1::2]):
        expanded.extend([lesson] * int(n))
    return expanded

def sorted_list_diff(lista,listb):
    a_not_b = []
    b_not_a = []
    
    i = j = 0
    while i < len(lista) and j < len(listb):
        if lista[i] < listb[j]:
            a_not_b.append(lista[i])
            i += 1
        elif lista[i] > listb[j]:
            b_not_a.append(listb[j])
            j += 1
        else:
            i += 1
            j += 1
    a_not_b.extend(lista[i:])
    b_not_a.extend(listb[j:])
    return (a_not_b, b_not_a)

def empty_spinner():
    class Dummy:
        def start(self): pass
        def stop(self): pass
    return Dummy()

def spin(msg):
    show_spinner = get_rconfig("show_spinner") == "True"
    if show_spinner:
        spinner = Spinner(DOTS, f"{msg}")
        spinner.start()
    else:
        spinner = empty_spinner()
    return spinner
    
def stop(spinner, msg):
    spinner.stop()
    schlogger.info(f"✓ {msg}")

def assure_deletion(path, timeout=20, interval=0.5):
    path = Path(path)
    end = time.time() + timeout
    while time.time() < end:
        if not path.exists():
            return
        time.sleep(interval)
    raise TimeoutError(f"File still exists: {path}")

