#!/bin/bash
set -e

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

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

# Build directories
CPP_DIR="$PROJECT_ROOT/internal/cpp"
BUILD_DIR="$CPP_DIR/cmake-build-release"
RAGFLOW_SERVER_BINARY="$PROJECT_ROOT/bin/server_main"
ADMIN_SERVER_BINARY="$PROJECT_ROOT/bin/admin_server"
RAGFLOW_CLI_BINARY="$PROJECT_ROOT/bin/ragflow_cli"

echo -e "${GREEN}=== RAGFlow Go Server Build Script ===${NC}"

# Function to print section headers
print_section() {
    echo -e "\n${YELLOW}>>> $1${NC}"
}

# Check dependencies
check_cpp_deps() {
    print_section "Checking c++ dependencies"

    command -v cmake >/dev/null 2>&1 || { echo -e "${RED}Error: cmake is required but not installed.${NC}"; exit 1; }
    command -v g++ >/dev/null 2>&1 || { echo -e "${RED}Error: g++ is required but not installed.${NC}"; exit 1; }

    # Check for pcre2 library
    if [ -f "/usr/lib/x86_64-linux-gnu/libpcre2-8.a" ] || [ -f "/usr/local/lib/libpcre2-8.a" ]; then
        echo "✓ pcre2 library found"
    else
        echo -e "${YELLOW}Warning: libpcre2-8.a not found. You may need to install libpcre2-dev:${NC}"
        echo "  sudo apt-get install libpcre2-dev"
    fi

    echo "✓ Required tools are available"
}

check_go_deps() {
    print_section "Checking go dependencies"
    
    command -v go >/dev/null 2>&1 || { echo -e "${RED}Error: go is required but not installed.${NC}"; exit 1; }

    echo "✓ Required tools are available"
}

# Build C++ static library
build_cpp() {
    print_section "Building C++ static library"
    
    mkdir -p "$BUILD_DIR"
    cd "$BUILD_DIR"
    
    echo "Running cmake..."
    cmake .. -DCMAKE_BUILD_TYPE=Release
    
    echo "Building librag_tokenizer_c_api.a..."
    make rag_tokenizer_c_api -j$(nproc)
    
    if [ ! -f "$BUILD_DIR/librag_tokenizer_c_api.a" ]; then
        echo -e "${RED}Error: Failed to build C++ static library${NC}"
        exit 1
    fi
    
    echo -e "${GREEN}✓ C++ static library built successfully${NC}"
}

# Build Go server
build_go() {
    print_section "Building RAGFlow go"
    
    cd "$PROJECT_ROOT"
    
    # Check if C++ library exists
    if [ ! -f "$BUILD_DIR/librag_tokenizer_c_api.a" ]; then
        echo -e "${RED}Error: C++ static library not found. Run with --cpp first.${NC}"
        exit 1
    fi

    # Check for pcre2 library — known Linux paths + macOS Homebrew (Apple Silicon
    # at /opt/homebrew, Intel Macs at /usr/local).
    if [ -f "/usr/lib/x86_64-linux-gnu/libpcre2-8.a" ] \
       || [ -f "/usr/local/lib/libpcre2-8.a" ] \
       || [ -f "/opt/homebrew/lib/libpcre2-8.a" ]; then
        echo "✓ pcre2 library found"
    else
        if [ "$(uname)" = "Darwin" ]; then
            echo -e "${RED}Error: libpcre2-8.a not found. Install with: brew install pcre2${NC}"
            exit 1
        fi
        echo -e "${YELLOW}Warning: libpcre2-8.a not found. You may need to install libpcre2-dev:${NC}"
        sudo apt -y install libpcre2-dev
    fi
    
    echo "Building RAGFlow binary: $RAGFLOW_SERVER_BINARY, $ADMIN_SERVER_BINARY, and $RAGFLOW_CLI_BINARY"
    GOPROXY=${GOPROXY:-https://goproxy.cn,https://proxy.golang.org,direct} CGO_ENABLED=1 go build -o "$RAGFLOW_SERVER_BINARY" cmd/server_main.go
    GOPROXY=${GOPROXY:-https://goproxy.cn,https://proxy.golang.org,direct} CGO_ENABLED=1 go build -o "$ADMIN_SERVER_BINARY" cmd/admin_server.go
    GOPROXY=${GOPROXY:-https://goproxy.cn,https://proxy.golang.org,direct} CGO_ENABLED=1 go build -o "$RAGFLOW_CLI_BINARY" cmd/ragflow_cli.go

    if [ ! -f "$RAGFLOW_SERVER_BINARY" ]; then
        echo -e "${RED}Error: Failed to build RAGFlow server binary${NC}"
        exit 1
    fi

    if [ ! -f "$ADMIN_SERVER_BINARY" ]; then
        echo -e "${RED}Error: Failed to build Admin server binary${NC}"
        exit 1
    fi

    echo -e "${GREEN}✓ Go ragflow_server built successfully: $RAGFLOW_SERVER_BINARY${NC}"
    echo -e "${GREEN}✓ Go admin_server built successfully: $ADMIN_SERVER_BINARY${NC}"
    echo -e "${GREEN}✓ Go ragflow_cli built successfully: $RAGFLOW_CLI_BINARY${NC}"
}

# Clean build artifacts
clean() {
    print_section "Cleaning build artifacts"
    
    rm -rf "$BUILD_DIR"
    rm -f "$RAGFLOW_SERVER_BINARY"
    rm -f "$ADMIN_SERVER_BINARY"

    echo -e "${GREEN}✓ Build artifacts cleaned${NC}"
}

# Run the server
run() {
    if [ ! -f "$ADMIN_SERVER_BINARY" ]; then
        echo -e "${RED}Error: Binary not found. Build first with --all or --go${NC}"
        exit 1
    fi

    print_section "Starting ADMIN server"
    cd "$PROJECT_ROOT"
    ./admin_server

    if [ ! -f "$RAGFLOW_SERVER_BINARY" ]; then
        echo -e "${RED}Error: Binary not found. Build first with --all or --go${NC}"
        exit 1
    fi
    
    print_section "Starting server"
    cd "$PROJECT_ROOT"
    ./server_main
}

# Show help
show_help() {
    cat << EOF
Usage: $0 [OPTIONS]

Build script for RAGFlow Go server with C++ bindings.

OPTIONS:
    --all, -a       Build everything (C++ library + Go server) [default]
    --cpp, -c       Build only C++ static library
    --go, -g        Build only Go server (requires C++ library to be built)
    --clean, -C     Clean all build artifacts
    --run, -r       Build and run the server
    --help, -h      Show this help message

EXAMPLES:
    $0              # Build everything
    $0 --cpp        # Build only C++ library
    $0 --go         # Build only Go server
    $0 --run        # Build and run
    $0 --clean      # Clean build artifacts

DEPENDENCIES:
    - cmake >= 4.0
    - go >= 1.24
    - g++ with C++17/23 support
    - libpcre2-dev
EOF
}

# Main function
main() {
    case "${1:-}" in
        --cpp|-c)
            check_cpp_deps
            build_cpp
            ;;
        --go|-g)
            check_go_deps
            build_go
            ;;
        --clean|-C)
            clean
            ;;
        --run|-r)
            check_cpp_deps
            check_go_deps
            build_cpp
            build_go
            run
            ;;
        --help|-h)
            show_help
            ;;
        --all|-a|"")
            check_cpp_deps
            check_go_deps
            build_cpp
            build_go
            echo -e "\n${GREEN}=== Build completed successfully! ===${NC}"
            echo "Binary: $RAGFLOW_SERVER_BINARY, $ADMIN_SERVER_BINARY"
            ;;
        *)
            echo -e "${RED}Unknown option: $1${NC}"
            show_help
            exit 1
            ;;
    esac
}

main "$@"
