#!/bin/bash

set -e # Exit immediately if a command exits with a non-zero status.
set -u # Treat unset variables as an error when substituting.
set -o pipefail # The return value of a pipeline is the status of the last command to exit with a non-zero status.

# Configuration for OpenAPI Generator JAR
OPENAPI_GENERATOR_VERSION="7.13.0"
OPENAPI_JAR_FILENAME="openapi-generator-cli-${OPENAPI_GENERATOR_VERSION}.jar"
OPENAPI_DOWNLOAD_URL="https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/${OPENAPI_GENERATOR_VERSION}/${OPENAPI_JAR_FILENAME}"

XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
JAR_DIR="${XDG_DATA_HOME}/openapi-generator"
JAR_PATH="${JAR_DIR}/${OPENAPI_JAR_FILENAME}"

usage() {
    local script_location_dir
    script_location_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
    local python_default_output_dir="${script_location_dir}/python"

    echo "Usage: $0 --<client-type> --spec <openapi_spec_url_or_file> [options]"
    echo ""
    echo "This script automates the generation of API clients using OpenAPI Generator."
    echo "It ensures Java 11+ is available and downloads the generator JAR if needed."
    echo "NOTE: Includes --skip-validate-spec to bypass initial OpenAPI spec validation errors."
    echo "      However, spec issues might still cause errors during generation (see recent logs)."
    echo ""
    echo "Client Types:"
    echo "  --python-client        Generate a Python client."
    echo ""
    echo "Required Arguments:"
    echo "  --spec <url_or_path>   URL or local file path to the OpenAPI specification."
    echo ""
    echo "General Options:"
    echo "  --output <dir>         Directory to output the generated client."
    echo "                         For Python, defaults to: '${python_default_output_dir}'"
    echo "                         For others, defaults to: './generated_client'"
    echo "  --help                 Show this help message."
    echo ""
    echo "Options for --python-client:"
    echo "  --package-name <name>  Python package name (default: goodmem_client)."
    echo "  --package-version <ver> Python package version (default: 1.0.0)."
    echo "  --project-name <name>  Project name, used as artifactId (default: goodmem_client)."
    echo ""
    echo "Python client generation settings for FULL output (APIs, Models, Supporting Files, Docs, Tests, Project files):"
    echo "  - Generator: 'python' (default library: urllib3, providing baseline external dependencies)."
    echo "  - Full project structure (generateSourceCodeOnly=false)."
    echo "  - Includes API/Model documentation and tests (apiDocs=true, modelDocs=true, apiTests=true, modelTests=true)."
    echo "  - Generates 'apis', 'models', and 'supportingFiles'."
    echo ""
    echo "Example (assuming this script is in 'clients/' directory):"
    echo "  $0 --python-client --spec http://localhost:8080/openapi"
    echo ""
    echo "JAR Location: ${JAR_PATH}"
}

get_java_major_version() {
    local version_line
    version_line=$(java -version 2>&1 | grep -i "version")
    local major_version=""
    if [[ "$version_line" =~ version[[:space:]]+\"([0-9]+)(\.[0-9]+)*(_[0-9]+)?\" ]]; then
        major_version="${BASH_REMATCH[1]}"
        if [[ "$major_version" == "1" ]]; then
            if [[ "$version_line" =~ version[[:space:]]+\"1\.([0-9]+) ]]; then
                major_version="${BASH_REMATCH[1]}"
            else echo "0"; return; fi
        fi
    elif [[ "$version_line" =~ (openjdk|java)[[:space:]]+version[[:space:]]+([0-9]+)\. ]]; then
        major_version="${BASH_REMATCH[2]}"
        if [[ "$major_version" == "1" ]]; then
            if [[ "$version_line" =~ (openjdk|java)[[:space:]]+version[[:space:]]+1\.([0-9]+) ]]; then
                major_version="${BASH_REMATCH[2]}"
            else echo "0"; return; fi
        fi
    else echo "0"; return; fi
    echo "$major_version"
}

check_java_version() {
    echo "INFO: Checking Java version..."
    if ! command -v java &> /dev/null; then
        echo "ERROR: Java command not found. Please install Java 11 or newer."; exit 1
    fi
    local major_version
    major_version=$(get_java_major_version)
    if ! [[ "$major_version" =~ ^[1-9][0-9]*$ ]] || [ "$major_version" -eq 0 ]; then
        echo "ERROR: Could not reliably determine Java major version."; java -version 2>&1; exit 1
    fi
    if [ "$major_version" -lt 11 ]; then
        echo "ERROR: Installed Java version $major_version. Requires Java 11+."; java -version 2>&1; exit 1
    fi
    echo "INFO: Java version $major_version found. Meets minimum requirement (Java 11+)."
}

ensure_jar_downloaded() {
    if [ ! -f "$JAR_PATH" ]; then
        echo "INFO: OpenAPI Generator CLI JAR not found at '$JAR_PATH'."
        echo "INFO: Downloading ${OPENAPI_JAR_FILENAME} from $OPENAPI_DOWNLOAD_URL..."
        mkdir -p "$JAR_DIR"
        if command -v curl &> /dev/null; then
            if ! curl -# -L "$OPENAPI_DOWNLOAD_URL" -o "$JAR_PATH"; then
                 echo "ERROR: curl failed to download JAR."; rm -f "$JAR_PATH"; exit 1
            fi
        elif command -v wget &> /dev/null; then
            if ! wget --progress=bar:force "$OPENAPI_DOWNLOAD_URL" -O "$JAR_PATH"; then
                echo "ERROR: wget failed to download JAR."; rm -f "$JAR_PATH"; exit 1
            fi
        else echo "ERROR: Neither curl nor wget is available."; exit 1; fi
        if [ -f "$JAR_PATH" ] && [ -s "$JAR_PATH" ]; then
            echo "INFO: Download complete: $JAR_PATH"
        else echo "ERROR: Failed to download/verify JAR."; rm -f "$JAR_PATH"; exit 1; fi
    else
        echo "INFO: OpenAPI Generator CLI JAR already exists at '$JAR_PATH'."
    fi
}

generate_python_client() {
    echo "------------------------------------------------------"
    echo "INFO: Starting Python client generation..."
    echo "------------------------------------------------------"
    echo "  OpenAPI Specification:    $OPENAPI_SPEC"
    echo "  Output Directory (root):  $OUTPUT_DIR"
    echo "  Python Package Name:      $PYTHON_PACKAGE_NAME"
    echo "  Python Package Version:   $PYTHON_PACKAGE_VERSION"
    echo "  Python Project Name (ID): $PYTHON_PROJECT_NAME"
    echo "  (Generated package will be at: ${OUTPUT_DIR}/${PYTHON_PACKAGE_NAME})"
    echo "  Spec Validation: SKIPPED (--skip-validate-spec is ON)"

    # Settings for FULL file output (project files, docs, tests, etc.)
    local additional_props="generateSourceCodeOnly=false,apiDocs=true,modelDocs=true,apiTests=true,modelTests=true"
    local global_props="apis,models,supportingFiles" # Ensures core code components

    mkdir -p "$OUTPUT_DIR"
    echo "INFO: Ensured output directory (root for generator) exists: $OUTPUT_DIR"

    # Check for config file
    local config_file="${OUTPUT_DIR}/.openapi-generator-config.json"
    local cmd_array=(
        "java" "-jar" "$JAR_PATH" "generate"
        "-i" "$OPENAPI_SPEC"
        "-g" "python"
        "-o" "$OUTPUT_DIR"
        "--package-name" "$PYTHON_PACKAGE_NAME"
        "--artifact-version" "$PYTHON_PACKAGE_VERSION"
        "--artifact-id" "$PYTHON_PROJECT_NAME"
        "--additional-properties" "$additional_props"
        "--global-property" "$global_props"
        "--skip-validate-spec"
    )
    
    # Add config file if it exists
    if [ -f "$config_file" ]; then
        cmd_array+=("-c" "$config_file")
        echo "INFO: Using OpenAPI Generator config file: $config_file"
    fi
    echo ""
    echo "INFO: Executing OpenAPI Generator command:"
    printf "    %q " "${cmd_array[@]}"; echo ""
    echo "------------------------------------------------------"
    if ! "${cmd_array[@]}"; then
        echo "------------------------------------------------------"
        echo "ERROR: OpenAPI Generator command failed."; exit 1
    fi
    
    # Run post-processing to fix setup.py
    local fix_setup_script="${OUTPUT_DIR}/fix_setup.py"
    if [ -f "$fix_setup_script" ]; then
        echo "INFO: Running post-processing to fix setup.py..."
        chmod +x "$fix_setup_script"
        if (cd "$OUTPUT_DIR" && ./fix_setup.py); then
            echo "INFO: Post-processing completed successfully."
        else
            echo "WARNING: Post-processing failed, but continuing..."
        fi
    fi
    
    echo "------------------------------------------------------"
    echo "INFO: Python client generation process completed."
    echo "      Source files are in: '${OUTPUT_DIR}/${PYTHON_PACKAGE_NAME}'"
    echo "INFO: The generated client uses 'urllib3' by default (check requirements.txt for all dependencies)."
    echo "INFO: Generated output is configured for a full project structure, including supporting files, docs, and tests."
    echo "      PLEASE VERIFY THE OUTPUT DIRECTORY CONTENTS."
    echo "------------------------------------------------------"
}

CLIENT_TYPE=""
OPENAPI_SPEC=""
OUTPUT_DIR=""
PYTHON_PACKAGE_NAME="goodmem_client"
PYTHON_PACKAGE_VERSION="1.0.0"
PYTHON_PROJECT_NAME="goodmem_client"

if [ "$#" -eq 0 ]; then usage; exit 1; fi

while [[ "$#" -gt 0 ]]; do
    case $1 in
        --python-client) CLIENT_TYPE="python"; shift ;;
        --spec) if [[ -n "${2-}" ]]; then OPENAPI_SPEC="$2"; shift 2; else echo "ERROR: --spec requires an argument."; usage; exit 1; fi ;;
        --output) if [[ -n "${2-}" ]]; then OUTPUT_DIR="$2"; shift 2; else echo "ERROR: --output requires an argument."; usage; exit 1; fi ;;
        --package-name) if [[ -n "${2-}" ]]; then PYTHON_PACKAGE_NAME="$2"; shift 2; else echo "ERROR: --package-name requires an argument."; usage; exit 1; fi ;;
        --package-version) if [[ -n "${2-}" ]]; then PYTHON_PACKAGE_VERSION="$2"; shift 2; else echo "ERROR: --package-version requires an argument."; usage; exit 1; fi ;;
        --project-name) if [[ -n "${2-}" ]]; then PYTHON_PROJECT_NAME="$2"; shift 2; else echo "ERROR: --project-name requires an argument."; usage; exit 1; fi ;;
        --help) usage; exit 0 ;;
        *) echo "ERROR: Unknown or misplaced parameter: $1"; usage; exit 1 ;;
    esac
done

if [ -z "$CLIENT_TYPE" ]; then echo "ERROR: Client type must be specified."; usage; exit 1; fi
if [ -z "$OPENAPI_SPEC" ]; then echo "ERROR: OpenAPI specification (--spec) must be provided."; usage; exit 1; fi

if [ -z "$OUTPUT_DIR" ]; then
    if [ "$CLIENT_TYPE" == "python" ]; then
        SCRIPT_DIR_FOR_DEFAULT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
        OUTPUT_DIR="${SCRIPT_DIR_FOR_DEFAULT}/python"
        echo "INFO: No --output specified. Defaulting Python client output (generator's root) to: ${OUTPUT_DIR}"
    else
        OUTPUT_DIR="./generated_client"
        echo "INFO: No --output specified. Defaulting client output (generator's root) to: ${OUTPUT_DIR}"
    fi
fi

check_java_version
ensure_jar_downloaded

if [ "$CLIENT_TYPE" == "python" ]; then
    generate_python_client
else
    echo "ERROR: Client type '$CLIENT_TYPE' is not supported."; usage; exit 1
fi

echo "INFO: Script finished successfully."
exit 0
