#!/bin/sh
set -e

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ROOT="$(dirname "$SCRIPT_DIR")"
SING_BOX="$ROOT/works/sing-box"
PATCH_DIR="$ROOT/works/patch"
CORE="$ROOT/works/core"

if [ ! -d "$SING_BOX/.git" ]; then
    echo "Error: works/sing-box not found. Run update first." >&2
    exit 1
fi

if [ ! -d "$CORE" ]; then
    echo "Error: works/core not found. Run generate first." >&2
    exit 1
fi

IGNORE_FILE="$ROOT/works/ignore"

is_ignored() {
    [ -f "$IGNORE_FILE" ] || return 1
    _rel="$1"
    _name="${_rel##*/}"
    while IFS= read -r _pattern || [ -n "$_pattern" ]; do
        case "$_pattern" in
            ''|\#*) continue ;;
        esac
        case "$_pattern" in
            */*)
                case "$_rel" in $_pattern) return 0 ;; esac
                ;;
            *)
                case "$_name" in $_pattern) return 0 ;; esac
                case "$_rel" in $_pattern/*) return 0 ;; esac
                ;;
        esac
    done < "$IGNORE_FILE"
    return 1
}

echo "Clearing existing patches..."
rm -rf "$PATCH_DIR"
mkdir -p "$PATCH_DIR"

echo "Generating patches for modified/new files..."
find "$CORE" -not -path "$CORE/.git/*" -type f | sort | while read -r dst_file; do
    rel="${dst_file#$CORE/}"
    if is_ignored "$rel"; then continue; fi
    src_file="$SING_BOX/$rel"
    patch_file="$PATCH_DIR/$rel.patch"

    if [ -f "$src_file" ]; then
        if ! diff -q "$src_file" "$dst_file" > /dev/null 2>&1; then
            mkdir -p "$(dirname "$patch_file")"
            diff -u --label "a/$rel" --label "b/$rel" "$src_file" "$dst_file" > "$patch_file" || true
            echo "  Modified: $rel"
        fi
    else
        mkdir -p "$(dirname "$patch_file")"
        diff -u --label /dev/null --label "b/$rel" /dev/null "$dst_file" > "$patch_file" || true
        echo "  New: $rel"
    fi
done

echo "Generating patches for deleted files..."
find "$SING_BOX" -not -path "$SING_BOX/.git/*" -type f | sort | while read -r src_file; do
    rel="${src_file#$SING_BOX/}"
    if is_ignored "$rel"; then continue; fi
    dst_file="$CORE/$rel"
    patch_file="$PATCH_DIR/$rel.patch"

    if [ ! -f "$dst_file" ]; then
        mkdir -p "$(dirname "$patch_file")"
        diff -u --label "a/$rel" --label /dev/null "$src_file" /dev/null > "$patch_file" || true
        echo "  Deleted: $rel"
    fi
done

echo "Done."
