import csv
import json
import os
from datetime import datetime
from typing import Any, Dict

from joint_teapot.utils.logger import logger


def generate_scoreboard(
    score_file_path: str, student_name: str, student_id: str, scoreboard_file_path: str
) -> None:
    if not scoreboard_file_path.endswith(".csv"):
        logger.error(
            f"Scoreboard file should be a .csv file, but now it is {scoreboard_file_path}"
        )
        return

    # Load the csv file if it already exists
    if os.path.exists(scoreboard_file_path):
        with open(scoreboard_file_path, newline="") as file:
            reader = csv.reader(file)
            rows = list(reader)
        columns = rows[0]
        data = rows[1:]
    else:
        columns = [
            "",
            "last_edit",  # FIXME:
            # This is just to make changes in the file so that it can be pushed.
            # Only used in development stage. Will be removed in the future.
            "total",
        ]
        data = []

    column_updated = [False] * len(columns)  # Record wether a score has been updated
    # Update data
    with open(score_file_path) as json_file:
        scorefile: Dict[str, Any] = json.load(json_file)

    student = f"{student_name} {student_id}"
    student_found = False
    for row in data:
        if row[0] == student:
            student_row = row  # This is a reference of the original data
            student_found = True
            break
    if not student_found:
        student_row = [student, "", "0"] + [""] * (
            len(columns) - 3
        )  # FIXME: In formal version should be -2
        data.append(student_row)

    for stagerecord in scorefile["stagerecords"]:
        stagename = stagerecord["stagename"]
        for stageresult in stagerecord["stageresults"]:
            name = stageresult["name"]
            for i, result in enumerate(stageresult["results"]):
                score = result["score"]
                colname = f"{stagename}/{name}"
                if len(stageresult["results"]) != 1:
                    colname = f"{colname}/{i}"
                if colname not in columns:
                    columns.append(colname)
                    column_updated.append(True)
                    for row in data:
                        row.append("")
                student_row[columns.index(colname)] = score
                column_updated[columns.index(colname)] = True
    # Score of any unupdated columns should be cleared
    for i, column in enumerate(columns):
        if column in ["", "last_edit", "total"]:
            continue
        if column_updated[i] == False:
            student_row[i] = ""

    total = 0
    for col in columns:
        if col in ["", "total", "last_edit"]:
            continue
        idx = columns.index(col)
        if (student_row[idx] is not None) and (student_row[idx] != ""):
            total += int(student_row[idx])

    student_row[columns.index("total")] = str(total)

    now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    student_row[
        columns.index("last_edit")
    ] = now  # FIXME: Delete this in formal version

    # Sort data by total
    data.sort(key=lambda x: int(x[columns.index("total")]), reverse=True)

    # Write back to the csv file:
    with open(scoreboard_file_path, mode="w", newline="") as file:
        writer = csv.writer(file)
        writer.writerow(columns)
        writer.writerows(data)


def generate_comment(score_file_path: str) -> str:
    # TODO
    return ""