#!/usr/bin/env bash

# Build and package the Flutter web app for the DEV environment with aggressive optimizations.
# Produces a timestamped folder + zip in the project root, with precompressed assets.

set -euo pipefail

PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
TIMESTAMP="$(date +%Y%m%d_%H%M%S)"
OUT_DIR="web_dev_export_${TIMESTAMP}"
ZIP_FILE="${OUT_DIR}.zip"

cd "${PROJECT_ROOT}"

set_env_dev() {
  echo "🔧 Switching to DEVELOPMENT environment..."
  local src="${PROJECT_ROOT}/assets/config/env_dev.json"
  local dest="${PROJECT_ROOT}/assets/config/env.json"
  if [ ! -f "${src}" ]; then
    echo "❌ ${src} not found" >&2
    exit 1
  fi
  cp "${src}" "${dest}"
  echo "📋 Current config:"
  cat "${dest}"
}

copy_x_app_sdk() {
  local src="node_modules/x-app-sdk/dist/index.es.js"
  local dest="build/web/js/x_app_sdk_bundle.js"
  if [ ! -f "${src}" ]; then
    echo "❌ x-app-sdk bundle not found at ${src}" >&2
    exit 1
  fi
  mkdir -p "$(dirname "${dest}")"
  cp "${src}" "${dest}"
  echo "✅ Copied x-app-sdk bundle."
}

compress_assets() {
  local dir="$1"
  echo "🗜️  Compressing assets with maximum compression..."
  
  # Gzip compression (level 9 = maximum)
  if command -v gzip >/dev/null 2>&1; then
    echo "   → Creating .gz files (gzip -9)..."
    find "${dir}" -type f \( -name '*.js' -o -name '*.css' -o -name '*.json' -o -name '*.wasm' -o -name '*.svg' -o -name '*.html' -o -name '*.woff2' -o -name '*.otf' -o -name '*.ttf' \) ! -name '*.gz' ! -name '*.br' -exec gzip -9 -kf {} \;
    echo "   ✅ Gzip compression completed"
  else
    echo "   ⚠️  gzip not available, skipping .gz artifacts"
  fi
  
  # Brotli compression (quality 11 = maximum)
  if command -v brotli >/dev/null 2>&1; then
    echo "   → Creating .br files (brotli -q 11)..."
    find "${dir}" -type f \( -name '*.js' -o -name '*.css' -o -name '*.json' -o -name '*.wasm' -o -name '*.svg' -o -name '*.html' -o -name '*.woff2' -o -name '*.otf' -o -name '*.ttf' \) ! -name '*.gz' ! -name '*.br' -exec brotli -f -k -q 11 {} \;
    echo "   ✅ Brotli compression completed"
  else
    echo "   ⚠️  brotli not available, skipping .br artifacts"
  fi
  
  # Calculate compression stats
  local original_size=$(du -sk "${dir}" | cut -f1)
  echo "   📊 Total size: ${original_size}KB (includes compressed files)"
}

echo "🚀 Building DEV export (optimized)..."
set_env_dev

echo "🧹 Cleaning previous artifacts..."
flutter clean || true

echo "📦 Getting Flutter packages..."
flutter pub get

echo "🔨 Flutter build web (release, MAXIMUM optimization for T3 delivery)..."
# --release: Build ở chế độ release (minified, optimized)
# --pwa-strategy=none: Tắt PWA service worker (giảm kích thước)
# --no-source-maps: Không tạo source maps (giảm kích thước build)
# --tree-shake-icons: Chỉ include icons được sử dụng (giảm kích thước fonts)
# --dart-define=FLUTTER_WEB_USE_SKIA: Use CanvasKit if KEEP_CANVASKIT=1, otherwise HTML renderer
if [ "${KEEP_CANVASKIT:-0}" = "1" ]; then
  echo "   → Building with CanvasKit (KEEP_CANVASKIT=1)..."
  flutter build web \
    --release \
    --pwa-strategy=none \
    --no-source-maps \
    --tree-shake-icons \
    --dart-define=FLUTTER_WEB_USE_SKIA=true \
    --dart-define=FLUTTER_WEB_USE_SKWASM=false
else
  echo "   → Building with HTML renderer (no CanvasKit)..."
  flutter build web \
    --release \
    --pwa-strategy=none \
    --no-source-maps \
    --tree-shake-icons \
    --dart-define=FLUTTER_WEB_USE_SKIA=false
fi

copy_x_app_sdk

echo "📁 Preparing export directory: ${OUT_DIR}"
mkdir -p "${OUT_DIR}"
cp -r build/web/* "${OUT_DIR}/"

# Post-process index.html to fix duplicate loading issues
echo "🔧 Post-processing index.html to prevent duplicate script loading..."
if [ -f "${OUT_DIR}/index.html" ]; then
  python3 - "${OUT_DIR}/index.html" <<'PYTHON_SCRIPT'
import re
import sys

file_path = sys.argv[1]
with open(file_path, 'r', encoding='utf-8') as f:
    content = f.read()

# Remove preload for main.dart.js if exists
content = re.sub(
    r'<link\s+rel="preload"\s+href="main\.dart\.js"[^>]*>',
    '<!-- Removed: main.dart.js preload (flutter_bootstrap.js will load it) -->',
    content,
    flags=re.IGNORECASE
)

# Set renderer and canvasKitBaseUrl based on KEEP_CANVASKIT
import os
keep_canvaskit = os.environ.get('KEEP_CANVASKIT') == '1'

if keep_canvaskit:
    # When KEEP_CANVASKIT=1, use CanvasKit with local path ONLY (no CDN fallback)
    # Remove all existing CanvasKit config to start fresh
    content = re.sub(
        r'window\.flutterConfiguration\.renderer\s*=\s*[^;]+;',
        '',
        content
    )
    content = re.sub(
        r'window\.flutterConfiguration\.canvasKitBaseUrl\s*=\s*[^;]+;',
        '',
        content
    )
    content = re.sub(
        r'window\.flutterConfiguration\.useLocalCanvasKit\s*=\s*[^;]+;',
        '',
        content
    )
    
    # Ensure flutterConfiguration is initialized FIRST, before any other scripts
    # Find the first <script> tag and add config right after it
    if not re.search(r'window\.flutterConfiguration\s*=\s*window\.flutterConfiguration\s*\|\|\s*\{\};', content):
        # Add initialization if missing - insert right after first script tag or in head
        if re.search(r'<script[^>]*>', content):
            content = re.sub(
                r'(<script[^>]*>)',
                r'\1\n    window.flutterConfiguration = window.flutterConfiguration || {};',
                content,
                count=1
            )
        else:
            # Add before closing head if no script tag found
            content = re.sub(
                r'(</head>)',
                r'  <script>\n    window.flutterConfiguration = window.flutterConfiguration || {};\n  </script>\n\1',
                content
            )
    
    # Set CanvasKit config - MUST be set before flutter_bootstrap.js loads
    # Use relative path 'canvaskit/' (will resolve to ./canvaskit/ from document base)
    # Set useLocalCanvasKit to prevent any CDN fallback
    config_block = """    window.flutterConfiguration.renderer = 'canvaskit';
    window.flutterConfiguration.canvasKitBaseUrl = 'canvaskit/';
    window.flutterConfiguration.useLocalCanvasKit = true;
    // Prevent CDN fallback - force local only
    window.flutterConfiguration.canvasKitVariant = 'chromium';"""
    
    # Insert config right after flutterConfiguration initialization
    if re.search(r'window\.flutterConfiguration\s*=\s*window\.flutterConfiguration\s*\|\|\s*\{\};', content):
        content = re.sub(
            r'(window\.flutterConfiguration\s*=\s*window\.flutterConfiguration\s*\|\|\s*\{\};)',
            r'\1\n' + config_block,
            content
        )
    else:
        # Fallback: add right after first script tag
        content = re.sub(
            r'(<script[^>]*>\s*[^<]*)',
            r'\1\n' + config_block,
            content,
            count=1
        )
    
    # Add script to redirect CDN requests to local - MUST run before flutter_bootstrap.js
    redirect_cdn_script = """  <!-- Redirect CanvasKit CDN requests to local files -->
  <script>
    (function() {
      // Redirect CDN URLs to local before Flutter loader runs
      var originalFetch = window.fetch;
      window.fetch = function(input, init) {
        try {
          var url = '';
          if (typeof input === 'string') {
            url = input;
          } else if (input instanceof Request) {
            url = input.url;
          } else if (input && typeof input === 'object' && input.url) {
            url = input.url;
          }
          
          if (url && url.includes('gstatic.com/flutter-canvaskit')) {
            // Extract the path after the engine revision
            // Pattern: https://www.gstatic.com/flutter-canvaskit/REVISION/path
            var match = url.match(/flutter-canvaskit\/[^\/]+\/(.+)$/);
            if (match) {
              var localPath = 'canvaskit/' + match[1];
              console.log('🔄 Redirecting CDN to local:', url.split('/').pop(), '->', localPath);
              // Redirect to local path
              if (typeof input === 'string') {
                return originalFetch.call(this, localPath, init);
              } else if (input instanceof Request) {
                return originalFetch.call(this, new Request(localPath, input));
              } else {
                var newInput = Object.assign({}, input);
                newInput.url = localPath;
                return originalFetch.call(this, newInput.url || localPath, newInput);
              }
            }
          }
        } catch (e) {
          console.error('Error in fetch redirect:', e);
        }
        return originalFetch.apply(this, arguments);
      };
    })();
  </script>"""
    
    # Add preload links for CanvasKit files to optimize loading
    canvaskit_preloads = """  <!-- Preload CanvasKit for faster loading (local only) -->
  <link rel="preload" href="canvaskit/chromium/canvaskit.wasm" as="fetch" crossorigin="anonymous">
  <link rel="preload" href="canvaskit/chromium/canvaskit.js" as="script" crossorigin="anonymous">"""
    
    # Add redirect CDN script and preloads before flutter_bootstrap.js script tag
    if re.search(r'<script[^>]*src=["\']flutter_bootstrap\.js["\']', content):
        content = re.sub(
            r'(<script[^>]*src=["\']flutter_bootstrap\.js["\'][^>]*>)',
            redirect_cdn_script + '\n' + canvaskit_preloads + '\n  ' + r'\1',
            content,
            count=1
        )
    elif '</head>' in content:
        # Add before closing head tag
        content = re.sub(
            r'(</head>)',
            redirect_cdn_script + '\n' + '  ' + canvaskit_preloads + '\n' + r'\1',
            content
        )
else:
    # When KEEP_CANVASKIT is not set, use HTML renderer
    # Replace existing renderer if it's set to 'canvaskit' (handle both escaped and unescaped quotes)
    content = re.sub(
        r'window\.flutterConfiguration\.renderer\s*=\s*(\\?[\'"])canvaskit\1;',
        "window.flutterConfiguration.renderer = 'html';",
        content
    )
    # Add renderer if it doesn't exist
    if 'window.flutterConfiguration.renderer' not in content:
        content = re.sub(
            r'(window\.flutterConfiguration\s*=\s*window\.flutterConfiguration\s*\|\|\s*\{\};)',
            r"\1\n    window.flutterConfiguration.renderer = 'html';",
            content
        )
    # Remove canvasKitBaseUrl and useLocalCanvasKit if they exist (not needed for HTML renderer)
    content = re.sub(
        r'window\.flutterConfiguration\.canvasKitBaseUrl\s*=\s*[^;]+;',
        '',
        content
    )
    content = re.sub(
        r'window\.flutterConfiguration\.useLocalCanvasKit\s*=\s*[^;]+;',
        '',
        content
    )

# Remove duplicate script tags for flutter_bootstrap.js (keep only the last one)
script_tags = list(re.finditer(r'<script[^>]*src=["\']flutter_bootstrap\.js["\'][^>]*>', content, re.IGNORECASE))
if len(script_tags) > 1:
    # Keep only the last one
    for match in script_tags[:-1]:
        content = content[:match.start()] + '<!-- Removed duplicate -->' + content[match.end():]

# Ensure flutter_bootstrap.js has async defer
content = re.sub(
    r'(<script[^>]*src=["\']flutter_bootstrap\.js["\'][^>]*)(>)',
    r'\1 async defer\2',
    content,
    flags=re.IGNORECASE
)

# Remove Branch SDK for web (only needed for mobile)
content = re.sub(
    r'<link[^>]*cdn\.branch\.io[^>]*>',
    '<!-- Removed: Branch SDK preconnect (not needed for web) -->',
    content,
    flags=re.IGNORECASE
)
content = re.sub(
    r'<script[^>]*branch[^>]*>.*?</script>',
    '<!-- Removed: Branch SDK (not needed for web) -->',
    content,
    flags=re.IGNORECASE | re.DOTALL
)

with open(file_path, 'w', encoding='utf-8') as f:
    f.write(content)
PYTHON_SCRIPT
  echo "✅ Post-processed index.html"
fi

if [ -f "web/firebase-messaging-sw.js" ] && [ ! -f "${OUT_DIR}/firebase-messaging-sw.js" ]; then
  cp web/firebase-messaging-sw.js "${OUT_DIR}/"
fi

# Helper script for local preview with SPA fallback
cat > "${OUT_DIR}/serve_local.sh" <<'EOF'
#!/usr/bin/env bash

PORT="${1:-8080}"

python3 - "$PORT" <<'PY'
import http.server
import socketserver
import os
import sys

ROOT = os.getcwd()
PORT = int(sys.argv[1])

class SPAHandler(http.server.SimpleHTTPRequestHandler):
    def do_GET(self):
        resolved = self.translate_path(self.path)
        if not os.path.exists(resolved):
            self.path = '/index.html'
        return super().do_GET()

    def log_message(self, fmt, *args):
        print(f"🌐 {fmt % args}")

with socketserver.TCPServer(('', PORT), SPAHandler) as httpd:
    print(f"🚀 Serving {ROOT} at http://localhost:{PORT}")
    print("💡 SPA fallback enabled. Ctrl+C to stop.")
    httpd.serve_forever()
PY
EOF
chmod +x "${OUT_DIR}/serve_local.sh"

if [ "${KEEP_CANVASKIT:-0}" != "1" ]; then
  echo "🧹 Removing CanvasKit bundle to shrink export (set KEEP_CANVASKIT=1 to keep)..."
  rm -rf "${OUT_DIR}/canvaskit"
  rm -f "${OUT_DIR}/canvaskit.js" "${OUT_DIR}/canvaskit.wasm" 2>/dev/null || true
  echo "✅ CanvasKit removed"
else
  echo "ℹ️ KEEP_CANVASKIT=1 → giữ nguyên thư mục canvaskit."
fi

echo "🗜️ Precompressing assets with maximum compression..."
compress_assets "${OUT_DIR}"

# Calculate final sizes
echo ""
echo "📊 Build size summary:"
echo "   Original files:"
du -sh "${OUT_DIR}" --exclude="*.gz" --exclude="*.br" 2>/dev/null || du -sh "${OUT_DIR}"
echo "   With compression:"
du -sh "${OUT_DIR}"

echo ""
echo "📦 Creating zip archive ${ZIP_FILE} (maximum compression)..."
zip -rq -9 "${ZIP_FILE}" "${OUT_DIR}"

echo ""
echo "🎉 DEV export ready (MAXIMUM OPTIMIZATION for T3 delivery)!"
echo "   📁 Folder : ${OUT_DIR}"
echo "   📦 Zip    : ${ZIP_FILE}"
echo ""
echo "📊 Final sizes:"
zip_size=$(du -sh "${ZIP_FILE}" | cut -f1)
folder_size=$(du -sh "${OUT_DIR}" | cut -f1)
echo "   📦 Zip file: ${zip_size}"
echo "   📁 Folder: ${folder_size}"
echo ""
echo "📌 Delivery notes for T3:"
echo "   ✅ All assets are pre-compressed (gzip + brotli)"
if [ "${KEEP_CANVASKIT:-0}" = "1" ]; then
  echo "   ✅ CanvasKit included (local, not from CDN)"
else
  echo "   ✅ CanvasKit removed (saves ~1.6MB)"
fi
echo "   ✅ Source maps removed (saves space)"
echo "   ✅ PWA disabled (simpler deployment)"
echo "   ✅ Tree-shaken icons (only used icons included)"
echo ""
echo "   💡 Server should serve with Content-Encoding: gzip or br"
echo "   💡 Check .gz and .br files are available for optimal performance"
echo ""
echo "▶️ Quick preview command:"
echo "   cd ${OUT_DIR} && ./serve_local.sh 8080"
echo "⚠️  Avoid using 'python3 -m http.server' directly; it does not handle SPA routes and will 404 on deep links."
