import csv
import argparse
from typing import Callable, get_type_hints
import types
from pathlib import Path



READER_OPTS = {
    'delimiter': ',',
    'quotechar': '"'
}

COURSE = "progI"

ALUMNOS = Path(__file__).parent / 'alumnos.csv'


def do_action(flname: Path,
              action: Callable[[dict[str, str]], None], **kwargs) -> None:
    ### IMPORTANTE: NO Cambiar el nombre del parámetro flname
    with open(flname) as fin:
        reader = csv.DictReader(fin, **READER_OPTS)
        for row in reader:
            action(row, **kwargs)

def feedback(filename: Path, exercise: str) -> None:
    print(f'# Feedback for {exercise}\n')
    pass

def adduser(filename: Path):
    def action(row: dict[str, str]) -> None:
        lastname, firstname = row["NOMBRE COMPLETO"].split(',')
        name = f'{firstname.strip()} {lastname.strip()}'
        username = row["CORREO"].replace("@ucm.es","")
        print(f'adduser --firstuid 2001 --disabled-password --home /home/{COURSE}/{username} --gecos "{name}" {username}')
        print(f'usermod -a -G {COURSE} {username}')
    do_action(filename, action)


def deluser(filename: Path):
    def action(row: dict[str, str]) -> None:
        lastname, firstname = row["NOMBRE COMPLETO"].split(',')
        username = row["CORREO"].replace("@ucm.es","")
        username = row["CORREO"].replace("@ucm.es","")
        print(f'deluser --remove-all-files {username}')
    do_action(filename, action)

def puertos(filename: Path):
    port = 271
    def action(row: dict[str, str]) -> None:
        nonlocal port

        name = row["NOMBRE COMPLETO"]
        username = row['CORREO'].replace('@ucm.es', '')
        print(f'"{name}", {username}, {port}XX')
        port += 1
    do_action(filename, action)

def lista_users(filename: Path):
    def action(row: dict[str, str]) -> None:
        email = row['CORREO']
        username = email.replace('@ucm.es', '')
        print(f'{username}')
    do_action(filename, action)

def moodle(filename: Path, course: str, group: str|None=None):
    def action(row: dict[str, str]) -> None:
        lastname, firstname = row['NOMBRE COMPLETO'].split(',')
        mail = row['CORREO']
        username = mail.replace('@ucm.es', '')
        print(f'{username},"{firstname.strip()}","{lastname.strip()}",{mail},"student",{course}', end='')
        if group is not None:
            print(f',"{group}"', end='')
        print()
    print('username,firstname,lastname,email,role1,course1', end='')
    if group is not None:
        print(f',group1', end='')
    print()

    do_action(filename, action)


CREATE_MONGO_USER = \
    """
db.createUser(
{{
    user: "{user}",
    pwd: "{user}",
    roles: [ {{ role: "readWrite", db: "{user}" }},
             {{ role: "read", db: "test"}},
             {{ role: "read", db: "admin"}}  ]
}})
    """

def mongo_users(filename: Path):
    def action(row: dict[str, str]) -> None:
        email = row["CORREO"].replace("@ucm.es","")
        print(CREATE_MONGO_USER.format(user=email))
    do_action(filename, action)

def nbgrader(filename: Path):
    def action(row: dict[str, str]) -> None:
        name = row["NOMBRE COMPLETO"].split(',')
        firstname = f'{name[1].strip()}'
        lastname = f'{name[0].strip()}'
        email = row["CORREO"]
        username = email.replace("@ucm.es","")
        print(f'nbgrader db student add  --first-name "{firstname}" --last-name "{lastname}" --email {email} {username} --lms-user-id={username}')
    do_action(filename, action)

def exam(filename: Path) -> None:
    students = {}
    def action(row: dict[str, str]) -> None:
        surname, fristname = row["NOMBRE COMPLETO"].split(',')
        name = f'{fristname.strip()} {surname.strip()}'
        moodle_id = row["MOODLE_ID"]
        email = row["CORREO"].replace("@ucm.es", '')
        students[email] = {'name': name, 'moodle_id': moodle_id}

    do_action(filename, action)
    corregidos = Path('corregidos')
    feedback = Path('feedback')
    if not feedback.exists():
        feedback.mkdir()
    for ori in corregidos.glob("*-c.xopp"):
        print(f'# Processing {ori}')
        email = ori.stem.replace('-c', '')
        print(f'# email {email}')
        dest_name = f'{email}.pdf'
        dest = feedback / dest_name
        command = f'xournalpp -p {dest} {ori}'
        print(command)

def get_args() -> argparse.ArgumentParser:
    actions = []
    for name in globals().keys():
        obj = globals()[name]
        if isinstance(obj, types.FunctionType) and \
           get_type_hints(obj).get('filename') is Path:
            actions.append(name)
    parser = argparse.ArgumentParser(description='Proccess student CSV file')
    parser.add_argument('action', type=str,
                        choices=actions,
                        default='adduser')
    parser.add_argument('--filename', type=Path, required=False,
                        default=ALUMNOS,
                        help='CSV file with students')
    parser.add_argument('--exercise', type=str, required=False,
                       help='Exercise identifier')

    parser.add_argument('--course', type=str, required=False,
                          help='Moodle Course identifier')
    parser.add_argument('--group', type=str, required=False,
                          help='Moodle Group identifier')
    return parser

def main():
    args = get_args().parse_args()
    optargs = {}
    for a in vars(args):
        v = getattr(args, a)
        if v and a not in ('action', 'filename'):
            optargs[a] = v
    globals()[args.action](args.filename, **optargs)


if __name__ == '__main__':
    main()
