

import requests
from .session_manager import load_session
from .network import NetworkHelper
from .config import API_BASE_URL, ENDPOINTS, REMOTE_TIMEOUT
from rich.console import Console

console = Console()

class APIClient:
    def __init__(self, base_url=None, endpoints=None):
        self.base_url = (base_url or API_BASE_URL).rstrip("/") + "/"
        self.endpoints = endpoints or ENDPOINTS
        self.session = load_session()
        self.token = self.session.get("token")
        self.sti = self.session.get("sti")
        self.net = NetworkHelper(console)

    # -----------------------
    # Internal helpers
    # -----------------------
    def _url(self, key, **kwargs):
        ep = self.endpoints.get(key)
        if not ep:
            raise KeyError(f"Unknown endpoint: {key}")
        return self.base_url + ep.format(**kwargs)

    def _headers(self, sti=None):
        headers = {"Content-Type": "application/json"}
        # Use the provided sti (if passed) or the one stored in session
        sti = sti or self.sti
        if sti and self.token:
            headers.update({"STI": str(sti), "Authorization": str(self.token)})
        return headers

    # -----------------------
    # Authentication
    # -----------------------
    def register(self, fullname, email, password, phone, country):
        return self.net.request(
            lambda: requests.post(
                self._url("register"),
                json={
                    "fullname": fullname,
                    "email": email,
                    "password": password,
                    "phone": phone,
                    "country": country,
                },
                timeout=REMOTE_TIMEOUT,
            ),
            spinner_text="Registering",
        )

    def sys_logo(self):
        return self.net.request(
            lambda: requests.get(
                self._url("logo"),
                timeout=REMOTE_TIMEOUT,
            ),
            spinner_text="Loading CodeHouse Cloud..."
        )

    def check_email_exist(self, email):
        return self.net.request(
            lambda: requests.post(
                self._url("check_email_exists"),
                json={"email": email},
                timeout=REMOTE_TIMEOUT,
            ),
            spinner_text="Checking if Account Exist",
        )
    def check_phone_exist(self, phone):
        return self.net.request(
            lambda: requests.post(
                self._url("check_phone_exists"),
                json={"phone": phone},
                timeout=REMOTE_TIMEOUT,
            ),
            spinner_text="Checking if Phone number  Exist",
        )

    def verify_email(self, email, token):
        return self.net.request(
            lambda: requests.post(
                self._url("verify_email"),
                json={"email": email, "token": token},
                timeout=REMOTE_TIMEOUT,
            ),
            spinner_text="Verifying email",
        )

    def login(self, sti, password):
        return self.net.request(
            lambda: requests.post(
                # self._url("login"),
                self._url("login"),
                json={"sti": sti, "password": password},
                timeout=REMOTE_TIMEOUT,
            ),
            spinner_text="Logging in",
        )

    # -----------------------
    # Account recovery
    # -----------------------
    def recover_request(self, sti):
        return self.net.request(
            lambda: requests.post(
                self._url("recover_request"),
                json={"sti": sti},
                timeout=REMOTE_TIMEOUT,
            ),
            spinner_text="Requesting recovery token",
        )

    def verify_recovery(self, recovery_token, sti):
        return self.net.request(
            lambda: requests.post(
                self._url("verify_recovery"),
                json={"sti": sti, "recovery_token": recovery_token},
                timeout=REMOTE_TIMEOUT,
            ),
            spinner_text="Verifying recovery token",
        )

    def reset_password(self, sti, recovery_token, new_password):
        return self.net.request(
            lambda: requests.post(
                self._url("reset_password"),
                json={"sti": sti, "recovery_token": recovery_token, "new_password": new_password},
                timeout=REMOTE_TIMEOUT,
            ),
            spinner_text="Resetting password",
        )
    def get_pending_quiz(self, sti):
        return self.net.request(
            lambda: requests.get(
                self._url("pending_quiz", sti=sti),
                headers=self._headers(sti),
                timeout=REMOTE_TIMEOUT,
            ),
            spinner_text="Checking pending quiz...",
        )

    # -----------------------
    # Courses / Quiz
    # -----------------------
    def get_courses(self, sti):
        return self.net.request(
            lambda: requests.get(
                self._url("courses", sti=sti),
                headers=self._headers(sti),
                timeout=REMOTE_TIMEOUT,
            ),
            spinner_text="Fetching courses",
        )

    def get_status(self, course_id, sti):
        return self.net.request(
            lambda: requests.get(
                self._url("quiz_status", course_id=course_id, sti=sti),
                headers=self._headers(sti),
                timeout=REMOTE_TIMEOUT,
            ),
            spinner_text="Checking quiz status",
        )

    def get_question(self, course_id, q_index, sti):
        return self.net.request(
            lambda: requests.get(
                self._url("quiz_question", course_id=course_id, q_index=q_index, sti=sti),
                headers=self._headers(sti),
                timeout=REMOTE_TIMEOUT,
            ),
            spinner_text="Loading question",
        )
    def submit_answer(self, course_id, q_index, selected, time_spent, source="cli", sti=None):

        return self.net.request(
            lambda: requests.post(
                self._url("submit_answer", course_id=course_id, question_id=q_index, sti=sti),
                headers=self._headers(sti),
                json={
                    "q_index": q_index,
                    "answer": selected,
                    "sti": sti or sti,
                    "time_spent": time_spent,
                    "source": "cli",
                },
                timeout=REMOTE_TIMEOUT,
            ),
            spinner_text="Submitting answer",
        )

    def finish(self, course_id, sti):
        return self.net.request(
            lambda: requests.post(
                self._url("finish", course_id=course_id,  sti=sti),
                headers=self._headers(sti),
                timeout=REMOTE_TIMEOUT,
            ),
            spinner_text="Finalizing quiz",
        )

    def get_top(self, course_id, sti):
        return self.net.request(
            lambda: requests.get(
                self._url("top_scorers", course_id=course_id, sti=sti),
                headers=self._headers(sti),
                timeout=REMOTE_TIMEOUT,
            ),
            spinner_text="Loading leaderboard",
        )

    def leaders_top_scorers(self, course_id, sti):
        return self.net.request(
            lambda: requests.get(
                self._url("leaders_top_scorers", course_id=course_id, sti=sti),
                headers=self._headers(sti),
                timeout=REMOTE_TIMEOUT,
            ),
            spinner_text="Loading leaderboard",
        )

    def get_result_pdf(self, result_id, sti):
        return self.net.request(
            lambda: requests.get(
                self._url("result_pdf", result_id=result_id),
                headers=self._headers(sti),
                timeout=REMOTE_TIMEOUT,
            ),
            spinner_text="Preparing your result PDF",
        )

    # -----------------------
    # Wallet
    # -----------------------
    def get_wallet(self):
        return self.net.request(
            lambda: requests.get(
                self._url("wallet"),
                headers=self._headers(),
                timeout=REMOTE_TIMEOUT,
            ),
            spinner_text="Fetching wallet",
        )

    def request_withdraw(self, quizcoin_amount, ngn_rate=None, bank_name=None, account_number=None):
        body = {"quizcoin_amount": quizcoin_amount}
        if ngn_rate:
            body["ngn_rate"] = ngn_rate
        if bank_name:
            body["bank_name"] = bank_name
        if account_number:
            body["account_number"] = account_number

        return self.net.request(
            lambda: requests.post(
                self._url("withdraw"),
                headers=self._headers(),
                json=body,
                timeout=REMOTE_TIMEOUT,
            ),
            spinner_text="Requesting withdrawal",
        )

    def appeal_block(self):
        return self.net.request(
            lambda: requests.post(
                self._url("appeal_block"),
                headers=self._headers(),
                timeout=REMOTE_TIMEOUT,
            ),
            spinner_text="Submitting appeal",
        )

