#!/usr/bin/env python3
"""Upload remaining files to SharePoint via Graph API - files that OneDrive missed."""

import requests
import subprocess
import json

# Get credentials
def get_vault(path, field):
    result = subprocess.run(
        ["bash", ".claude/scripts/vault.sh", "get-field", path, field],
        capture_output=True, text=True, check=True
    )
    return result.stdout.strip()

def get_rmm_token():
    result = subprocess.run(
        ["bash", ".claude/scripts/vault.sh", "get-field", "clients/birth-biologic/gururmm-site-main", "credentials.api_key"],
        capture_output=True, text=True, check=True
    )
    return result.stdout.strip()

# Birth Biologic credentials
tenant_id = "19a568e8-9e88-413b-9341-cbc224b39145"
client_id = "709e6eed-0711-4875-9c44-2d3518c47063"
client_secret = get_vault("msp-tools/computerguru-tenant-admin", "credentials.client_secret")
drive_id = "b!F8BzMb1YakCIWCyWlmczb09LHqtxDxVMpLT6kAwYmsM7NUY4oPLSRq7ng3tJq-E9"
rmm_token = get_rmm_token()
agent_id = "a4524e85-8a07-45d0-91b1-51ce7e2ca74a"

# Get Graph token
print("Getting Graph API token...")
token_data = {
    "client_id": client_id,
    "client_secret": client_secret,
    "scope": "https://graph.microsoft.com/.default",
    "grant_type": "client_credentials"
}
token_resp = requests.post(
    f"https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token",
    data=token_data
)
token_resp.raise_for_status()
graph_token = token_resp.json()["access_token"]
print("[OK] Graph token acquired")

headers = {"Authorization": f"Bearer {graph_token}"}

# Get all files from Datto via RMM
print("\nGetting file list from Datto on VM...")
get_files_script = r'''
$source = "C:\Users\Public\Desktop\Datto Workplace Server Projects\Quality Department"
Get-ChildItem $source -Recurse -File -ErrorAction SilentlyContinue | ForEach-Object {
    $relativePath = $_.FullName.Substring($source.Length + 1).Replace('\', '/')
    [PSCustomObject]@{
        Path = $relativePath
        Size = $_.Length
    }
} | ConvertTo-Json -Compress
'''

rmm_headers = {
    "Authorization": f"Bearer {rmm_token}",
    "Content-Type": "application/json"
}

command_payload = {
    "command_type": "powershell",
    "command": get_files_script,
    "timeout": 300
}

resp = requests.post(
    f"https://rmm.azcomputerguru.com/api/agents/{agent_id}/command",
    headers=rmm_headers,
    json=command_payload
)
resp.raise_for_status()
command_id = resp.json()["command_id"]

# Wait for result
import time
for _ in range(60):
    time.sleep(5)
    resp = requests.get(
        f"https://rmm.azcomputerguru.com/api/commands/{command_id}",
        headers=rmm_headers
    )
    resp.raise_for_status()
    cmd_data = resp.json()

    if cmd_data["status"] in ["completed", "failed"]:
        if cmd_data["status"] == "failed":
            print(f"[ERROR] Command failed: {cmd_data.get('stderr', 'Unknown error')}")
            exit(1)
        break

datto_files_json = cmd_data.get("stdout", "[]")
datto_files = json.loads(datto_files_json) if datto_files_json.strip() else []

if isinstance(datto_files, dict):
    datto_files = [datto_files]

print(f"[OK] Found {len(datto_files)} files in Datto")

# Get all files currently in SharePoint
def get_all_sharepoint_files(item_id=None):
    if item_id:
        url = f"https://graph.microsoft.com/v1.0/drives/{drive_id}/items/{item_id}/children"
    else:
        url = f"https://graph.microsoft.com/v1.0/drives/{drive_id}/root/children"

    files = []
    while url:
        resp = requests.get(url, headers=headers)
        resp.raise_for_status()
        data = resp.json()

        for item in data.get("value", []):
            if "folder" in item:
                files.extend(get_all_sharepoint_files(item["id"]))
            else:
                # Get path from parentReference and name
                path = item.get("name", "")
                if "parentReference" in item and "path" in item["parentReference"]:
                    parent_path = item["parentReference"]["path"]
                    # Extract relative path
                    if "/root:" in parent_path:
                        relative_parent = parent_path.split("/root:")[-1]
                        if relative_parent:
                            path = f"{relative_parent}/{item['name']}"

                files.append({
                    "path": path.strip("/"),
                    "size": item.get("size", 0)
                })

        url = data.get("@odata.nextLink")

    return files

print("\nGetting file list from SharePoint...")
sp_files = get_all_sharepoint_files()
print(f"[OK] Found {len(sp_files)} files in SharePoint")

# Find missing files
sp_paths = {f["path"].lower().replace("\\", "/") for f in sp_files}
missing_files = []

for datto_file in datto_files:
    datto_path = datto_file["Path"].lower().replace("\\", "/")
    if datto_path not in sp_paths:
        missing_files.append(datto_file)

print(f"\n[INFO] Missing files: {len(missing_files)}")

if len(missing_files) == 0:
    print("[OK] No missing files - sync is complete!")
    exit(0)

# Upload missing files
print(f"\nUploading {len(missing_files)} missing files...")

upload_script_template = r'''
$source = "C:\Users\Public\Desktop\Datto Workplace Server Projects\Quality Department"
$driveId = "{drive_id}"
$token = "{token}"
$filePath = "{file_path}"

$fullPath = Join-Path $source $filePath
$uploadPath = $filePath.Replace('\', '/')
$uploadUrl = "https://graph.microsoft.com/v1.0/drives/$driveId/root:/$uploadPath`:/content"

$headers = @{{
    "Authorization" = "Bearer $token"
    "Content-Type" = "application/octet-stream"
}}

try {{
    $fileBytes = [System.IO.File]::ReadAllBytes($fullPath)
    Invoke-RestMethod -Method Put -Uri $uploadUrl -Headers $headers -Body $fileBytes -UseBasicParsing | Out-Null
    Write-Host "[OK] $uploadPath"
}} catch {{
    Write-Host "[ERROR] $uploadPath - $_"
    exit 1
}}
'''

uploaded = 0
errors = []

for missing_file in missing_files[:100]:  # Upload first 100 to start
    file_path = missing_file["Path"]

    upload_script = upload_script_template.format(
        drive_id=drive_id,
        token=graph_token,
        file_path=file_path.replace('"', '`"')
    )

    command_payload = {
        "command_type": "powershell",
        "command": upload_script,
        "timeout": 120
    }

    try:
        resp = requests.post(
            f"https://rmm.azcomputerguru.com/api/agents/{agent_id}/command",
            headers=rmm_headers,
            json=command_payload
        )
        resp.raise_for_status()
        command_id = resp.json()["command_id"]

        # Wait for completion
        for _ in range(24):
            time.sleep(5)
            resp = requests.get(
                f"https://rmm.azcomputerguru.com/api/commands/{command_id}",
                headers=rmm_headers
            )
            resp.raise_for_status()
            cmd_data = resp.json()

            if cmd_data["status"] in ["completed", "failed"]:
                if cmd_data["status"] == "completed":
                    uploaded += 1
                    if uploaded % 10 == 0:
                        print(f"  Uploaded {uploaded} / {len(missing_files)} files...")
                else:
                    errors.append(file_path)
                    print(f"  [ERROR] {file_path}")
                break
    except Exception as e:
        errors.append(file_path)
        print(f"  [ERROR] {file_path}: {e}")

print(f"\n[OK] Uploaded {uploaded} files")
if errors:
    print(f"[WARNING] {len(errors)} errors")
    print("\nFirst 10 errors:")
    for err in errors[:10]:
        print(f"  {err}")
