#!/usr/bin/env bash
# scripts/brand/brandize.sh — re-apply this fork's brand layer.
#
# Idempotent: running it twice changes nothing, so it is safe to run after every
# merge from upstream. Run with no arguments to sweep the whole repo, or pass
# specific files.
#
# EVERY brand-specific value lives in brand.conf — name, palette, logo. There is
# no hand-maintained file left, which is the point: a file the sweep does not
# own is a file that conflicts on every sync and eventually gets it wrong.
#
# What it deliberately does NOT touch:
#   * lower-case `propertylab` — it is a config key, an AI persona id, a column
#     value and a domain (propertylab_ai, app.propertylab.com.my). Renaming it
#     breaks lookups against rows already in the database.
#   * `PropertyLab` glued to more letters — those are CLASS names
#     (PropertyLabEvaluationController). The lookarounds below spare them.
#   * the vendor's own names — every KEEP_PHRASES entry ("PropertyLab API", the
#     service a client buys from PropertyLab), and any line carrying a
#     `brand:keep` comment (upstream marks its service / model-label constants
#     that way). A client's UI must name the service it is billed for, not
#     itself: Starcity's Setting tab read "Starcity Global API" (2026-09-06).
set -euo pipefail

HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1090
source "${BRAND_CONF:-$HERE/brand.conf}"
cd "$(git rev-parse --show-toplevel)"

if [ $# -gt 0 ]; then
    FILES=("$@")
else
    # No mapfile: macOS ships bash 3.2, and a sync is run from a laptop too.
    FILES=()
    while IFS= read -r f; do FILES+=("$f"); done < <(
        { git ls-files -- app config resources routes src \
            | grep -E '\.(vue|js|ts|css|php|md)$'
          git ls-files -- resources/lang | grep -E '\.json$'
        } | sort -u
    )
fi
[ ${#FILES[@]} -eq 0 ] && { echo "brandize: nothing to do"; exit 0; }

sweep() { printf '%s\0' "${FILES[@]}" | xargs -0 -r "$@"; }

# 1. Tailwind colour families -> the brand token.
sweep perl -pi -e '
    # border-t- / divide-x- / ring-offset- included: a directional utility is
    # still the same colour, and missing one leaves a single blue edge behind.
    s/\b(bg|text|border(?:-[xytrbles])?|ring(?:-offset)?|from|via|to|fill|stroke|divide(?:-[xy])?|outline|decoration|shadow|accent|placeholder|caret)-(blue|indigo|sky)-([0-9]{2,3})\b/$1-brand-$3/g;
'

# 2. Every hex upstream uses for its own ramp -> this fork's ramp. This is what
#    rewrites the @theme block in resources/css/app.css as well as the charts,
#    mapbox markers and canvas code that cannot read a CSS class.
sweep perl -pi -e "
    s/#eef4ff/${RAMP_50}/gi;  s/#d9e6ff/${RAMP_100}/gi; s/#bcd3ff/${RAMP_200}/gi;
    s/#8eb6ff/${RAMP_300}/gi; s/#5a8dff/${RAMP_400}/gi; s/#3366f6/${RAMP_500}/gi;
    s/#2563eb/${RAMP_600}/gi; s/#1d4ed8/${RAMP_700}/gi; s/#1e40af/${RAMP_800}/gi;
    s/#1e3a8a/${RAMP_900}/gi;
    s/#2d4368/${NAVY_600}/gi; s/#243656/${NAVY_700}/gi; s/#182944/${NAVY_800}/gi;
    s/#111e35/${NAVY_900}/gi; s/#0b1626/${NAVY_950}/gi;
    # stock Tailwind blue, which upstream code reaches for in charts
    s/#dbeafe/${RAMP_100}/gi; s/#bfdbfe/${RAMP_200}/gi; s/#93c5fd/${RAMP_300}/gi;
    s/#60a5fa/${RAMP_400}/gi; s/#3b82f6/${RAMP_500}/gi;
"

# 3. Display name. The lookarounds are the whole safety story — see the header.
#    Two escapes, both from brand.conf's "vendor's own names" note: a line with
#    `brand:keep` is printed untouched, and every KEEP_PHRASES entry is parked
#    behind a NUL placeholder for the duration of the substitution and put back
#    on the same line, so the phrase survives while the bare name around it is
#    still renamed. Values travel through the environment so the perl stays
#    single-quoted — no shell-in-perl-in-shell escaping to get wrong.
sweep env UP="$UPSTREAM_NAME" UP_SP="$UPSTREAM_NAME_SPACED" UP_UC="$UPSTREAM_NAME_UPPER" \
          BR="$BRAND_NAME" BR_UC="$BRAND_NAME_UPPER" \
          KEEP="$(printf '%s\n' ${KEEP_PHRASES[@]+"${KEEP_PHRASES[@]}"})" \
    perl -pi -e '
        BEGIN { $keep_re = join "|", map { quotemeta } grep { length } split /\n/, $ENV{KEEP}; }
        next if /brand:keep/;
        my @park;
        s/($keep_re)/push @park, $1; "\x00" . $#park . "\x00"/ge if length $keep_re;
        s/(?<![A-Za-z_])\Q$ENV{UP}\E(?![A-Za-z_])/$ENV{BR}/g;
        s/(?<![A-Za-z_])\Q$ENV{UP_SP}\E(?![A-Za-z_])/$ENV{BR}/g;
        s/(?<![A-Za-z_])\Q$ENV{UP_UC}\E(?![A-Za-z_])/$ENV{BR_UC}/g;
        s/\x00(\d+)\x00/$park[$1]/g;
    '

# 4. Logo paths, then any one-off prose. Plain literal find/replace.
for pair in "${LOGO_SUBS[@]}" "${EXTRA_SUBS[@]}"; do
    [ -n "$pair" ] || continue
    sweep env FROM="${pair%%|*}" TO="${pair#*|}" \
        perl -pi -e 's/\Q$ENV{FROM}\E/$ENV{TO}/g'
done

echo "brandize: swept ${#FILES[@]} files"
