#!/bin/bash

# Check if input file is provided
if [ $# -ne 1 ]; then
    echo "Usage: $0 <sql_file>"
    exit 1
fi

SQL_FILE="$1"
BASE_DIR="sql_objects"

# Create directory structure
mkdir -p "$BASE_DIR/procedures"

# Ensure proper permissions
chmod -R 755 "$BASE_DIR"

# Function to clean filename
clean_filename() {
    # Remove brackets, convert dots and spaces to underscores, remove parentheses
    echo "$1" | sed 's/\[\|\]//g' | tr '.' '_' | tr ' ' '_' | sed 's/[()]//g' | sed 's/__*/_/g' | sed 's/_$//'
}

# Function to extract procedure name
extract_procedure_name() {
    # More flexible procedure name extraction
    local name=$(echo "$1" | sed -nE 's/.*CREATE[[:space:]]+PROC(EDURE)?[[:space:]]+(\[[^]]+\](\.[^]]+)?|\S+).*/\2/pi' | tr -d '[]')
    echo "$name"
}

# Function to extract schema name (if present)
extract_schema_name() {
    # Extract schema name with more flexible matching
    local schema=$(echo "$1" | sed -nE 's/.*CREATE[[:space:]]+PROC(EDURE)?[[:space:]]+\[?([^.]+)\.([^]]+)\]?.*/\2/pi')
    if [ -z "$schema" ]; then
        # Try alternative extraction
        schema=$(echo "$1" | sed -nE 's/.*CREATE[[:space:]]+PROC(EDURE)?[[:space:]]+\[?([^]]+)\]?.*/\2/pi' | cut -d. -f1)
    fi
    
    if [ -z "$schema" ]; then
        echo "dbo"  # Default schema if not specified
    else
        echo "$schema" | tr -d '[]'
    fi
}

# Function to process each procedure statement
process_procedure() {
    local procedure_statement="$1"
    local procedure_name=$(extract_procedure_name "$procedure_statement")
    local schema_name=$(extract_schema_name "$procedure_statement")
    
    # Skip if we couldn't extract procedure name
    if [ -z "$procedure_name" ]; then
        echo "Warning: Could not extract procedure name from:"
        echo "$procedure_statement"
        return
    fi
    
    # Clean filename and save
    clean_name=$(clean_filename "${schema_name}_${procedure_name}")
    output_file="$BASE_DIR/procedures/${clean_name}.sql"
    
    # Trim whitespace and ensure semicolon at end if not already present
    procedure_statement=$(echo "$procedure_statement" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
    if [[ "$procedure_statement" != *\; ]]; then
        procedure_statement="${procedure_statement};"
    fi
    
    # Save the procedure
    echo "$procedure_statement" > "$output_file"
    echo "Created: $output_file"
}

# Main processing function
extract_procedures() {
    local current_statement=""
    local capturing_procedure=false
    local depth=0
    
    # Disable case sensitivity
    shopt -s nocasematch
    
    # Read the file line by line
    while IFS= read -r line || [ -n "$line" ]; do
        # Skip empty lines and pure comment lines
        if [ -z "${line// }" ] || [[ "$line" =~ ^[[:space:]]*-- ]]; then
            continue
        fi
        
        # Check for procedure start (more flexible)
        if [[ "$line" =~ CREATE[[:space:]]+PROC(EDURE)?[[:space:]]+ ]]; then
            # Process previous statement if any
            if [ -n "$current_statement" ] && $capturing_procedure; then
                process_procedure "$current_statement"
            fi
            
            # Start new procedure statement
            current_statement="$line"
            capturing_procedure=true
            depth=0
            
            # Check if GO is on the same line
            if [[ "$line" =~ GO[[:space:]]*$ ]]; then
                # Remove GO and process
                current_statement=$(echo "$current_statement" | sed 's/[[:space:]]*GO[[:space:]]*$//')
                process_procedure "$current_statement"
                current_statement=""
                capturing_procedure=false
            fi
            continue
        fi
        
        # If we're capturing a procedure
        if $capturing_procedure; then
            # Track BEGIN/END blocks to ensure we capture the entire procedure
            if [[ "$line" =~ BEGIN ]]; then
                ((depth++))
            fi
            
            if [[ "$line" =~ END ]]; then
                ((depth--))
            fi
            
            # Add line to current statement
            current_statement+=" $line"
            
            # Check for GO statement or end of procedure
            if [[ "$line" =~ ^[[:space:]]*GO[[:space:]]*$ ]] || 
               ([[ "$line" =~ END ]] && [[ $depth -le 0 ]]); then
                # Remove GO and process
                current_statement=$(echo "$current_statement" | sed 's/[[:space:]]*GO[[:space:]]*$//; s/;[[:space:]]*$//')
                process_procedure "$current_statement"
                current_statement=""
                capturing_procedure=false
                depth=0
            fi
        fi
    done
    
    # Process any remaining procedure statement
    if [ -n "$current_statement" ] && $capturing_procedure; then
        process_procedure "$current_statement"
    fi
    
    # Re-enable case sensitivity
    shopt -u nocasematch
}

# Remove comment lines and process
echo "Extracting stored procedures..."
sed 's/--.*$//' "$SQL_FILE" | extract_procedures

echo "Stored procedures have been saved in $BASE_DIR/procedures"

# Count and list files
count=$(ls -1 "$BASE_DIR/procedures"/*.sql 2>/dev/null | wc -l || echo 0)
echo -e "\nTotal stored procedures extracted: $count"

if [ "$count" -gt 0 ]; then
    echo -e "\nExtracted stored procedures:"
    for file in "$BASE_DIR/procedures"/*.sql; do
        if [ -f "$file" ]; then
            echo "- $(basename "$file")"
        fi
    done
fi