# Script Refactoring Guide

This guide explains how to refactor existing scripts to use the new common library structure.

## Quick Start

### Before (Old Pattern)

```bash
#!/bin/bash
set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

# Load subscription ID
if [ -f "$PROJECT_ROOT/.env" ]; then
    export $(grep -v '^#' "$PROJECT_ROOT/.env" | grep AZURE_SUBSCRIPTION_ID | xargs)
fi

SUBSCRIPTION_ID="${AZURE_SUBSCRIPTION_ID:-fc08d829-4f14-413d-ab27-ce024425db0b}"

# Check Azure CLI
if ! command -v az &> /dev/null; then
    echo -e "${RED}Error: Azure CLI not found${NC}"
    exit 1
fi

# Check Azure login
az account show &> /dev/null || {
    echo -e "${RED}Error: Not logged in to Azure${NC}"
    exit 1
}

az account set --subscription "$SUBSCRIPTION_ID" &> /dev/null || true

echo -e "${GREEN}Starting script...${NC}"
```

### After (New Pattern)

```bash
#!/bin/bash
set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/../lib/init.sh"

# Initialize Azure
SUBSCRIPTION_ID="$(get_subscription_id)"
ensure_azure_cli || exit 1
set_subscription "$SUBSCRIPTION_ID" || true

log_info "Starting script..."
```

## Migration Checklist

### Step 1: Add Library Sourcing

Replace:
```bash
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
```

With:
```bash
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/../lib/init.sh"
```

**Note**: `PROJECT_ROOT` is automatically set by the library.

### Step 2: Remove Color Definitions

Remove:
```bash
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
```

Use logging functions instead:
```bash
log_info "Message"
log_warn "Warning"
log_error "Error"
log_success "Success"
```

### Step 3: Replace Echo Statements

| Old | New |
|-----|-----|
| `echo -e "${GREEN}Success${NC}"` | `log_success "Success"` |
| `echo -e "${RED}Error${NC}"` | `log_error "Error"` |
| `echo -e "${YELLOW}Warning${NC}"` | `log_warn "Warning"` |
| `echo "Info"` | `log_info "Info"` |

### Step 4: Replace Azure CLI Checks

Remove:
```bash
if ! command -v az &> /dev/null; then
    echo -e "${RED}Error: Azure CLI not found${NC}"
    exit 1
fi

az account show &> /dev/null || {
    echo -e "${RED}Error: Not logged in${NC}"
    exit 1
}
```

Replace with:
```bash
ensure_azure_cli || exit 1
```

### Step 5: Replace Subscription Loading

Remove:
```bash
if [ -f "$PROJECT_ROOT/.env" ]; then
    export $(grep -v '^#' "$PROJECT_ROOT/.env" | grep AZURE_SUBSCRIPTION_ID | xargs)
fi

SUBSCRIPTION_ID="${AZURE_SUBSCRIPTION_ID:-fc08d829-4f14-413d-ab27-ce024425db0b}"
az account set --subscription "$SUBSCRIPTION_ID" &> /dev/null || true
```

Replace with:
```bash
SUBSCRIPTION_ID="$(get_subscription_id)"
set_subscription "$SUBSCRIPTION_ID" || true
```

### Step 6: Replace Region Code Mappings

Remove large `declare -A REGION_CODES` blocks and replace with:
```bash
# Get all regions
get_all_regions

# Get specific region code
CODE=$(get_region_code "westeurope")  # Returns "wst"

# Get region name from code
REGION=$(get_region_name "wst")  # Returns "westeurope"
```

## Common Patterns

### Pattern 1: Script with Azure Operations

```bash
#!/bin/bash
set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/../lib/init.sh"

ensure_azure_cli || exit 1

log_section "Script Title"

# Your script logic here
```

### Pattern 2: Script with Region Iteration

```bash
#!/bin/bash
set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/../lib/init.sh"

ensure_azure_cli || exit 1

log_section "Processing Regions"

while IFS=':' read -r region_name region_code; do
    log_info "Processing $region_name ($region_code)..."
    # Your logic here
done < <(get_all_regions)
```

### Pattern 3: Script with Error Handling

```bash
#!/bin/bash
set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/../lib/init.sh"

ensure_azure_cli || exit 1

ERRORS=()

# Process items
for item in "${ITEMS[@]}"; do
    if ! process_item "$item"; then
        ERRORS+=("$item")
        log_error "Failed to process $item"
    else
        log_success "Processed $item"
    fi
done

# Report errors
if [ ${#ERRORS[@]} -gt 0 ]; then
    log_warn "Failed to process ${#ERRORS[@]} items"
    exit 1
fi

log_success "All items processed successfully"
```

## Available Library Functions

### Logging (`lib/common/logging.sh`)
- `log_debug "message"` - Debug level log
- `log_info "message"` - Info level log
- `log_warn "message"` - Warning log
- `log_error "message"` - Error log
- `log_success "message"` - Success message
- `log_failure "message"` - Failure message
- `log_section "title"` - Section header
- `log_subsection "title"` - Subsection header

### Colors (`lib/common/colors.sh`)
- `color_red "text"` - Red text
- `color_green "text"` - Green text
- `color_yellow "text"` - Yellow text
- `color_blue "text"` - Blue text
- `color_cyan "text"` - Cyan text

### Azure CLI (`lib/azure/cli.sh`)
- `check_azure_cli` - Check if Azure CLI is installed
- `check_azure_login` - Check if logged in
- `ensure_azure_cli` - Ensure CLI is ready (installed + logged in)
- `get_current_subscription` - Get current subscription ID
- `get_current_subscription_name` - Get current subscription name

### Configuration (`lib/config/`)
- `get_subscription_id` - Get subscription ID from env or default
- `set_subscription "id"` - Set Azure subscription
- `get_region_code "name"` - Get 3-char region code
- `get_region_name "code"` - Get region name from code
- `get_all_regions` - Get all regions (name:code format)
- `is_valid_region_code "code"` - Validate region code

### Utilities (`lib/common/utils.sh`)
- `require_command "cmd" ["hint"]` - Require command exists
- `command_exists "cmd"` - Check if command exists
- `confirm "prompt" ["default"]` - Confirm action
- `is_dry_run` - Check if in dry-run mode
- `print_header "title" ["width"]` - Print header box

## Testing Refactored Scripts

1. Test with `--dry-run` if supported
2. Verify output formatting matches original
3. Check error messages are clear
4. Ensure backward compatibility if script is called by others

## Examples

See `scripts/azure/check-naming-conventions.sh.refactored` for a complete example of a refactored script.

```bash
# Example migrated scripts (as references):
# - scripts/deployment/fix-resource-groups-and-keyvaults.sh
# - scripts/azure/list-all-resources.sh
# - scripts/key-management/manage-keyvaults.sh
# - scripts/key-management/azure-keyvault-setup.sh
# - scripts/key-management/store-nodes-in-keyvault.sh
```

## Testing

```bash
# Syntax check only (no execution):
bash -n scripts/azure/list-all-resources.sh
bash -n scripts/key-management/manage-keyvaults.sh
bash -n scripts/key-management/azure-keyvault-setup.sh
bash -n scripts/key-management/store-nodes-in-keyvault.sh

# Dry run (where supported):
DRY_RUN=1 scripts/key-management/store-nodes-in-keyvault.sh
```

