"""Add Mail.Send permission to the app registration and grant admin consent."""
import json
import sys
import urllib.request
import urllib.parse
import urllib.error
import ssl

TENANT_ID = "5c53ae9f-7071-4248-b834-8685b646450f"
APP_ID = "fabb3421-8b34-484b-bc17-e46de9703418"
APP_SECRET = "~QJ8Q~NyQSs4OcGqHZyPrA2CVnq9KBfKiimntbMO"
GRAPH_APP_ID = "00000003-0000-0000-c000-000000000000"  # Microsoft Graph

ctx = ssl.create_default_context()


def get_token():
    data = urllib.parse.urlencode({
        "client_id": APP_ID,
        "scope": "https://graph.microsoft.com/.default",
        "client_secret": APP_SECRET,
        "grant_type": "client_credentials",
    }).encode()
    req = urllib.request.Request(
        f"https://login.microsoftonline.com/{TENANT_ID}/oauth2/v2.0/token",
        data=data, method="POST"
    )
    with urllib.request.urlopen(req, context=ctx) as resp:
        return json.loads(resp.read())["access_token"]


def graph_get(token, url):
    req = urllib.request.Request(url, headers={"Authorization": f"Bearer {token}"})
    with urllib.request.urlopen(req, context=ctx) as resp:
        return json.loads(resp.read())


def graph_post(token, url, payload=None):
    headers = {"Authorization": f"Bearer {token}"}
    body = None
    if payload:
        headers["Content-Type"] = "application/json"
        body = json.dumps(payload).encode()
    else:
        body = b""
    req = urllib.request.Request(url, data=body, headers=headers, method="POST")
    try:
        with urllib.request.urlopen(req, context=ctx) as resp:
            content = resp.read()
            return json.loads(content) if content else {}
    except urllib.error.HTTPError as e:
        body = e.read().decode()
        try:
            return json.loads(body)
        except:
            return {"error": {"message": body, "code": str(e.code)}}


token = get_token()
print("[OK] Token acquired")

# Find our app's service principal
filter_val = urllib.parse.quote(f"appId eq '{APP_ID}'")
url = f"https://graph.microsoft.com/v1.0/servicePrincipals?$filter={filter_val}"
data = graph_get(token, url)
if not data.get("value"):
    print("[ERROR] Could not find our service principal")
    print(json.dumps(data, indent=2)[:1000])
    sys.exit(1)
our_sp_id = data["value"][0]["id"]
print(f"[OK] Our SP ID: {our_sp_id}")

# Find Microsoft Graph service principal
filter_val2 = urllib.parse.quote(f"appId eq '{GRAPH_APP_ID}'")
url2 = f"https://graph.microsoft.com/v1.0/servicePrincipals?$filter={filter_val2}"
data2 = graph_get(token, url2)
graph_sp_id = data2["value"][0]["id"]
print(f"[OK] Graph SP ID: {graph_sp_id}")

# Find Mail.Send role
app_roles = data2["value"][0].get("appRoles", [])
mail_send_id = None
for role in app_roles:
    if role.get("value") == "Mail.Send":
        mail_send_id = role["id"]
        break

if not mail_send_id:
    print("[ERROR] Mail.Send role not found")
    sys.exit(1)
print(f"[OK] Mail.Send role ID: {mail_send_id}")

# Grant the appRoleAssignment (admin consent)
payload = {
    "principalId": our_sp_id,
    "resourceId": graph_sp_id,
    "appRoleId": mail_send_id
}
url3 = f"https://graph.microsoft.com/v1.0/servicePrincipals/{our_sp_id}/appRoleAssignments"
result = graph_post(token, url3, payload)
if result.get("id"):
    print(f"[SUCCESS] Mail.Send permission granted! Assignment ID: {result['id']}")
elif "already exists" in str(result.get("error", {}).get("message", "")):
    print("[INFO] Mail.Send permission already assigned")
else:
    print(f"[RESULT] Response: {json.dumps(result, indent=2)[:1000]}")
