import socket
import os
import hashlib
import json
import requests

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5, AES

from server.vars import Var


def login(self):
    print(f"⚙️  Step 1: Receive Login Start")
    # Step 1: Receive Login Start
    packet_id, data = self.recv_packet()
    if packet_id != 0x00:
        raise Exception("Expected Login Start")

    name_len, offset = Var.read_varint_from_bytes(data)
    username = data[offset:offset + name_len].decode("utf-8")
    print(f"🔓 Login Start received for username: {username}")
    self.username = username



    print(f"⚙️  Step 2: Generate RSA keypair and verify token")
    # Step 2: Generate RSA keypair and verify token
    rsa_key = RSA.generate(1024)
    public_key = rsa_key.publickey().export_key(format='DER')
    verify_token = os.urandom(16)



    print(f"⚙️  Step 3: Send Encryption Request")
    # Step 3: Send Encryption Request
    authenticate = True
    payload = (
        Var.write_string("") +
        Var.write_varint(len(public_key)) + public_key +
        Var.write_varint(len(verify_token)) + verify_token
        + b'\x01' if authenticate else b'\x00'
    )
    self.send_packet(0x01, payload)



    print(f"⚙️  Step 4: Receive Encryption Response")
    # Step 4: Receive Encryption Response
    packet_id, data = self.recv_packet()
    if packet_id != 0x01:
        raise Exception("Expected Encryption Response")

    secret, rest = Var.read_varint_bytes(data)
    token, _ = Var.read_varint_bytes(rest)



    print(f"⚙️  Step 5: Decrypt shared secret and verify token")
    # Step 5: Decrypt shared secret and verify token
    cipher = PKCS1_v1_5.new(rsa_key)
    shared_secret = cipher.decrypt(secret, None)
    decrypted_token = cipher.decrypt(token, None)

    if decrypted_token != verify_token:
        raise Exception("Verify token mismatch")



    print(f"⚙️  Step 6: Mojang Authentication")
    # Step 6: Mojang Authentication
    sha1 = hashlib.sha1()
    sha1.update(b"")  # empty server ID
    sha1.update(shared_secret)
    sha1.update(public_key)
    server_hash = Var.java_hex(sha1.digest())

    resp = requests.get(
        "https://sessionserver.mojang.com/session/minecraft/hasJoined",
        params={"username": username, "serverId": server_hash}
    )
    if resp.status_code != 200:
        raise Exception("Mojang authentication failed")

    profile = resp.json()
    uuid = profile["id"]
    # name = profile["name"]



    # AES Encryption (Step 7)
    print(f"⚙️  Step 7: Enable AES encryption (correct initialization)")
    iv = shared_secret[:16]
    aes = AES.new(shared_secret, AES.MODE_CFB, iv=iv, segment_size=128)
    self.encrypt_cipher = aes
    self.decrypt_cipher = aes
    self.encryption_enabled = True

    # Verify Token Validation (Step 5)
    if decrypted_token != verify_token:
        raise Exception("Verify token mismatch: Decrypted token does not match original")


    # Step 8: Send Login Success
    print("⚙️  Step 8: Send Login Success")

    # Player's UUID and Username
    uuid = profile["id"]  # Player's UUID as a 16-byte string

    import base64
    # Player's profile properties (e.g., skin textures)
    # properties = [
    #     {
    #         "name": "textures",
    #         "value": base64.b64encode(json.dumps({
    #             "timestamp": 0,
    #             "profileId": uuid,
    #             "profileName": username,
    #             "textures": {
    #                 "SKIN": {
    #                     "url": "http://textures.minecraft.net/texture/skin_texture_hash"
    #                 }
    #             }
    #         }).encode('utf-8')).decode('utf-8'),
    #         "signature": ""  # Optional: Include if you have a signature
    #     }
    # ]

    properties = profile.get("properties", [])

    # Encode UUID and Username lengths
    uuid_bytes = uuid.encode('utf-8')
    username_bytes = username.encode('utf-8')
    uuid_length = len(uuid_bytes)
    username_length = len(username_bytes)

    # Encode properties
    properties_data = b""
    for prop in properties:
        name_bytes = prop['name'].encode('utf-8')
        value_bytes = prop['value'].encode('utf-8')  # Already base64 string
        properties_data += Var.write_varint(len(name_bytes)) + name_bytes
        properties_data += Var.write_varint(len(value_bytes)) + value_bytes

        if prop.get('signature'):
            signature_bytes = prop['signature'].encode('utf-8')
            properties_data += Var.write_varint(len(signature_bytes)) + signature_bytes

    # Construct the packet
    packet_data = (
        Var.write_varint(uuid_length) + uuid_bytes +
        Var.write_varint(username_length) + username_bytes +
        Var.write_varint(len(properties)) + properties_data
    )

    # Send the packet
    self.send_packet(0x02, packet_data)

    packet_id, data = self.recv_packet()
    print(f"📦 Received packet: ID={packet_id:02X}, Data={data.hex()}")

    id, _ = self.recv_packet()
    if id == 0x03:
        print("✅  Login Success")
    else:
        raise Exception(f"Login error | packet_id: {id} | packet_data: {_}")