import json
import os
from flask import Flask, request, jsonify
from pydantic import BaseModel

app = Flask(__name__)
SAVE_FILE: str = "./data/athlete.json"


class Athlete(BaseModel):
    current_idx: int = 0
    id: int
    name: str
    surname: str
    email: str
    country: str
    isDisabled: bool

    def modify_from_key(self, key, value):
        if key == "name":
            self.name = value
        if key == "surname":
            self.surname = value
        if key == "email":
            self.email = value
        if key == "country":
            self.country = value
        if key == "isDisabled":
            self.isDisabled = bool(value)

    def serialize(self):
        return {
            'id': self.id,
            'name': self.name,
            'surname': self.surname,
            'email': self.email,
            'country': self.country,
            'isDisabled': self.isDisabled,
        }


def load_athlete_from_json(path: str) -> dict[int, Athlete]:
    if not os.path.isfile(path):
        Athlete.current_idx = 0
        return {}
    with open(path, "r") as file:
        content = file.read()
    list_test = json.loads(content)
    if len(list_test) != 0:
        Athlete.current_idx = list_test[-1]['id']
    else:
        Athlete.current_idx = 0
    obj: dict[int, Athlete] = {}
    for element in list_test:
        obj[int(element['id'])] = Athlete(
            id=int(element['id']), name=element['name'],
            surname=element['surname'], email=element['email'],
            country=element['country'], isDisabled=bool(element['isDisabled']))
    return obj


def save_athlete_in_json(path: str, athlete_dict: dict[int, Athlete]):
    athlete_list = []
    for _, value in athlete_dict.items():
        athlete_list.append(value.serialize())
    with open(path, "w") as file:
        file.write(json.dumps(athlete_list))


@ app.route('/')
def root():
    return jsonify({"name": "Jo API", "description": "An API to get information on 2024 olympic games"}), 200


@ app.route('/athlete', methods=['GET', 'POST'])
def handleAthlete():
    if request.method == 'POST':
        return handleAthletePOST()
    else:
        return handleAthleteGET()


def handleAthletePOST():
    athlete_list: dict[int, Athlete] = load_athlete_from_json(SAVE_FILE)
    try:
        post_data = request.get_json()
        id = Athlete.current_idx + 1
        name = post_data['name']
        surname = post_data['surname']
        email = post_data['email']
        country = post_data['country']
        isDisabled = bool(post_data['isDisabled'])
        athlete = Athlete(id=id, name=name, surname=surname,
                          email=email, country=country, isDisabled=isDisabled)
        athlete_list[athlete.id] = athlete
        Athlete.current_idx += 1
        save_athlete_in_json(SAVE_FILE, athlete_list)
    except Exception:
        return jsonify({"Message": "Bad request"}), 400
    return jsonify({'id': athlete.id}), 200


def handleAthleteGET():
    athlete_list: dict[int, Athlete] = load_athlete_from_json(SAVE_FILE)
    ret: list(Athlete) = []
    for _, val in athlete_list.items():
        ret.append(val.serialize())
    return jsonify(ret)


@ app.route('/athlete/<id>', methods=['GET', 'PATCH', 'DELETE'])
def handleAthleteId(id: int):
    if request.method == 'GET':
        return handleAthleteIdGET(id)
    elif request.method == 'PATCH':
        return handleAthleteIdPATCH(id)
    else:
        return handleAthleteIdDELETE(id)


def handleAthleteIdGET(id: int):
    athlete_list: dict[int, Athlete] = load_athlete_from_json(SAVE_FILE)
    try:
        athlete = athlete_list[int(id)]
        return jsonify(athlete.serialize())
    except Exception:
        return jsonify({'Message': 'Not found'}), 404


def handleAthleteIdPATCH(id: int):
    try:
        athlete_list: dict[int, Athlete] = load_athlete_from_json(
            SAVE_FILE)
        patch_data = request.get_json()
        key_list = ['name', 'surname', 'surname',
                    'email', 'country', 'isDisabled']
        _ = athlete_list[int(id)]
        for key, value in patch_data.items():
            if key in key_list:
                athlete_list[int(id)].modify_from_key(key, value)
            else:
                return jsonify({'Message': 'Bad request'}), 400
        save_athlete_in_json(SAVE_FILE, athlete_list)
        return "OK", 200
    except Exception:
        return jsonify({'Message': 'Not found'}), 404


def handleAthleteIdDELETE(id: int):
    athlete_list: dict[int, Athlete] = load_athlete_from_json(SAVE_FILE)
    try:
        athlete_list.pop(int(id))
        save_athlete_in_json(SAVE_FILE, athlete_list)
    except Exception:
        return jsonify({"Message": "Not found"})

    return "Ok"