#!/bin/bash
# Create or update a shared Forgejo release with branded macOS assets.

set -e

VERSION=""
BRANDS=()
FORGEJO_USER="${FORGEJO_USER}"
FORGEJO_PASS="${FORGEJO_PASS}"
FORGEJO_URL="https://git.him-tools.de"
REPO="HIM-public/webdrop-bridge"
CLEAR_CREDS=false
DRY_RUN=false
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
BRAND_HELPER="$PROJECT_ROOT/build/scripts/brand_config.py"
MANIFEST_OUTPUT="$PROJECT_ROOT/build/dist/release-manifest.json"
LOCAL_MANIFEST_OUTPUT="$PROJECT_ROOT/build/dist/release-manifest.local.json"
EXISTING_MANIFEST_OUTPUT="$PROJECT_ROOT/build/dist/release-manifest.existing.json"
LOCAL_DATA_OUTPUT="$PROJECT_ROOT/build/dist/release-data.local.json"

while [[ $# -gt 0 ]]; do
    case $1 in
        -v|--version) VERSION="$2"; shift 2 ;;
        -u|--url) FORGEJO_URL="$2"; shift 2 ;;
        --brand) BRANDS+=("$2"); shift 2 ;;
        --clear-credentials) CLEAR_CREDS=true; shift ;;
        --dry-run) DRY_RUN=true; shift ;;
        *) echo "Unknown option: $1"; exit 1 ;;
    esac
done

if [ "$CLEAR_CREDS" = true ]; then
    unset FORGEJO_USER
    unset FORGEJO_PASS
    echo "[OK] Credentials cleared from this session"
    exit 0
fi

if [ -z "$VERSION" ]; then
    VERSION="$(python3 -c "from pathlib import Path; import sys; sys.path.insert(0, str(Path(r'$PROJECT_ROOT/build/scripts').resolve())); from version_utils import get_current_version; print(get_current_version())")"
fi

get_release_notes() {
    python3 -c "from pathlib import Path; import sys; sys.path.insert(0, str(Path(r'$PROJECT_ROOT/build/scripts').resolve())); from version_utils import get_release_notes; print(get_release_notes('$VERSION'))"
}

LOCAL_ARGS=("$BRAND_HELPER" "local-release-data" "--platform" "macos" "--version" "$VERSION")
if [ ${#BRANDS[@]} -gt 0 ]; then
    LOCAL_ARGS+=("--brands" "${BRANDS[@]}")
fi

python3 "${LOCAL_ARGS[@]}" > "$LOCAL_DATA_OUTPUT"

ARTIFACTS=()
while IFS= read -r artifact; do
    if [ -n "$artifact" ]; then
        ARTIFACTS+=("$artifact")
    fi
done < <(python3 - "$LOCAL_DATA_OUTPUT" "$LOCAL_MANIFEST_OUTPUT" <<'PY'
import json
import sys
from pathlib import Path

data = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
Path(sys.argv[2]).write_text(json.dumps(data["manifest"], indent=2), encoding="utf-8")
for artifact in data["artifacts"]:
    print(artifact)
PY
)

VALIDATION_RESULT=$(python3 - "$LOCAL_DATA_OUTPUT" "$LOCAL_MANIFEST_OUTPUT" <<'PY'
import json
import sys
from pathlib import Path

data = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
manifest = json.loads(Path(sys.argv[2]).read_text(encoding="utf-8"))

selected_brands = data.get("brands", [])
manifest_brands = manifest.get("brands", {})
missing = []

for brand_id in selected_brands:
    platform_entry = manifest_brands.get(brand_id, {}).get("macos-universal", {})
    installer_name = platform_entry.get("installer", "")
    if not installer_name:
        missing.append(brand_id)

if missing:
    print("MISSING:" + ",".join(missing))
else:
    print("OK")
PY
)

if [[ "$VALIDATION_RESULT" == MISSING:* ]]; then
    MISSING_BRANDS="${VALIDATION_RESULT#MISSING:}"
    echo "ERROR: release-manifest.json is missing macos-universal installer entries for brand(s): $MISSING_BRANDS"
    echo "Build the missing brand(s) first or check artifact naming/version before creating the release."
    exit 1
fi

if [ ${#BRANDS[@]} -gt 0 ]; then
    FOUND_BRANDS_CSV=$(python3 - "$LOCAL_DATA_OUTPUT" <<'PY'
import json
import sys
from pathlib import Path

data = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
print(",".join(data.get("brands", [])))
PY
)

for REQUESTED_BRAND in "${BRANDS[@]}"; do
    if [[ ",$FOUND_BRANDS_CSV," != *",$REQUESTED_BRAND,"* ]]; then
        echo "ERROR: Requested brand '$REQUESTED_BRAND' has no local macOS artifact for version $VERSION"
        echo "Run build/scripts/build_macos.sh --brand $REQUESTED_BRAND first, then retry release creation."
        exit 1
    fi
done
fi

for ARTIFACT in "${ARTIFACTS[@]}"; do
    if [ -f "$ARTIFACT" ] && [ "${ARTIFACT##*.}" = "dmg" ]; then
        DMG_SIZE=$(du -m "$ARTIFACT" | cut -f1)
        echo "macOS artifact: $(basename "$ARTIFACT") ($DMG_SIZE MB)"
    fi
done

if [ ${#ARTIFACTS[@]} -eq 0 ]; then
    echo "ERROR: No local macOS artifacts found"
    exit 1
fi

if [ "$DRY_RUN" = true ]; then
    cp "$LOCAL_MANIFEST_OUTPUT" "$MANIFEST_OUTPUT"
    DISCOVERED_BRANDS=$(python3 - "$LOCAL_DATA_OUTPUT" <<'PY'
import json
import sys
from pathlib import Path

data = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
print(", ".join(data.get("brands", [])) or "<none>")
PY
)

    echo "[DRY RUN] No network requests or uploads will be performed."
    echo "[DRY RUN] Release tag: v$VERSION"
    echo "[DRY RUN] Release URL: $FORGEJO_URL/$REPO/releases/tag/v$VERSION"
    echo "[DRY RUN] Discovered brands: $DISCOVERED_BRANDS"
    echo "[DRY RUN] Artifacts that would be uploaded:"
    for ARTIFACT in "${ARTIFACTS[@]}"; do
        echo "  - $ARTIFACT"
    done
    echo "[DRY RUN] Local manifest preview: $MANIFEST_OUTPUT"
    exit 0
fi

if [ -z "$FORGEJO_USER" ] || [ -z "$FORGEJO_PASS" ]; then
    echo "Forgejo credentials not found. Enter your credentials:"
    if [ -z "$FORGEJO_USER" ]; then
        read -r -p "Username: " FORGEJO_USER
    fi
    if [ -z "$FORGEJO_PASS" ]; then
        read -r -s -p "Password: " FORGEJO_PASS
        echo ""
    fi
    export FORGEJO_USER
    export FORGEJO_PASS
fi

BASIC_AUTH=$(echo -n "${FORGEJO_USER}:${FORGEJO_PASS}" | base64)
RELEASE_URL="$FORGEJO_URL/api/v1/repos/$REPO/releases"
RELEASE_LOOKUP_URL="$FORGEJO_URL/api/v1/repos/$REPO/releases/tags/v$VERSION"

RELEASE_RESPONSE_FILE=$(mktemp)
HTTP_CODE=$(curl -s -o "$RELEASE_RESPONSE_FILE" -w "%{http_code}" -H "Authorization: Basic $BASIC_AUTH" "$RELEASE_LOOKUP_URL")
if [ "$HTTP_CODE" = "200" ]; then
    RELEASE_ID=$(python3 - "$RELEASE_RESPONSE_FILE" <<'PY'
import json
import sys
from pathlib import Path

payload = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
print(payload.get("id", ""))
PY
)
else
    RELEASE_ID=""
fi

if [ -z "$RELEASE_ID" ]; then
    RELEASE_BODY="$(get_release_notes)"
    RELEASE_DATA=$(RELEASE_BODY="$RELEASE_BODY" VERSION="$VERSION" python3 - <<'PY'
import json
import os

print(json.dumps({
    "tag_name": f"v{os.environ['VERSION']}",
    "name": f"WebDropBridge v{os.environ['VERSION']}",
    "body": os.environ["RELEASE_BODY"],
    "draft": False,
    "prerelease": False,
}))
PY
)
    HTTP_CODE=$(curl -s -o "$RELEASE_RESPONSE_FILE" -w "%{http_code}" -X POST \
        -H "Authorization: Basic $BASIC_AUTH" \
        -H "Content-Type: application/json" \
        -d "$RELEASE_DATA" \
        "$RELEASE_URL")
    if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "201" ]; then
        RELEASE_ID=$(python3 - "$RELEASE_RESPONSE_FILE" <<'PY'
import json
import sys
from pathlib import Path

payload = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
print(payload.get("id", ""))
PY
)
    fi
fi

if [ -z "$RELEASE_ID" ]; then
    echo "ERROR creating or finding release"
    cat "$RELEASE_RESPONSE_FILE"
    exit 1
fi

MANIFEST_URL=$(python3 - "$RELEASE_RESPONSE_FILE" <<'PY'
import json
import sys
from pathlib import Path

payload = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
for asset in payload.get("assets", []):
    if asset.get("name") == "release-manifest.json":
        print(asset.get("browser_download_url", ""))
        break
PY
)

if [ -n "$MANIFEST_URL" ]; then
    curl -s -H "Authorization: Basic $BASIC_AUTH" "$MANIFEST_URL" -o "$EXISTING_MANIFEST_OUTPUT"
    python3 "$BRAND_HELPER" merge-manifests --base "$EXISTING_MANIFEST_OUTPUT" --overlay "$LOCAL_MANIFEST_OUTPUT" --output "$MANIFEST_OUTPUT" >/dev/null
else
    cp "$LOCAL_MANIFEST_OUTPUT" "$MANIFEST_OUTPUT"
fi

ARTIFACTS+=("$MANIFEST_OUTPUT")

UPLOAD_URL="$FORGEJO_URL/api/v1/repos/$REPO/releases/$RELEASE_ID/assets"
for ARTIFACT in "${ARTIFACTS[@]}"; do
    ASSET_NAME="$(basename "$ARTIFACT")"
    EXISTING_ASSET_ID=$(python3 - "$RELEASE_RESPONSE_FILE" "$ASSET_NAME" <<'PY'
import json
import sys
from pathlib import Path

payload = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
asset_name = sys.argv[2]
for asset in payload.get("assets", []):
    if asset.get("name") == asset_name:
        print(asset.get("id", ""))
        break
PY
)

    if [ -n "$EXISTING_ASSET_ID" ]; then
        curl -s -X DELETE \
            -H "Authorization: Basic $BASIC_AUTH" \
            "$FORGEJO_URL/api/v1/repos/$REPO/releases/$RELEASE_ID/assets/$EXISTING_ASSET_ID" >/dev/null
        echo "[OK] Replaced existing asset $ASSET_NAME"
    fi

    HTTP_CODE=$(curl -s -w "%{http_code}" -X POST \
        -H "Authorization: Basic $BASIC_AUTH" \
        -F "attachment=@$ARTIFACT" \
        "$UPLOAD_URL" \
        -o /tmp/curl_response.txt)

    if [ "$HTTP_CODE" -eq 201 ] || [ "$HTTP_CODE" -eq 200 ]; then
        echo "[OK] Uploaded $ASSET_NAME"
    else
        echo "ERROR uploading $ASSET_NAME (HTTP $HTTP_CODE)"
        cat /tmp/curl_response.txt
        exit 1
    fi
done

echo ""
echo "[OK] Release complete!"
echo "View at: $FORGEJO_URL/$REPO/releases/tag/v$VERSION"
