from typer import Typer, Exit, Option
from requests import post, get
from typing import List, Optional
from datetime import datetime

__app_name__ = 'ces'
__version__ = '0.0.1'
app = Typer()


faculty_api_url = r'http://127.0.0.1:8000/faculty/'
outcomes_api_url = r'http://127.0.0.1:8000/outcomes/'
response_api_url = r'http://127.0.0.1:8000/responses/'
sections_api_url = r'http://127.0.0.1:8000/sections/'
courses_api_url = r'http://127.0.0.1:8000/courses/'
gen_questions_api_url = r'http://127.0.0.1:8000/gen_questions/'
users_api_url = r'http://127.0.0.1:8000/users/'
students_in_sections_api_url = r'http://127.0.0.1:8000/students_in_sections/'
students_api_url = r'http://127.0.0.1:8000/students/'
subject_areas_api_url = r'http://127.0.0.1:8000/subject_areas/'
major_questions_api_url = r'http://127.0.0.1:8000/major_questions/'
semesters_api_url = r'http://127.0.0.1:8000/semesters/'
majors_api_url = r'http://127.0.0.1:8000/majors/'
token = '9684afad5d92407097a65bd1b74079ca9d5be879'
headers = {'Authorization': f'Token {token}'}
def get_file_data_all_lines(csv: str):
    f = open(csv, 'r')
    lines = f.readlines()
    f.close()
    return lines

def get_input(prompt: str):
    return input(prompt).strip()

@app.command('iaf')
def add_faculty():
    '''
    Interactively add faculty.\n
    You will be prompted for the faculty's username,pid,first name,last name, and role    
    '''

    add_more = 'Y'
    while add_more in ['Y', 'y']:
        username = get_input('Username:')
        pid = int(get_input('PID:'))
        first_name = get_input('First name:')
        last_name = get_input('Last name:')
        password = f'{first_name[0]}{pid}{last_name[0]}'
        role = get_input('Role:')
        faculty_data = {'user': {'username': username, 'pid': pid, 'first_name': first_name, 'last_name': last_name, 'password': password, 'email': None}, 'role': role}
        resp = post(faculty_api_url, json=faculty_data, headers=headers)
        print(resp.text)
        add_more = get_input('Add more? [Y/y/N/n]')

@app.command('iao')
def add_outcomes():
    '''
    Interactively add outcomes.\n
    You will be prompted for the outcome's heading, # questions, questions, and semester
    '''
    add_more = 'Y'
    while add_more in ['Y', 'y']:
        heading = get_input('Heading:')
        num_q = int(get_input('Number of questions:'))
        questions = [''] * num_q
        for q in range(num_q):
            current_q = get_input(f'Question {q + 1}:')
            questions[q] = current_q
        
        year = int(get_input('Year:'))
        month = int(get_input('Month number:'))
        resp = get(f'{semesters_api_url}{year}/{month}/', headers=headers)
        if 200 <= resp.status_code <= 299:
            semester_pk = resp.json()['id']
        else:
            semester_data = {'month': month, 'year': year}
            resp = post(semesters_api_url, json=semester_data, headers=headers)
            semester_pk = resp.json()['id']                
        
        outcomes_data = {'heading': heading, 'questions': questions, 'semester': semester_pk}
        resp = post(outcomes_api_url, json=outcomes_data, headers=headers)
        print(resp.text)
        add_more = get_input('Add more? [Y/y/N/n]')


@app.command('ias')
def add_student():
    '''
    Interactively add students. \n
    You will be prompted for username,pid,first name,last name,degree,subject_area
    '''
    
    add_more = 'Y'
    while add_more in ['Y', 'y']:
        username = get_input('Username:')
        pid = int(get_input('PID:'))
        first_name = get_input('First name:')
        last_name = get_input('Last name:')
        password = f'{first_name[0]}{pid}{last_name[0]}'
        degree = get_input('Degree:')
        subject_area = get_input('Subject area:')        
        resp = get(f'{users_api_url}{username}/', headers=headers)
        if not (200 <= resp.status_code <= 299):
            user_data = {'username': username, 'pid': pid, 'first_name': first_name, 'last_name': last_name, 'password': password, 'email': None}
            resp = post(users_api_url, json=user_data, headers=headers)
            print(resp.text)
            user_pk = resp.json()['username']
        else:
            user_pk = resp.json()['username']
        
        resp = get(f'{majors_api_url}{degree}/{subject_area}/', headers=headers)
        if not (200 <= resp.status_code <= 299):
            major_data = {'degree': degree, 'subject_area': subject_area}
            resp = post(majors_api_url, json=major_data, headers=headers)
            print(resp.text)
            major_pk = resp.json()['id']
        else:
            major_pk = resp.json()['id']
        
        student_data = {'user': user_pk, 'major': major_pk}
        resp = post(students_api_url, json=student_data, headers=headers)
        print(resp.text)
        add_more = get_input('Add more? [Y/y/N/n]')

@app.command('iasa')
def add_subject_area():
    ''''
    Interactively add subject areas. \n
    You will be prompted for title of subject area,and area coordinator username
    '''
    add_more = 'Y'
    while add_more in ['Y', 'y']:
        title = get_input('Title:')
        coordinator = get_input('Coordinator username:')
        resp = get(f'{faculty_api_url}{coordinator}/', headers=headers)
        if resp.status_code == 200:
            subject_area_data = {'title': title, 'coordinator': coordinator}
            resp = post(subject_areas_api_url, json=subject_area_data, headers=headers)
            print(resp.text)
        else:
            print('Unable to find coordinator')
        add_more = get_input('Add more? [Y/y/N/n]')
    
        

@app.command('bas')
def csv_bulk_add_student(csv: str):
    '''
    Bulk add students given the path of a comma-separated values file.\n
    The first line of the csv file is ignored.\n
    Each line is ended with a comma \',\'.\n

    csv file line format:\n
        username,pid,first name,last name,degree,subject_area,
    \n    
    Command input:\n
        csv:str -> path of the csv file\n
    Command Output:\n
        None    
    '''
    
    lines = get_file_data_all_lines(csv)
    n = len(lines)
    i = 1
    while i < n:
        line = lines[i].split(',')
        if len(line) != 7:
            i += 1
            continue
        username = line[0]
        pid = line[1]
        f_name = line[2]
        l_name = line[3]
        degree = line[4]
        subject_area = line[5]
        user_resp = get(f'{users_api_url}{username}/', headers=headers)
        if not (200 <= user_resp.status_code <= 299):
            user_data = {'username': username, 'pid': pid, 'first_name': f_name, 'last_name': l_name, 'password': f'{f_name[0]}{pid}{l_name[0]}', 'email': ' '}
            user_resp = post(users_api_url, json=user_data, headers=headers)
            if not (200 <= user_resp.status_code <= 299):
                i += 1
                continue

        major_resp = get(f'{majors_api_url}{degree}/{subject_area}/', headers=headers)
        if not (200 <= major_resp.status_code <= 299):
            majors_data = {'degree': degree, 'subject_area': subject_area}
            major_resp = post(majors_api_url, json=majors_data, headers=headers)
            if not (200 <= major_resp.status_code <= 299):
                i += 1
                continue
        majors_pk = major_resp.json()['id']
        students_data = {'user': username, 'major': majors_pk}
        post(students_api_url, json=students_data, headers=headers)
        i += 1                            



@app.command('bac')
def csv_bulk_add_course(file: str):
    '''
    Bulk add courses given the path of a comma-separated values file.\n
    The first line of the csv file is ignored.\n
    Each line is ended with a comma \',\' and each record is ended with a \'%\' in a new line.

    csv file line format:\n
        course_number,course_name,subject_area,year,month,\n
        heading,number_of_questions(Q),\n
        question1\n
        question2\n
        question3\n
        question4\n
        ...\n
        questxonQ\n
        %
    
    '''

    lines = get_file_data_all_lines(file)
    n = len(lines)
    i = 1
    while i < n:
        line = lines[i].split(',')
        if len(line) != 6:
            raise ValueError('Not enough values in the line')

        skip = i
        while skip < n and lines[skip][0] != '%':
            skip += 1
        
        course_number = line[0]
        course_name = line[1]
        subject_area = line[2]
        year = int(line[3])
        month = int(line[4])
        semester_data = {'month': month, 'year': year}
        resp_semester = post(semesters_api_url, json=semester_data, headers=headers)
        if resp_semester.status_code <= 199 or resp_semester.status_code >= 300:
            resp_semester = get(f'{semesters_api_url}{year}/{month}/', headers=headers)
            if 200 <= resp_semester.status_code <= 299:
                semester_pk = resp_semester.json()['id']
            else:
                i = skip + 1
                continue
        else:
            semester_pk = resp_semester.json()['id']

        course_resp = get(f'{courses_api_url}{course_number}/{year}/{month}/', headers=headers)
        if 200 <= course_resp.status_code <= 299:
            i = skip + 1
            continue

        j = i + 1
        outcomes_pks = []
        while j < skip:
            line = lines[j].split(',')
            heading = line[0]
            num_questions = int(line[1])
            resp_outcomes = get(f'{outcomes_api_url}{heading}/{year}/{month}/', headers=headers)
            if 200 <= resp_outcomes.status_code <= 299:
                outcomes_pk = resp_outcomes.json()['id']
                outcomes_pks.append(outcomes_pk)
                j += num_questions + 1
            else:
                k = j + 1
                questions = []
                while k < min(n, j + num_questions + 1):
                    questions.append(lines[k])
                    k += 1                
                j = k     
                outcomes_data = {'heading': heading, 'questions': questions, 'semester': semester_pk}
                resp_outcomes = post(outcomes_api_url, json=outcomes_data, headers=headers)
                if 200 <= resp_outcomes.status_code <= 299:
                    outcomes_pk = resp_outcomes.json()['id']
                    outcomes_pks.append(outcomes_pk)
        i = skip + 1

        courses_data = {'number': course_number, 'name': course_name, 'subject_area': subject_area, 'semester': semester_pk, 'outcomes': outcomes_pks}
        post(courses_api_url, json=courses_data, headers=headers)




def _version_callback(value: bool) -> None:

    if value:

        print(f"{__app_name__} v{__version__}")

        raise Exit()


@app.callback()
def main(

    version: Optional[bool] = Option(

        None,

        "--version",

        "-v",

        help="Show the application's version and exit.",

        callback=_version_callback,

        is_eager=True,

    )

) -> None:

    return

if __name__ == '__main__':
	app(prog_name=__app_name__)
