import requests
import ujson
from .check import status_info, check_apikey
from .error import (
    APIKeyNotFound,
    MissingRequiredValues,
    AuthenticationKeyInvaild,
    ServiceNotFound,
    LocationValueTypeInvaild,
    CannotExceed1000,
    DailyTrafficLimit,
    ServerError,
    DatabaseConnectionError,
    SQLStatementError,
    LimitUseAuthenticationkey,
    DataNotFound,
    HTTPException,
)


class SyncHttp:
    def __init__(self, KEY, Type, pIndex, pSize, force):
        if force is False:
            check_apikey(KEY)

        self.requirement_query = self.requirement(KEY, Type, pIndex, pSize)

    def request(self, url, query) -> dict:
        base_url = "https://open.neis.go.kr/hub/"
        URL = base_url + url + self.requirement_query + query
        r = requests.get(URL)
        response = r.text
        try:
            data = ujson.loads(response)
        except Exception:
            raise HTTPException(r.code, "API서버로부터 잘못된 응답을 받았습니다. 서버 상태를 확인해주세요")
        code, msg = status_info(data, url)

        if code == "INFO-000":
            return data

        if code == "ERROR-300":
            raise MissingRequiredValues(code, msg)
        elif code == "ERROR-290":
            raise AuthenticationKeyInvaild(code, msg)
        elif code == "ERROR-310":
            raise ServiceNotFound(code, msg)
        elif code == "ERROR-333":
            raise LocationValueTypeInvaild(code, msg)
        elif code == "ERROR-336":
            raise CannotExceed1000(code, msg)
        elif code == "ERROR-337":
            raise DailyTrafficLimit(code, msg)
        elif code == "ERROR-500":
            raise ServerError(code, msg)
        elif code == "ERROR-600":
            raise DatabaseConnectionError(code, msg)
        elif code == "ERROR-601":
            raise SQLStatementError(code, msg)
        elif code == "INFO-300":
            raise LimitUseAuthenticationkey(code, msg)
        elif code == "INFO-200":
            raise DataNotFound(code, msg)
        else:
            raise HTTPException(code, msg)

    @classmethod
    def requirement(cls, KEY, Type, pIndex, pSize) -> tuple:
        apikey = f"?KEY={KEY}"
        reqtype = f"&Type={Type}"
        pindex = f"&pindex={pIndex}"
        psize = f"&pSize={pSize}"
        return apikey + reqtype + pindex + psize

    def schoolInfo(self, query) -> dict:
        return self.request("schoolInfo", query)

    def mealServiceDietInfo(self, query) -> dict:
        return self.request("mealServiceDietInfo", query)

    def SchoolSchedule(self, query) -> dict:
        return self.request("SchoolSchedule", query)

    def acaInsTiInfo(self, query) -> dict:
        return self.request("acaInsTiInfo", query)

    def timeTable(self, schclass, query) -> dict:
        return self.request(f"{schclass}Timetable", query)

    def classInfo(self, query) -> dict:
        return self.request("classInfo", query)

    def schoolMajorinfo(self, query) -> dict:
        return self.request("schoolMajorinfo", query)

    def schulAflcoinfo(self, query) -> dict:
        return self.request("schulAflcoinfo", query)

    def tiClrminfo(self, query) -> dict:
        return self.request("tiClrminfo", query)

    def spsTimetable(self, query) -> dict:
        return self.request("spsTimetable", query)
