#!/usr/bin/env bash
set -euo pipefail

# Complete Project Generation Script
# Generates a full Rust web service from templates

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_SPEC="${SCRIPT_DIR}/project-spec.yaml"
TEMPLATES_DIR="${SCRIPT_DIR}/templates"
OUTPUT_DIR="${SCRIPT_DIR}/output"

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

# Default variables (can be overridden)
PROJECT_NAME="my-web-service"
VERSION="0.1.0"
AUTHOR="Generated by ggen"
PORT="3000"
LOG_LEVEL="info"

log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

show_usage() {
    cat <<EOF
Usage: $0 [COMMAND] [OPTIONS]

Commands:
    validate    Validate all templates
    generate    Generate complete project
    clean       Remove generated output
    help        Show this help message

Options for generate:
    --project-name NAME    Set project name (default: my-web-service)
    --port PORT           Set server port (default: 3000)
    --author AUTHOR       Set author name
    --version VERSION     Set version (default: 0.1.0)

Examples:
    $0 validate
    $0 generate
    $0 generate --project-name my-api --port 8080
    $0 clean

EOF
}

validate_templates() {
    log_info "Validating templates..."

    local failed=0

    # Check if templates directory exists
    if [[ ! -d "$TEMPLATES_DIR" ]]; then
        log_error "Templates directory not found: $TEMPLATES_DIR"
        return 1
    fi

    # Check each template file
    for template in "$TEMPLATES_DIR"/*.tmpl; do
        if [[ -f "$template" ]]; then
            local filename=$(basename "$template")

            # Basic validation: check if file is readable
            if [[ ! -r "$template" ]]; then
                log_error "Cannot read template: $filename"
                failed=1
                continue
            fi

            # Check for common template syntax errors
            if grep -q '{{[^}]*$' "$template"; then
                log_error "Unclosed template variable in: $filename"
                failed=1
                continue
            fi

            log_success "Validated: $filename"
        fi
    done

    if [[ $failed -eq 0 ]]; then
        log_success "All templates validated successfully"
        return 0
    else
        log_error "Template validation failed"
        return 1
    fi
}

substitute_variables() {
    local input_file="$1"
    local output_file="$2"

    # Read template
    local content
    content=$(<"$input_file")

    # Substitute variables
    content="${content//\{\{project_name\}\}/$PROJECT_NAME}"
    content="${content//\{\{version\}\}/$VERSION}"
    content="${content//\{\{author\}\}/$AUTHOR}"
    content="${content//\{\{port\}\}/$PORT}"
    content="${content//\{\{log_level\}\}/$LOG_LEVEL}"
    content="${content//\{\{rust_edition\}\}/2021}"
    content="${content//\{\{description\}\}/A production-ready Rust web service}"
    content="${content//\{\{api_prefix\}\}//api}"

    # Write output
    echo "$content" > "$output_file"
}

generate_project() {
    log_info "Generating project: $PROJECT_NAME"

    # Create output directory structure
    local project_dir="$OUTPUT_DIR/$PROJECT_NAME"
    mkdir -p "$project_dir"/{src/{models,api,config},tests}

    # Generate Cargo.toml
    log_info "Generating Cargo.toml..."
    substitute_variables \
        "$TEMPLATES_DIR/cargo-toml.tmpl" \
        "$project_dir/Cargo.toml"

    # Generate main.rs
    log_info "Generating src/main.rs..."
    substitute_variables \
        "$TEMPLATES_DIR/main-rs.tmpl" \
        "$project_dir/src/main.rs"

    # Generate models
    log_info "Generating models..."
    substitute_variables \
        "$TEMPLATES_DIR/models-mod.tmpl" \
        "$project_dir/src/models/mod.rs"
    substitute_variables \
        "$TEMPLATES_DIR/user-model.tmpl" \
        "$project_dir/src/models/user.rs"
    substitute_variables \
        "$TEMPLATES_DIR/product-model.tmpl" \
        "$project_dir/src/models/product.rs"

    # Generate API
    log_info "Generating API..."
    substitute_variables \
        "$TEMPLATES_DIR/api-mod.tmpl" \
        "$project_dir/src/api/mod.rs"
    substitute_variables \
        "$TEMPLATES_DIR/api-handlers.tmpl" \
        "$project_dir/src/api/handlers.rs"
    substitute_variables \
        "$TEMPLATES_DIR/api-routes.tmpl" \
        "$project_dir/src/api/routes.rs"

    # Generate config
    log_info "Generating config..."
    substitute_variables \
        "$TEMPLATES_DIR/config-mod.tmpl" \
        "$project_dir/src/config/mod.rs"
    substitute_variables \
        "$TEMPLATES_DIR/config-settings.tmpl" \
        "$project_dir/src/config/settings.rs"

    # Generate tests
    log_info "Generating integration tests..."
    substitute_variables \
        "$TEMPLATES_DIR/integration-test.tmpl" \
        "$project_dir/tests/integration_test.rs"

    log_success "Project structure generated"

    # Build project
    log_info "Building project..."
    if (cd "$project_dir" && cargo build 2>&1 | tee build.log); then
        log_success "Build successful"
    else
        log_error "Build failed. Check $project_dir/build.log for details"
        return 1
    fi

    # Run tests
    log_info "Running tests..."
    if (cd "$project_dir" && cargo test 2>&1 | tee test.log); then
        log_success "All tests passed"
    else
        log_error "Tests failed. Check $project_dir/test.log for details"
        return 1
    fi

    # Format code
    log_info "Formatting code..."
    (cd "$project_dir" && cargo fmt)

    # Show summary
    echo ""
    log_success "✓ Project generation complete!"
    echo ""
    echo "Project location: $project_dir"
    echo ""
    echo "Next steps:"
    echo "  cd $project_dir"
    echo "  cargo run"
    echo ""
    echo "API will be available at: http://localhost:$PORT"
    echo ""
    echo "Endpoints:"
    echo "  GET  /health             - Health check"
    echo "  GET  /api/users          - List users"
    echo "  POST /api/users          - Create user"
    echo "  GET  /api/products       - List products"
    echo "  POST /api/products       - Create product"
    echo ""
}

clean_output() {
    log_info "Cleaning output directory..."
    if [[ -d "$OUTPUT_DIR" ]]; then
        rm -rf "$OUTPUT_DIR"
        log_success "Output directory cleaned"
    else
        log_warning "Output directory does not exist"
    fi
}

# Parse command line arguments
COMMAND="${1:-help}"
shift || true

case "$COMMAND" in
    validate)
        validate_templates
        ;;

    generate)
        # Parse options
        while [[ $# -gt 0 ]]; do
            case "$1" in
                --project-name)
                    PROJECT_NAME="$2"
                    shift 2
                    ;;
                --port)
                    PORT="$2"
                    shift 2
                    ;;
                --author)
                    AUTHOR="$2"
                    shift 2
                    ;;
                --version)
                    VERSION="$2"
                    shift 2
                    ;;
                *)
                    log_error "Unknown option: $1"
                    show_usage
                    exit 1
                    ;;
            esac
        done

        # Validate first
        if ! validate_templates; then
            exit 1
        fi

        # Generate project
        generate_project
        ;;

    clean)
        clean_output
        ;;

    help|--help|-h)
        show_usage
        ;;

    *)
        log_error "Unknown command: $COMMAND"
        show_usage
        exit 1
        ;;
esac
