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

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


class Medal(BaseModel):
    current_idx: int = 0
    id: int
    rank: str
    athleteID: int

    def modify_from_key(self, key, value):
        if key == "rank":
            self.rank = value
        if key == "athleteId":
            self.athleteID = int(value)

    def serialize(self):
        return {
            'id': self.id,
            'rank': self.rank,
            'athleteID': self.athleteID,
        }


def load_medal_from_json(path: str) -> dict[int, Medal]:
    if not os.path.isfile(path):
        Medal.current_idx = 0
        return {}
    with open(path, "r") as file:
        content = file.read()
    list_test = json.loads(content)
    if len(list_test) != 0:
        Medal.current_idx = list_test[-1]['id']
    else:
        Medal.current_idx = 0
    print(Medal.current_idx)
    obj: dict[int, Medal] = {}
    for element in list_test:
        obj[int(element['id'])] = Medal(id=int(element['id']),
                                        rank=element['rank'], athleteID=element['athleteID'])
    return obj


def save_medal_in_json(path: str, medal_dict: dict[int, Medal]):
    medal_list = []
    for _, value in medal_dict.items():
        medal_list.append(value.serialize())
    with open(path, "w") as file:
        file.write(json.dumps(medal_list))


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


@ app.route('/medal', methods=['GET', 'POST'])
def handleMedal():
    if request.method == 'POST':
        return handleMedalPOST()
    else:
        return handleMedalGET()


def handleMedalPOST():
    medal_list: dict[int, Medal] = load_medal_from_json(SAVE_FILE)
    try:
        post_data = request.get_json()
        id = Medal.current_idx + 1
        rank = post_data['rank']
        if rank not in ['gold', 'silver', 'bronze']:
            return jsonify({"Message": "Bad request"}), 400
        athleteID = post_data['athleteID']
        medal = Medal(id=id, rank=rank, athleteID=athleteID)
        medal_list[medal.id] = medal
        Medal.current_idx += 1
        save_medal_in_json(SAVE_FILE, medal_list)
    except Exception:
        return jsonify({"Message": "Bad request"}), 400
    return jsonify({'id': medal.id}), 200


def handleMedalGET():
    medal_list: dict[int, Medal] = load_medal_from_json(SAVE_FILE)
    ret: list(Medal) = []
    for _, val in medal_list.items():
        ret.append(val.serialize())
    return jsonify(ret)


@ app.route('/medal/<id>', methods=['GET', 'PATCH', 'DELETE'])
def handleMedalId(id: int):
    if request.method == 'GET':
        return handleMedalIdGET(id)
    elif request.method == 'PATCH':
        return handleMedalIdPATCH(id)
    else:
        return handleMedalIdDELETE(id)


def handleMedalIdGET(id: int):
    medal_list: dict[int, Medal] = load_medal_from_json(SAVE_FILE)
    try:
        medal = medal_list[int(id)]
        return jsonify(medal.serialize())
    except Exception:
        return jsonify({'Message': 'Not found'}), 404


def handleMedalIdPATCH(id: int):
    try:
        medal_list: dict[int, Medal] = load_medal_from_json(SAVE_FILE)
        patch_data = request.get_json()
        key_list = ['rank', 'athleteID']
        _ = medal_list[int(id)]
        for key, value in patch_data.items():
            if key in key_list:
                if key == "rank":
                    if value in ['gold', 'bronze', 'silver']:
                        medal_list[int(id)].modify_from_key(key, value)
                    else:
                        return jsonify({'Message': 'Bad request'}), 400
                else:
                    medal_list[int(id)].modify_from_key(key, value)
            else:
                return jsonify({'Message': 'Bad request'}), 400
        save_medal_in_json(SAVE_FILE, medal_list)
        return "OK", 200
    except Exception:
        return jsonify({'Message': 'Not found'}), 404


def handleMedalIdDELETE(id: int):
    medal_list: dict[int, Medal] = load_medal_from_json(SAVE_FILE)
    try:
        medal_list.pop(int(id))
        save_medal_in_json(SAVE_FILE, medal_list)
    except Exception:
        return jsonify({"Message": "Not found"})

    return "Ok"