import getpass
import os
import time
from multiprocessing import AuthenticationError

import grpc
import jwt
import requests

from .exception import P90ConnectionError


def login(username=None, password=None) -> grpc.CallCredentials:
    """Login to PV Lighthouse and return call credentials.

    Raises AuthenticationError or P90ConnectionError if authentication fails.
    """
    try:
        # Check for existing valid token
        if os.path.exists(".pvlToken"):
            with open(".pvlToken", encoding="utf-8") as token_file:
                token = token_file.read()
            decoded = jwt.decode(token, options={"verify_signature": False})
            exp_time = decoded.get("exp")
            if exp_time is not None and int(time.time()) < int(exp_time):
                return grpc.access_token_call_credentials(token)

        # Get user credentials
        if not username:
            username = input("Enter username:")

        if not password:
            password = getpass.getpass("Enter password:")

        # Request new token
        post_data = {"grant_type": "password", "username": username, "password": password}
        r = requests.post("https://www.pvlighthouse.com.au/Token", data=post_data, timeout=30)
        r.raise_for_status()
        jwt_obj = r.json()
        new_token = jwt_obj["access_token"]

        # Save token for future use
        with open(".pvlToken", "w", encoding="utf-8") as f:
            f.write(new_token)
        return grpc.access_token_call_credentials(new_token)

    except (requests.RequestException, requests.HTTPError) as e:
        print(f"Authentication failed - network error: {e}")
        raise AuthenticationError("Failed to connect to PV Lighthouse service") from e
    except (jwt.InvalidTokenError, KeyError) as e:
        print(f"Authentication failed - token error: {e}")
        raise AuthenticationError("Failed to connect to PV Lighthouse service") from e
    except OSError as e:
        print(f"Authentication failed - file error: {e}")
        raise P90ConnectionError("Failed to connect to PV Lighthouse service") from e
    except Exception as e:
        print(f"Authentication failed - unexpected error: {e}")
        raise P90ConnectionError("Failed to connect to PV Lighthouse service") from e
