#!/bin/bash

SOURCEIPA="$1"
OUTPUT="$2"
OUTPUTAPP="$3"
HASNES="$4"
UNIVERSALLINK="$5"
miniappCacheDir="$6"
CERTIFICATENAME="$7"
MOBILEPROV="$8"
extensionProfilePath="$9"

echo $UNIVERSALLINK
echo $miniappCacheDir

if [ "$CERTIFICATENAME" == '' ]; then 
    CERTIFICATENAME=$(osascript -e 'Tell application "System Events" to display dialog "请输入签名证书名（可以查看钥匙串）:"  with title "Miniapp Builder" default answer "" buttons {"Cancel", "OK"} default button "OK"' -e 'if button returned of result is "OK" then' -e 'text returned of result' -e 'else' -e 'return "Cancel"' -e 'end if' 2>/dev/null)
fi

if [ $? -ne 0 ]; then
    echo "execute osascript failed: 可能工具未获得授权将 Apple 事件发送给 System Events。可以在「安全与隐私 > 隐私 > 自动化」中开启权限" >&2
    exit -1
fi

if [ "$CERTIFICATENAME" != 'Cancel' ]; then 
    # 选择profile
    if [ "$MOBILEPROV" == '' ]; then 
        MOBILEPROV=$(osascript -e 'set profilePath to choose file with prompt "请选择类型的 profile 文件（mobileprovision文件）" of type {"mobileprovision"}' -e 'if profilePath is not equal to false then' -e 'set profilePath to POSIX path of profilePath' -e 'end if' 2>/dev/null)
    fi
    if [ "$MOBILEPROV" != '' ]; then 
        if [ "$HASNES" == 'true' ]; then
            # 选择profile
            if [ "$extensionProfilePath" == '' ]; then 
                extensionProfilePath=$(osascript -e 'set extensionProfilePath to choose file with prompt "请选择 消息服务扩展(notification service extension) profile 文件（mobileprovision文件）" of type {"mobileprovision"}' -e 'if extensionProfilePath is not equal to false then' -e 'set extensionProfilePath to POSIX path of extensionProfilePath' -e 'end if' 2>/dev/null)
            fi

            if [ "$extensionProfilePath" == '' ]; then
                extensionProfilePath=""
                CERTIFICATENAME=""
                MOBILEPROV=""
                echo "Cancel At choose ExtensionProfilePath" >&2
                exit -1
            fi
        else
            extensionProfilePath=""
        fi
    else
        CERTIFICATENAME=""
        MOBILEPROV=""
        echo "Cancel At choose MOBILEPROV" >&2
        exit -1
    fi
else 
    CERTIFICATENAME=""
    echo "Cancel At enter CERTIFICATENAME" >&2
    exit -1
fi

temp_dir=$(mktemp -d)
temp_extracted="$temp_dir/extracted"
unzip -qo "$SOURCEIPA" -d $temp_extracted
cd $temp_dir
 
APPLICATION=$(ls $temp_extracted/Payload/)
 
cp "$MOBILEPROV" "$temp_extracted/Payload/$APPLICATION/embedded.mobileprovision"

if [ "$HASNES" == 'true' ]; then
    echo "$extensionProfilePath"
    echo "$temp_extracted/Payload/$APPLICATION/PlugIns/TPNSService.appex/embedded.mobileprovision"
    cp "$extensionProfilePath" "$temp_extracted/Payload/$APPLICATION/PlugIns/TPNSService.appex/embedded.mobileprovision"
    if [ $? -ne 0 ]; then
        echo "cp TPNSService failed"
        exit -1
    else
        echo "cp TPNSService success"
    fi
fi
 
# Create an empty plist file
empty_plist="empty_entitlements.plist"
touch "$empty_plist"
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" >> "$empty_plist"
echo "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">" >> "$empty_plist"
echo "<plist version=\"1.0\">" >> "$empty_plist"
echo "<dict>" >> "$empty_plist"
echo "</dict>" >> "$empty_plist"
echo "</plist>" >> "$empty_plist"

echo "Resigning with certificate: $CERTIFICATENAME"
find -d $temp_extracted \( -name "*.app" -o -name "*.appex" -o -name "*.framework" -o -name "*.dylib" \) | grep -v "SwiftSupport" > sign_items.txt

# gen main app entitlement
security cms -D -i "$temp_extracted/Payload/$APPLICATION/embedded.mobileprovision" > entitlements_full.plist
/usr/libexec/PlistBuddy -x -c 'Print:Entitlements' entitlements_full.plist > entitlements.plist

function replaceUniversalLink {
    echo "start to replace universalLink to $UNIVERSALLINK"
    i=0
    filename="entitlements.plist"
    finded=0

    # 使用 sed 循环读取文件内容
    while IFS= read -r line; do
    # 在这里对每一行进行处理
        ((i++))
        if echo "$line" | grep -q "<string>\*</string>"; then
            ((j=i-1))
            result=$(sed -n "${j}p" "$filename")
            if echo "$result" | grep -q "<key>com\.apple\.developer\.associated-domains<\/key>"; then
                finded=1
                echo "finded previous universalLink"
                break
            fi
        fi
    done < "$filename"

    if [ "$finded" -eq 1 ]; then

        echo "start to analyse universal link"
        if [[ "$UNIVERSALLINK" == *"_\$_ULinK_\$_"* ]]; then
            echo "multiple universalLink with ul"
            # 根据 "$_ULinK_$_" 分割字符串
            ulArr=(${UNIVERSALLINK//_\$_ULinK_\$_/ })
            ulArrStr+="\t<array>"
            for ul in "${ulArr[@]}"; do
                echo "ul: $ul"
                ulArrStr+="\n\t\t<string>$ul</string>"
            done
            ulArrStr+="\n\t</array>"
            sed -i '' "${i}s#.*#${ulArrStr}#g" "$filename"
        else
            echo "\nsingle universal link"
            sed -i '' "${i}s#.*#\t<array><string>${UNIVERSALLINK}<\/string><\/array>#g" "$filename"
        fi
    else
        echo "!Error replacing Universal Link in profile, enable Associated Domains for you identifier in https://developer.apple.com/account/resources/identifiers"
        exit -1
    fi

    echo "finished replace previous universalLink"
}

replaceUniversalLink

# gen appex entitlement
if [ "$HASNES" == 'true' ]; then
    security cms -D -i "$temp_extracted/Payload/$APPLICATION/PlugIns/TPNSService.appex/embedded.mobileprovision" > entitlements_appex_full.plist
    /usr/libexec/PlistBuddy -x -c 'Print:Entitlements' entitlements_appex_full.plist > entitlements_appex.plist
fi

function prepareAppexProfiles {
    profilesMapForShell="$miniappCacheDir/__appexProfilesCacheDir__/profilesMapForShell.txt"

    if [ -f "$profilesMapForShell" ] && [ "$miniappCacheDir" != '' ]; then 
        echo "start prepareAppexProfiles" $profilesMapForShell
        bundleIDs=()
        profiles=()
        appexNames=()
        # Initialize empty arrays for bundle IDs and profiles

        while IFS= read -r line; do
            # Use awk with custom field separator to extract bundleID and profile
            appexName=$(echo "$line" | awk -F 'pluginAppexName:|;_;_;bundleID:|;_;_;profile:' '{print $2}')
            bundleID=$(echo "$line" | awk -F 'pluginAppexName:|;_;_;bundleID:|;_;_;profile:' '{print $3}')
            profile=$(echo "$line" | awk -F 'pluginAppexName:|;_;_;bundleID:|;_;_;profile:' '{print $4}')

            # Remove any trailing whitespace from bundleID and profile
            bundleID=$(echo "$bundleID" | xargs)
            profile=$(echo "$profile" | xargs)
            appexName=$(echo "$appexName" | xargs)

            echo "start prepareAppexProfiles": $appexName $profile $bundleId

            # Store them in the arrays
            if [ -n "$bundleID" ] && [ -n "$profile" ] && [ -n "$appexName" ]; then 
                bundleIDs+=("$bundleID")
                profiles+=("$profile")
                appexNames+=("$appexName")

                echo "using appex profiles : $bundleID $profile $appexName"

                # 1.拷贝profile到指定的appex目录下 2.然后输出entitlement.plist
                if [ -f "$profile" ]; then 
                    targetAppexPath="$temp_extracted/Payload/$APPLICATION/PlugIns/$appexName.appex"
                    if [ -d $targetAppexPath ]; then
                        cp "$profile" "$targetAppexPath/embedded.mobileprovision"
                        security cms -D -i "$targetAppexPath/embedded.mobileprovision" > entitlements_${appexName}_full.plist
                        /usr/libexec/PlistBuddy -x -c 'Print:Entitlements' entitlements_${appexName}_full.plist > entitlements_${appexName}.plist
                    else
                        echo -e "Error: cant find appex in path: $targetAppexPath"
                        exit -1
                    fi
                else
                    echo -e "Error: cant find profile in path: $profile"
                    exit -1
                fi
            fi
        done < "$profilesMapForShell" # Replace with your actual input file name
    else
        echo "prepareAppexProfiles cant find file: " $file
    fi
}

prepareAppexProfiles

check_if_invalid_cer() {
    local output="$1"
    keyword="unable to build chain to self-signed root"

    echo $output
    while IFS= read -r line; do
        if echo "$line" | grep -q "$keyword"; then
           echo "所选证书非有效证书，请查看「钥匙串访问」确认证书有效" >&2
        fi
    done <<< "$output"
}

xattr -cr ./

while IFS='' read -r line || [[ -n "$line" ]]; do
    file_name=$(basename "$line")

    if [ "${file_name##*.}"x = "appex"x ] || [ "${file_name##*.}"x = "framework"x ]; then
        if [ "$file_name" == "TPNSService.appex" ] && [ "$HASNES" == 'true' ]; then
            # 腾讯云 TPNS 老的消息推送逻辑
            output=$(/usr/bin/codesign --continue -f -s "$CERTIFICATENAME" --entitlements "entitlements_appex.plist" "$line" 2>&1)
            if [ $? -ne 0 ]; then
                check_if_invalid_cer "$output"
                echo -e "execute codesign failed ：$CERTIFICATENAME , $line" >&2
                exit -1
            else
                check_if_invalid_cer "$output"
            fi
        elif [ "${file_name##*.}"x = "appex"x ]; then
            # 自定义appex 逻辑 去找一下对应的appex是否存在
            fileBasename=${file_name%.*}
            echo "doing codesign for "$fileBasename
            appexProfilePath=entitlements_${fileBasename}.plist
            if [ -f "$appexProfilePath" ]; then 
                echo "doing appex signing " $CERTIFICATENAME $appexProfilePath
                output=$(/usr/bin/codesign --continue -f -s "$CERTIFICATENAME" --entitlements "$appexProfilePath" "$line" 2>&1)
                if [ $? -ne 0 ]; then
                    check_if_invalid_cer "$output"
                    echo -e "execute appex ${fileBasename} codesign failed ：$CERTIFICATENAME , $line" >&2
                    exit -1
                else
                    check_if_invalid_cer "$output"
                fi
            else
                echo "cant find appex profile " $appexProfilePath
            fi
        else
            output=$(/usr/bin/codesign --continue -f -s "$CERTIFICATENAME" --entitlements "$empty_plist" "$line" 2>&1)
            if [ $? -ne 0 ]; then
                check_if_invalid_cer "$output"
                echo -e "execute codesign failed ：$CERTIFICATENAME , $line" >&2
                exit -1
            else
                check_if_invalid_cer "$output"
            fi
        fi
    else
        output=$(/usr/bin/codesign --continue -f -s "$CERTIFICATENAME" --entitlements "entitlements.plist"  "$line" 2>&1)
        if [ $? -ne 0 ]; then
            check_if_invalid_cer "$output"
            echo -e "execute codesign failed ：$CERTIFICATENAME , $line" >&2
            exit -1
        else
            check_if_invalid_cer "$output"
        fi
    fi
done < sign_items.txt

bundleId=$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "$temp_extracted/Payload/$APPLICATION/info.plist")
bundleId=$(echo "$bundleId" | tr -d '.')
bundleShortVersionString=$(/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" "$temp_extracted/Payload/$APPLICATION/info.plist")

echo "Create the Signed IPA"
cd $temp_extracted

if [ "$OUTPUTAPP" == 'false' ]; then 
    zip -x "/*.cstemp" -qry ../extracted.ipa * 
    cd ..
    bundleId=${bundleId//./}
    mv extracted.ipa $OUTPUT/$bundleId-$bundleShortVersionString.ipa
else
    cd ./Payload
    rm -rf "$OUTPUT/demo.app"
    cp -R "$APPLICATION" "$OUTPUT/$OUTPUTAPP"
fi

rm -rf $temp_dir
# rm sign_items.txt
# rm entitlements.plist
# rm entitlements_full.plist
# if [ "$HASNES" == 'true' ]; then
#     rm entitlements_appex_full.plist
#     rm entitlements_appex.plist
# fi
# rm $empty_plist
