#!/bin/bash

# Semi-Automated SCSS → LESS Converter
# Converts SCSS syntax to LESS syntax with safety checks and manual review

set -e

# Get script directory for relative file paths
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Flags
DRY_RUN=false
VERBOSE=false
AUTO_APPROVE=false
CONVERT_ALL=false

# Parse arguments
while [[ $# -gt 0 ]]; do
  case $1 in
    --dry-run)
      DRY_RUN=true
      shift
      ;;
    --verbose)
      VERBOSE=true
      shift
      ;;
    --yes|-y)
      AUTO_APPROVE=true
      shift
      ;;
    --all)
      CONVERT_ALL=true
      shift
      ;;
    --help|-h)
      cat <<EOF
SCSS to LESS Converter

Usage: $0 [OPTIONS] [FILE]

Options:
  --dry-run       Show what would be converted without writing files
  --verbose       Show detailed conversion steps
  --yes, -y       Auto-approve all conversions (use with caution)
  --all           Convert all modified SCSS files
  --help, -h      Show this help message

Examples:
  $0 styles/core/buttons/_buttons.scss
  $0 --dry-run styles/core/forms/_forms.scss
  $0 --all
  $0 --yes --all

Note:
  Variable imports are automatically removed from LESS files since LESS uses
  global scope (variables imported at entry points are available everywhere).
  This differs from SCSS's @use module system which requires explicit imports.

EOF
      exit 0
      ;;
    *)
      SCSS_FILE="$1"
      shift
      ;;
  esac
done

# Function to print colored messages
print_info() {
  echo -e "${BLUE}ℹ${NC} $1"
}

print_success() {
  echo -e "${GREEN}✅${NC} $1"
}

print_warning() {
  echo -e "${YELLOW}⚠️${NC} $1"
}

print_error() {
  echo -e "${RED}❌${NC} $1"
}

# Function to convert SCSS syntax to LESS
convert_syntax() {
  local content="$1"
  local warnings=""

  # Track complex patterns that need review
  local needs_review=false

  # 0a. Remove SCSS-specific @use imports FIRST (sass:string, sass:math, etc.)
  if [[ $VERBOSE == true ]]; then
    print_info "Removing SCSS-specific @use imports"
  fi
  content=$(echo "$content" | sed '/^@use[[:space:]]*["'"'"']sass:/d')

  # 0b. Convert string.unquote() to ~'' BEFORE other conversions
  if [[ $VERBOSE == true ]]; then
    print_info "Converting string.unquote() → ~''"
  fi
  # Handle single quotes
  content=$(echo "$content" | sed -E "s/string\.unquote\('([^']+)'\)/~'\1'/g")
  # Handle double quotes
  content=$(echo "$content" | sed -E "s/string\.unquote\(\"([^\"]+)\"\)/~\"\1\"/g")

  # 0b2. Convert math.div(a, b) to (a / b) BEFORE other conversions
  if [[ $VERBOSE == true ]]; then
    print_info "Converting math.div() → (a / b)"
  fi
  content=$(echo "$content" | sed -E 's/math\.div\(([^,]+),([^)]+)\)/(\1 \/\2)/g')

  # 0c. Convert @use to @import (remove 'as *' and add .less extension)
  if [[ $VERBOSE == true ]]; then
    print_info "Converting @use → @import"
  fi
  # With 'as *' suffix - double quotes
  content=$(echo "$content" | sed -E 's/@use +"([^"]+)" +as +\*;/@import "\1";/g')
  # With 'as *' suffix - single quotes
  content=$(echo "$content" | sed -E "s/@use +'([^']+)' +as +\*;/@import '\1';/g")
  # Without 'as *' - double quotes
  content=$(echo "$content" | sed -E 's/@use +"([^"]+)";/@import "\1";/g')
  # Without 'as *' - single quotes
  content=$(echo "$content" | sed -E "s/@use +'([^']+)';/@import '\1';/g")

  # 0d. Add underscore prefix and .less extension to @import paths
  # SCSS allows omitting _ and extension, LESS requires exact filenames
  if [[ $VERBOSE == true ]]; then
    print_info "Normalizing @import paths for LESS"
  fi
  # Process @import statements with path/filename pattern
  # Add _ prefix if filename doesn't start with _ (unless it's index)
  # Add .less extension if not present
  # IMPORTANT: Anchor to start of line to avoid matching quoted strings in CSS properties
  content=$(echo "$content" | perl -pe '
    s{^\s*\@import\s+(["'\''])([^"'\'']*/)([^_/][^"'\''/]+?)["'\'']}{
      my ($quote, $path, $file) = ($1, $2, $3);
      $file = "_$file" unless $file =~ /^index$/;
      $file .= ".less" unless $file =~ /\.less$/;
      "\@import $quote$path$file$quote"
    }gme;
    s{^\s*\@import\s+(["'\''])([^/]+?)["'\'']}{
      my ($quote, $file) = ($1, $2);
      $file = "_$file" unless $file =~ /^_/ or $file =~ /^index$/;
      $file .= ".less" unless $file =~ /\.less$/;
      "\@import $quote$file$quote"
    }gme;
  ')
  # Add .less extension to imports that already have _ but no extension
  content=$(echo "$content" | sed -E "s/@import (['\"])(_[^'\"]+)(['\"])/\@import \1\2.less\3/g")
  # Fix double .less.less
  content=$(echo "$content" | sed -E 's/\.less\.less/.less/g')

  # 0e. Remove redundant variable imports (LESS has global scope)
  # Variables are imported at entry points (main.less, branding.less, login.less), so component
  # files don't need to re-import them. This is different from SCSS @use which requires
  # explicit imports due to its module system.
  if [[ $VERBOSE == true ]]; then
    print_info "Removing redundant variable imports (LESS has global scope)"
  fi
  # Remove any import of variables/index.less or _login-vars.less
  content=$(echo "$content" | sed -E '/@import[[:space:]]+.*variables\/index\.less/d')
  content=$(echo "$content" | sed -E '/@import[[:space:]]+.*variables\/_login-vars\.less/d')

  # 1. Remove @content keyword (LESS doesn't support it)
  # Mixins with @content need manual expansion - just remove the keyword itself
  if echo "$content" | grep -q "@content"; then
    if [[ $VERBOSE == true ]]; then
      print_info "Removing @content keywords (not supported in LESS)"
    fi
    # Simply remove @content; lines - the mixin caller still needs manual work
    content=$(echo "$content" | sed '/^[[:space:]]*@content;*$/d')
    warnings="${warnings}⚠️  @content removed - mixins need manual handling in LESS\n"
    needs_review=true
  fi

  # 2. Convert mixin definitions (before converting variables): @mixin name() → .name()
  if [[ $VERBOSE == true ]]; then
    print_info "Converting mixin definitions: @mixin → .name()"
  fi
  content=$(echo "$content" | sed -E 's/@mixin[[:space:]]+([a-zA-Z0-9_-]+)/.\1/g')

  # 2. Remove SCSS module namespacing BEFORE converting @include
  if [[ $VERBOSE == true ]]; then
    print_info "Removing module namespacing"
  fi
  # Remove module prefix before dollar signs (variables): module.$var → $var
  content=$(echo "$content" | sed -E 's/[a-zA-Z0-9_-]+\.\$/\$/g')
  # Remove module prefix for mixin calls: @include module.mixin() → @include mixin()
  content=$(echo "$content" | sed -E 's/@include +[a-zA-Z0-9_-]+\.([a-zA-Z0-9_-]+)/@include \1/g')

  # 2b. Convert mixin includes: @include mixin() → .mixin()
  if [[ $VERBOSE == true ]]; then
    print_info "Converting mixin calls: @include → .mixin()"
  fi
  content=$(echo "$content" | sed -E 's/@include[[:space:]]+([a-zA-Z0-9_-]+)/.\1/g')

  # Note: Mixin calls without parentheses will generate LESS deprecated warnings
  # These should be manually fixed in LESS files after conversion
  # Automatic conversion is too error-prone (matches decimals, @content, etc.)

  # 3. Convert variables: $var → @var (after mixins so @mixin doesn't become @.ixin)
  if [[ $VERBOSE == true ]]; then
    print_info "Converting variables: \$var → @var"
  fi
  content=$(echo "$content" | sed -E 's/\$([a-zA-Z0-9_-]+)/@\1/g')

  # 4. Convert interpolation: #{$var} → @{var}
  if [[ $VERBOSE == true ]]; then
    print_info "Converting interpolation: #{} → @{}"
  fi
  content=$(echo "$content" | sed -E 's/#\{@([a-zA-Z0-9_-]+)\}/@{\1}/g')

  # 5. Convert mixin parameter separators: commas → semicolons (LESS prefers semicolons)
  # IMPORTANT: Only convert commas that are clearly inside mixin definitions/calls, not selector commas
  if [[ $VERBOSE == true ]]; then
    print_info "Converting mixin parameter separators: , → ; (in mixin definitions/calls only)"
  fi

  # Strategy: Convert commas to semicolons ONLY in mixin definitions/calls
  # This specifically targets mixin parameter lists: .mixin(@param1, @param2, @param3)
  # But PRESERVES commas in CSS function calls: transform: translate(@x, @y)
  #
  # Key distinction:
  # - Mixin definitions/calls: .name(@params) or lines starting with .
  # - CSS property values: lines with property: value pattern
  #
  # Solution: Only convert commas on lines that start with . (mixin definitions/calls)
  # This reliably identifies mixin contexts and avoids CSS property values

  # Process line by line to have better context control
  content=$(echo "$content" | perl -pe '
    # Only process lines that start with . (after optional whitespace) - these are mixin definitions/calls
    if (/^\s*\./) {
      # On mixin definition/call lines, convert comma-before-@variable to semicolon-before-@variable
      # This simpler pattern works even when default values contain commas (like rgba())
      # because we only care about commas that are directly followed by @variable names
      s/,(\s*@[a-zA-Z0-9_-]+)/;$1/g;
    }
  ')

  # Check if we converted @use
  if echo "$content" | grep -q "@import.*\.less"; then
    warnings="${warnings}⚠️  @use converted to @import - review if needed\n"
  fi

  # 6. Convert @forward to @import
  if echo "$content" | grep -q "@forward "; then
    if [[ $VERBOSE == true ]]; then
      print_info "Converting @forward → @import"
    fi
    content=$(echo "$content" | sed -E "s/@forward[[:space:]]+(['\"])([^'\"]+)\\1/@import \\1\\2\\1/g")
    warnings="${warnings}⚠️  @forward converted to @import - review re-exports\n"
    needs_review=true
  fi

  # 7. Flag complex color functions for review
  if echo "$content" | grep -qE "rgba\(@[a-zA-Z0-9_-]+,[[:space:]]*0\.[0-9]+\)"; then
    warnings="${warnings}⚠️  rgba() with alpha detected - consider using fade() in LESS\n"
    needs_review=true
  fi

  # 8. Convert @extend to LESS :extend() syntax
  # SCSS: @extend .class !optional;
  # LESS: &:extend(.class);
  if echo "$content" | grep -q "@extend "; then
    if [[ $VERBOSE == true ]]; then
      print_info "Converting @extend → &:extend()"
    fi
    # Convert @extend .class !optional; to &:extend(.class);
    content=$(echo "$content" | sed -E 's/^([[:space:]]*)@extend[[:space:]]+\.([a-zA-Z0-9_-]+)[[:space:]]+!optional;/\1\&:extend(.\2);/g')
    # Convert @extend .class; to &:extend(.class);
    content=$(echo "$content" | sed -E 's/^([[:space:]]*)@extend[[:space:]]+\.([a-zA-Z0-9_-]+);/\1\&:extend(.\2);/g')
    # Convert @extend class !optional; to &:extend(.class); (for classes without dot)
    content=$(echo "$content" | sed -E 's/^([[:space:]]*)@extend[[:space:]]+([a-zA-Z0-9_-]+)[[:space:]]+!optional;/\1\&:extend(.\2);/g')
    warnings="${warnings}⚠️  @extend converted to :extend() - review output\n"
  fi

  # 9. Convert @if/@else to LESS guards
  # SCSS: @if $var == value { ... } @else if $var == value2 { ... } @else { ... }
  # LESS: & when (@var = value) { ... } & when (@var = value2) { ... } & when (default()) { ... }
  if echo "$content" | grep -qE "@if |@else"; then
    if [[ $VERBOSE == true ]]; then
      print_info "Converting @if/@else → LESS guards"
    fi

    # Convert @else if to & when (note: after variable conversion $ → @)
    content=$(echo "$content" | sed -E 's/^([[:space:]]*)} @else if ([^{]+)\{/\1}\n\1\& when (\2) {/g')

    # Convert @if var != '' to & when not (var = ~'') BEFORE generic @if conversion
    content=$(echo "$content" | sed -E "s/^([[:space:]]*)@if ([^ ]+) != '' \{/\1\& when not (\2 = ~'') {/g")
    content=$(echo "$content" | sed -E 's/^([[:space:]]*)@if ([^ ]+) != "" \{/\1\& when not (\2 = ~"") {/g')

    # Convert standalone @if to & when
    content=$(echo "$content" | sed -E 's/^([[:space:]]*)@if ([^{]+)\{/\1\& when (\2) {/g')

    # Convert @else { to & when (default()) {
    content=$(echo "$content" | sed -E 's/^([[:space:]]*)} @else \{/\1}\n\1\& when (default()) {/g')

    # Convert == to = in guards (LESS uses single =)
    content=$(echo "$content" | sed -E 's/& when \(([^)]*) == /\& when (\1 = /g')

    # Add comment about guard conversion
    warnings="${warnings}⚠️  @if/@else converted to LESS guards - review conditional logic\n"
    needs_review=true
  fi

  # Return results via file (since we can't return complex data from bash function)
  echo "$content" > /tmp/scss-less-convert-content.tmp
  echo -e "$warnings" > /tmp/scss-less-convert-warnings.tmp
  if [[ $needs_review == true ]]; then
    echo "1" > /tmp/scss-less-convert-needsreview.tmp
  else
    echo "0" > /tmp/scss-less-convert-needsreview.tmp
  fi
}

# Function to convert a single file
convert_file() {
  local scss_file="$1"

  # Strip packages/style/ prefix if present
  scss_file="${scss_file#packages/style/}"

  # Check skip list for files that need manual conversion
  if [[ -f "$SCRIPT_DIR/scss-to-less-skip" ]]; then
    if grep -q "^${scss_file}$" "$SCRIPT_DIR/scss-to-less-skip" 2>/dev/null; then
      print_warning "Skipping $scss_file (in skip list - requires manual sync)"
      return 0
    fi
  fi

  # Special case: stroke icons file uses a different conversion process
  if [[ "$scss_file" == *"_dlt-c8y-icons-stroke.scss" ]]; then
    print_info "Converting stroke icons file (uses special converter)"
    if [[ $DRY_RUN == false ]]; then
      node "$SCRIPT_DIR/convert-stroke-icons-to-less.js"
      print_success "Stroke icons converted successfully"
    else
      print_info "Dry run - would run: node $SCRIPT_DIR/convert-stroke-icons-to-less.js"
    fi
    return 0
  fi

  # Check if file exists (may be a renamed/deleted file from git diff)
  if [[ ! -f "$scss_file" ]]; then
    print_warning "Skipping $scss_file (file not found - may have been renamed/deleted)"
    return 0
  fi

  # Determine LESS file path
  local less_file="${scss_file%.scss}.less"

  if [[ ! -f "$less_file" ]]; then
    print_warning "Skipping $scss_file (no corresponding LESS file: $less_file)"
    return 0
  fi

  print_info "Converting: $scss_file → $less_file"

  # Read SCSS content
  local scss_content=$(cat "$scss_file")

  # Convert syntax
  convert_syntax "$scss_content"

  # Read results
  local less_content=$(cat /tmp/scss-less-convert-content.tmp)
  local warnings=$(cat /tmp/scss-less-convert-warnings.tmp)
  local needs_review=$(cat /tmp/scss-less-convert-needsreview.tmp)

  # Clean up temp files
  rm -f /tmp/scss-less-convert-content.tmp /tmp/scss-less-convert-warnings.tmp /tmp/scss-less-convert-needsreview.tmp

  # Show warnings if any
  if [[ -n "$warnings" && "$warnings" != "" ]]; then
    echo ""
    echo -e "$warnings"
  fi

  # Create temp file with new content
  echo "$less_content" > /tmp/scss-less-new-content.tmp

  # Show diff
  echo ""
  print_info "Changes to be applied:"
  echo ""

  # Create a colored diff
  if command -v colordiff >/dev/null 2>&1; then
    diff -u "$less_file" /tmp/scss-less-new-content.tmp | colordiff || true
  else
    diff -u "$less_file" /tmp/scss-less-new-content.tmp || true
  fi

  echo ""

  # Check if there are actual changes
  if diff -q "$less_file" /tmp/scss-less-new-content.tmp >/dev/null 2>&1; then
    print_success "No changes needed - files already in sync"
    rm /tmp/scss-less-new-content.tmp
    return 0
  fi

  # Ask for confirmation (unless dry-run or auto-approve)
  if [[ $DRY_RUN == true ]]; then
    print_info "Dry run - no files modified"
    rm /tmp/scss-less-new-content.tmp
    return 0
  fi

  if [[ $AUTO_APPROVE == false ]]; then
    if [[ $needs_review == "1" ]]; then
      print_warning "Complex patterns detected - manual review recommended"
    fi

    echo -n "Apply these changes to $less_file? [y/N] "
    read -r response

    if [[ ! "$response" =~ ^[Yy]$ ]]; then
      print_info "Skipped - no changes made"
      rm /tmp/scss-less-new-content.tmp
      return 0
    fi
  fi

  # Apply changes
  mv /tmp/scss-less-new-content.tmp "$less_file"
  print_success "Converted: $less_file"

  return 0
}

# Main execution
echo "==========================================="
echo "SCSS → LESS Semi-Automated Converter"
echo "==========================================="
echo ""

if [[ $CONVERT_ALL == true ]]; then
  # Convert all modified SCSS files
  print_info "Finding all modified SCSS files..."

  SCSS_FILES=$(git diff --name-only HEAD -- . | grep '\.scss$' || true)
  SCSS_STAGED=$(git diff --cached --name-only -- . | grep '\.scss$' || true)
  ALL_SCSS=$(printf "%s\n%s" "$SCSS_FILES" "$SCSS_STAGED" | sort -u | grep -v '^$' || true)

  if [[ -z "$ALL_SCSS" ]]; then
    print_success "No modified SCSS files found"
    exit 0
  fi

  SCSS_COUNT=$(echo "$ALL_SCSS" | wc -l | tr -d ' ')
  print_info "Found $SCSS_COUNT modified SCSS file(s)"
  echo ""

  SUCCESS_COUNT=0
  SKIP_COUNT=0
  ERROR_COUNT=0

  while IFS= read -r file; do
    if [[ -z "$file" ]]; then
      continue
    fi

    if convert_file "$file"; then
      SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
    else
      ERROR_COUNT=$((ERROR_COUNT + 1))
    fi

    echo ""
  done <<< "$ALL_SCSS"

  echo "==========================================="
  print_info "Conversion Summary:"
  print_success "$SUCCESS_COUNT file(s) converted"
  if [[ $ERROR_COUNT -gt 0 ]]; then
    print_error "$ERROR_COUNT file(s) failed"
  fi
  echo "==========================================="

  exit 0

elif [[ -n "$SCSS_FILE" ]]; then
  # Convert single file
  if convert_file "$SCSS_FILE"; then
    exit 0
  else
    exit 1
  fi

else
  # No file specified
  print_error "No file specified"
  echo ""
  echo "Usage: $0 [OPTIONS] <scss-file>"
  echo "       $0 --all"
  echo ""
  echo "Use --help for more options"
  exit 1
fi
