param(
    [string]$ServerHost = '192.168.0.185',
    [string]$Username = 'sevenhill',
    [Parameter(Mandatory = $true)]
    [string]$Password,
    [string]$ArgusBaseUrl = 'https://argus.kusoft.xyz',
    [string]$ArgusInternalBaseUrl = 'http://127.0.0.1:5105',
    [string]$ArgusEnvPath = '/home/sevenhill/argus-deploy/.env.server',
    [string]$Slug = 'ikar-android',
    [string]$Notes = 'Android client update for Ikar',
    [string]$AppName = 'Ikar Android',
    [string]$Summary = 'Android client build',
    [string]$Description = 'Android release channel for the Ikar client.',
    [string]$HomepageUrl = 'https://ikar.kusoft.xyz',
    [string]$Platform = 'android',
    [string]$PackageKind = 'apk',
    [string]$Channel = 'stable'
)

$ErrorActionPreference = 'Stop'

Set-Location (Join-Path $PSScriptRoot '..')

$repoRoot = (Get-Location).Path
$projectPath = '.\src\Ikar.Client\Ikar.Client.csproj'

[xml]$projectXml = Get-Content $projectPath
$versionName = $projectXml.Project.PropertyGroup.ApplicationDisplayVersion | Select-Object -First 1
$versionCode = [int]($projectXml.Project.PropertyGroup.ApplicationVersion | Select-Object -First 1)
$publishDir = Join-Path $repoRoot (".codex-temp\android-update-publish\v{0}" -f $versionCode)

if (Test-Path $publishDir) {
    Remove-Item $publishDir -Recurse -Force
}

dotnet publish $projectPath -f net10.0-android -c Release -p:AndroidPackageFormat=apk -p:UseSharedCompilation=false -o $publishDir

$sourceApk = Join-Path $publishDir 'com.seven.ikar-Signed.apk'
if (-not (Test-Path $sourceApk)) {
    throw "Signed APK not found: $sourceApk"
}

$remoteFileName = "ikar-android-$versionCode.apk"
$localCopy = Join-Path $publishDir $remoteFileName
Copy-Item $sourceApk $localCopy -Force

$manifest = [ordered]@{
    versionCode = $versionCode
    versionName = $versionName
    packageFileName = $remoteFileName
    publishedAt = [DateTimeOffset]::UtcNow.ToString('O')
    notes = $Notes
}

$manifestPath = Join-Path $publishDir 'latest.json'
$manifest | ConvertTo-Json -Depth 4 | Set-Content $manifestPath -Encoding UTF8

$argusPublishResult = @"
import json
import os
import paramiko
import posixpath

host = os.environ['IKAR_UPDATE_HOST']
username = os.environ['IKAR_UPDATE_USERNAME']
password = os.environ['IKAR_UPDATE_PASSWORD']
env_path = os.environ['IKAR_UPDATE_ARGUS_ENV_PATH']
local_apk_path = os.environ['IKAR_UPDATE_APK_PATH']
remote_apk_name = os.environ['IKAR_UPDATE_REMOTE_APK_NAME']
argus_internal_base_url = os.environ['IKAR_UPDATE_ARGUS_INTERNAL_BASE_URL']
slug = os.environ['IKAR_UPDATE_ARGUS_SLUG']
app_name = os.environ['IKAR_UPDATE_ARGUS_NAME']
summary = os.environ['IKAR_UPDATE_ARGUS_SUMMARY']
description = os.environ['IKAR_UPDATE_ARGUS_DESCRIPTION']
homepage_url = os.environ['IKAR_UPDATE_ARGUS_HOMEPAGE_URL']
release_version = os.environ['IKAR_UPDATE_ARGUS_VERSION']
channel = os.environ['IKAR_UPDATE_ARGUS_CHANNEL']
platform = os.environ['IKAR_UPDATE_ARGUS_PLATFORM']
package_kind = os.environ['IKAR_UPDATE_ARGUS_PACKAGE_KIND']
notes = os.environ['IKAR_UPDATE_ARGUS_NOTES']
temp_root = f"/home/{username}/.argus-upload"

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(host, username=username, password=password, timeout=10)
sftp = client.open_sftp()

with sftp.open(env_path, 'r') as handle:
    content = handle.read().decode('utf-8', errors='replace')

values = {}
for raw_line in content.splitlines():
    line = raw_line.strip()
    if not line or line.startswith('#') or '=' not in line:
        continue
    key, value = line.split('=', 1)
    values[key.strip()] = value.strip()

username = values.get('Admin__Username')
password = values.get('Admin__Password')
if not username or not password:
    raise RuntimeError(f"Admin credentials were not found in {env_path}.")

parts = temp_root.strip('/').split('/')
current = '/'
for part in parts:
    current = posixpath.join(current, part)
    try:
        sftp.stat(current)
    except FileNotFoundError:
        sftp.mkdir(current)

remote_apk_path = posixpath.join(temp_root, remote_apk_name)
sftp.put(local_apk_path, remote_apk_path)
sftp.close()

def run_remote_python(script: str) -> str:
    stdin, stdout, stderr = client.exec_command("python3 -", timeout=600)
    stdin.write(script)
    stdin.channel.shutdown_write()
    out = stdout.read().decode('utf-8', errors='replace')
    err = stderr.read().decode('utf-8', errors='replace')
    exit_status = stdout.channel.recv_exit_status()
    if exit_status != 0:
        raise RuntimeError(f"Remote publish failed with exit status {exit_status}\\nSTDOUT:\\n{out}\\nSTDERR:\\n{err}")
    return out

remote_payload = json.dumps({
    'base_url': argus_internal_base_url.rstrip('/'),
    'slug': slug,
    'package_path': remote_apk_path,
    'admin_username': username,
    'admin_password': password,
    'app_name': app_name,
    'summary': summary,
    'description': description,
    'homepage_url': homepage_url,
    'release_version': release_version,
    'release_channel': channel,
    'release_platform': platform,
    'release_package_kind': package_kind,
    'release_notes': notes,
})

remote_script = '''
import json
import os
import urllib.request
import uuid

payload = json.loads(%s)
base_url = payload['base_url']
slug = payload['slug']
package_path = payload['package_path']
admin_username = payload['admin_username']
admin_password = payload['admin_password']
app_name = payload['app_name']
summary = payload['summary']
description = payload['description']
homepage_url = payload['homepage_url']
release_version = payload['release_version']
release_channel = payload['release_channel']
release_platform = payload['release_platform']
release_package_kind = payload['release_package_kind']
release_notes = payload['release_notes']

def read_response(response):
    body = response.read().decode('utf-8', errors='replace')
    return response.getcode(), body

opener = urllib.request.build_opener()

login_payload = json.dumps({
    'username': admin_username,
    'password': admin_password,
}).encode('utf-8')
login_request = urllib.request.Request(
    f"{base_url}/api/admin/session/login",
    data=login_payload,
    headers={'Content-Type': 'application/json'},
    method='POST')
login_response = opener.open(login_request, timeout=600)
login_status, login_body = read_response(login_response)
if login_status < 200 or login_status >= 300:
    raise RuntimeError(f"Login failed with status {login_status}: {login_body}")

cookie_header = login_response.headers.get('Set-Cookie', '')
auth_cookie = cookie_header.split(';', 1)[0].strip()
if not auth_cookie:
    raise RuntimeError('Argus login did not return an auth cookie.')

metadata_payload = json.dumps({
    'name': app_name,
    'summary': summary,
    'description': description,
    'homepageUrl': homepage_url or None,
    'repositoryUrl': None,
    'isListed': True,
}).encode('utf-8')
metadata_request = urllib.request.Request(
    f"{base_url}/api/admin/apps/{slug}",
    data=metadata_payload,
    headers={
        'Content-Type': 'application/json',
        'Cookie': auth_cookie,
    },
    method='PUT')
metadata_response = opener.open(metadata_request, timeout=600)
metadata_status, metadata_body = read_response(metadata_response)
if metadata_status < 200 or metadata_status >= 300:
    raise RuntimeError(f"Metadata update failed with status {metadata_status}: {metadata_body}")

with open(package_path, 'rb') as handle:
    file_bytes = handle.read()

boundary = f"----IkarArgusBoundary{uuid.uuid4().hex}"
parts: list[bytes] = []

def add_field(name: str, value: str):
    parts.append(f"--{boundary}\\r\\n".encode('utf-8'))
    parts.append(f'Content-Disposition: form-data; name="{name}"\\r\\n\\r\\n'.encode('utf-8'))
    parts.append(value.encode('utf-8'))
    parts.append(b"\\r\\n")

for field_name, field_value in [
    ('Version', release_version),
    ('Channel', release_channel),
    ('Platform', release_platform),
    ('PackageKind', release_package_kind),
]:
    add_field(field_name, field_value)

if release_notes:
    add_field('Notes', release_notes)

file_name = os.path.basename(package_path)
parts.append(f"--{boundary}\\r\\n".encode('utf-8'))
parts.append(
    f'Content-Disposition: form-data; name="Package"; filename="{file_name}"\\r\\n'.encode('utf-8'))
parts.append(b"Content-Type: application/vnd.android.package-archive\\r\\n\\r\\n")
parts.append(file_bytes)
parts.append(b"\\r\\n")
parts.append(f"--{boundary}--\\r\\n".encode('utf-8'))

release_request = urllib.request.Request(
    f"{base_url}/api/admin/apps/{slug}/releases",
    data=b''.join(parts),
    headers={
        'Content-Type': f'multipart/form-data; boundary={boundary}',
        'Cookie': auth_cookie,
    },
    method='POST')
release_response = opener.open(release_request, timeout=600)
release_status, release_body = read_response(release_response)
if release_status < 200 or release_status >= 300:
    raise RuntimeError(f"Release upload failed with status {release_status}: {release_body}")

print(release_body)
''' % json.dumps(remote_payload)

publish_output = run_remote_python(remote_script)

try:
    sftp = client.open_sftp()
    sftp.remove(remote_apk_path)
    sftp.close()
except Exception:
    pass

client.close()
print(json.dumps({'status': 'UPLOAD_OK', 'release': publish_output.strip()}))
"@ | ForEach-Object {
    $env:IKAR_UPDATE_HOST = $ServerHost
    $env:IKAR_UPDATE_USERNAME = $Username
    $env:IKAR_UPDATE_PASSWORD = $Password
    $env:IKAR_UPDATE_ARGUS_ENV_PATH = $ArgusEnvPath
    $env:IKAR_UPDATE_APK_PATH = (Resolve-Path $localCopy)
    $env:IKAR_UPDATE_REMOTE_APK_NAME = $remoteFileName
    $env:IKAR_UPDATE_ARGUS_INTERNAL_BASE_URL = $ArgusInternalBaseUrl
    $env:IKAR_UPDATE_ARGUS_SLUG = $Slug
    $env:IKAR_UPDATE_ARGUS_NAME = $AppName
    $env:IKAR_UPDATE_ARGUS_SUMMARY = $Summary
    $env:IKAR_UPDATE_ARGUS_DESCRIPTION = $Description
    $env:IKAR_UPDATE_ARGUS_HOMEPAGE_URL = $HomepageUrl
    $env:IKAR_UPDATE_ARGUS_VERSION = "$versionName+$versionCode"
    $env:IKAR_UPDATE_ARGUS_CHANNEL = $Channel
    $env:IKAR_UPDATE_ARGUS_PLATFORM = $Platform
    $env:IKAR_UPDATE_ARGUS_PACKAGE_KIND = $PackageKind
    $env:IKAR_UPDATE_ARGUS_NOTES = $Notes
    $_
} | python -

$publishResult = $argusPublishResult | ConvertFrom-Json
if ($publishResult.status -ne 'UPLOAD_OK') {
    throw "Argus publish failed."
}

Write-Output $publishResult.status
