#!/bin/bash

# ==============================================================================
# WellDrySense API Test Suite (Bash Version)
# Functionality: Exercises Job APIs including Create, List, Edit, Details, Weather,
#                Sensor Data, and performs Database Cleanup.
# ==============================================================================

# --- Configuration ---
# Load .env file if it exists
if [ -f .env ]; then
    export $(cat .env | xargs)
fi

# Defaults (can be overridden by env vars)
PORT="${PORT:-8002}"
BASE_URL="http://localhost:$PORT/api/well_api"
API_USER="${API_USER:-jpeters}"
API_PASSWORD="${API_PASSWORD:-WellJson}"
DB_NAME="${DB_NAME:-wellnuo}"
DB_USER="${DB_USER:-postgres}"
DB_HOST="${DB_HOST:-localhost}"
DB_PORT="${DB_PORT:-5432}"
# DB_PASSWORD should be set in .env or exported

# Colors
GREEN='\033[0;32m'
RED='\033[0;31m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Global Variables
TOKEN=""
USER_ID=""
JOB_ID=""

# Check for jq
if ! command -v jq &> /dev/null; then
    echo -e "${RED}Error: 'jq' is not installed. Please install it to run this script.${NC}"
    exit 1
fi

echo -e "${BLUE}=== Setting up WellDrySense Test Suite on Port $PORT ===${NC}"

# ==============================================================================
# Helper Functions
# ==============================================================================

# Function to print section headers
print_header() {
    echo -e "\n${BLUE}----------------------------------------------------------------${NC}"
    echo -e "${BLUE}[Test] $1${NC}"
}

# Function to perform a POST request
# Usage: perform_test "Test Name" "JSON_PAYLOAD_STRING"
perform_test() {
    local test_name="$1"
    local json_payload="$2"
    
    print_header "$test_name"

    # 1. Print Request
    echo "# Request:"
    echo "$json_payload" | jq '.'

    # 2. Convert JSON to Form Data for curl (flattening simple objects)
    # Note: This simple conversion handles top-level keys. 
    # Complex nested JSON strings (like 'devices') need to be passed as strings in the input JSON.
    local form_data=""
    
    # Extract keys and values and build form string
    while IFS="=" read -r key value; do
        if [ -n "$key" ]; then
            # URL encode the value
            encoded_value=$(printf '%s' "$value" | jq -sRr @uri)
            if [ -z "$form_data" ]; then
                form_data="${key}=${encoded_value}"
            else
                form_data="${form_data}&${key}=${encoded_value}"
            fi
        fi
    done < <(echo "$json_payload" | jq -r "to_entries|map(\"\(.key)=\(.value)\")|.[]")

    # 3. Execute Request
    response=$(curl -s -X POST "$BASE_URL" \
        -H "Content-Type: application/x-www-form-urlencoded" \
        -d "$form_data")

    # 4. Print Response
    echo -e "\n# Response:"
    if [ -z "$response" ]; then
        echo "(Empty Response)"
        echo -e "${RED}FAIL${NC}"
        return 1
    else
        echo "$response" | jq '.' 2>/dev/null || echo "$response"
    fi

    # 5. Evaluate Pass/Fail based on "ok": 1
    ok_val=$(echo "$response" | jq -r '.ok // .status // 0')
    
    # Handle different response structures (some return {status: 200}, some {ok: 1})
    if [ "$ok_val" == "1" ] || [ "$ok_val" == "200" ] || [ "$ok_val" == "success" ]; then
        echo -e "${GREEN}PASS${NC}"
        
        # Extract Job ID if this was the create step
        if [ "$test_name" == "job_create" ]; then
            JOB_ID=$(echo "$response" | jq -r '.job_id')
            echo "-> Captured Job ID: $JOB_ID"
        fi
        return 0
    else
        error_msg=$(echo "$response" | jq -r '.error // .message // "Unknown error"')
        echo -e "${RED}FAIL: $error_msg${NC}"
        return 1
    fi
}

# ==============================================================================
# Test Execution
# ==============================================================================

# 1. Login / Credentials
# ----------------------
login_payload=$(jq -n \
                  --arg fn "credentials" \
                  --arg un "$API_USER" \
                  --arg ps "$API_PASSWORD" \
                  --arg cid "bash-suite" \
                  --arg nonce "test-nonce" \
                  '{function: $fn, user_name: $un, ps: $ps, clientId: $cid, nonce: $nonce}')

print_header "Login"
echo "# Request:"
echo "$login_payload" | jq '.'

# Special handling for login to capture token
response=$(curl -s -X POST "$BASE_URL" -d "function=credentials&user_name=$API_USER&ps=$API_PASSWORD&clientId=bash-suite&nonce=test-nonce")

echo -e "\n# Response:"
echo "$response" | jq '.'

TOKEN=$(echo "$response" | jq -r '.access_token // .data.access_token')
USER_ID=$(echo "$response" | jq -r '.user_id // .data.user_id')

if [ -n "$TOKEN" ] && [ "$TOKEN" != "null" ]; then
    echo -e "${GREEN}PASS${NC} (User ID: $USER_ID)"
else
    echo -e "${RED}FATAL: Login failed. Check credentials.${NC}"
    exit 1
fi

# 2. Create Job
# ----------------------
# Note: We pass JSON strings for complex fields like 'devices' and 'alerts_config'
devices_json='[{"mac": "TEST_MAC_VIRTUAL", "location": "Lab"}]'
alerts_json='{"temp_high": 30}'

create_payload=$(jq -n \
    --arg fn "job_create" \
    --arg un "$API_USER" \
    --arg tk "$TOKEN" \
    --arg cn "TEST_SUITE_CUSTOMER_BASH" \
    --arg as "123 Bash Script Ln" \
    --arg ac "Shellville" \
    --arg dev "$devices_json" \
    --arg lat "34.05" \
    --arg lng "-118.25" \
    '{function: $fn, user_name: $un, token: $tk, customer_name: $cn, address_street: $as, address_city: $ac, devices: $dev, lat: $lat, lng: $lng}')

perform_test "job_create" "$create_payload" || exit 1

# 3. Job List
# ----------------------
list_payload=$(jq -n \
    --arg fn "job_list" \
    --arg un "$API_USER" \
    --arg tk "$TOKEN" \
    '{function: $fn, user_name: $un, token: $tk}')

perform_test "job_list" "$list_payload"

# 3. Job List 2 (with added search)
# ----------------------
list_payload=$(jq -n \
    --arg fn "job_list2" \
    --arg un "$API_USER" \
    --arg tk "$TOKEN" \
    --arg sch "" \
    '{function: $fn, user_name: $un, token: $tk, search: $sch}')

perform_test "job_list2" "$list_payload"

# 4. Job Details
# ----------------------
details_payload=$(jq -n \
    --arg fn "job_details" \
    --arg un "$API_USER" \
    --arg tk "$TOKEN" \
    --arg jid "$JOB_ID" \
    '{function: $fn, user_name: $un, token: $tk, job_id: $jid}')

perform_test "job_details" "$details_payload"

# 5. Job Edit (Stop Job)
# ----------------------
edit_payload=$(jq -n \
    --arg fn "job_edit" \
    --arg un "$API_USER" \
    --arg tk "$TOKEN" \
    --arg jid "$JOB_ID" \
    --arg st "Stopped" \
    --arg dt "2025-12-31T23:59:59" \
    '{function: $fn, user_name: $un, token: $tk, job_id: $jid, job_status: $st, date_to: $dt}')

perform_test "job_edit" "$edit_payload"

# 6. Available Devices (two versions, with direct SQL and via GetProximityList)
# ----------------------
avail_payload=$(jq -n \
    --arg fn "job_available_devices" \
    --arg un "$API_USER" \
    --arg tk "$TOKEN" \
    '{function: $fn, user_name: $un, token: $tk}')

perform_test "job_available_devices" "$avail_payload"

# 6. Available Devices (Alternative Test using job_available_devices2, which is using GetProximityList)
avail_payload=$(jq -n \
    --arg fn "job_available_devices2" \
    --arg un "$API_USER" \
    --arg tk "$TOKEN" \
    '{function: $fn, user_name: $un, token: $tk}')

perform_test "job_available_devices2" "$avail_payload"

# 6. Available Devices(made reusing job_user_all_devices2, adding filter and search)
avail_payload=$(jq -n \
    --arg fn "job_devices" \
    --arg un "$API_USER" \
    --arg tk "$TOKEN" \
    --arg fl "all" \
    --arg sch "" \
    '{function: $fn, user_name: $un, token: $tk, filter: $fl, search: $sch}')

perform_test "job_devices" "$avail_payload"

# 7. Job Weather
# ----------------------
weather_payload=$(jq -n \
    --arg fn "job_weather" \
    --arg un "$API_USER" \
    --arg tk "$TOKEN" \
    --arg jid "$JOB_ID" \
    '{function: $fn, user_name: $un, token: $tk, job_id: $jid}')

perform_test "job_weather" "$weather_payload"

# 8. Job Sensor Bucketed Data (New Test)
# ----------------------
# Using dynamic dates for the test
DATE_FROM=$(date +%Y-%m-%d)
DATE_TO=$(date +%Y-%m-%d)

sensor_payload=$(jq -n \
    --arg fn "get_job_sensor_bucketed_data" \
    --arg un "$API_USER" \
    --arg tk "$TOKEN" \
    --arg jid "$JOB_ID" \
    --arg sens "temperature" \
    --arg dt "$DATE_FROM" \
    --arg dtt "$DATE_TO" \
    --arg bs "15m" \
    '{function: $fn, user_name: $un, token: $tk, job_id: $jid, sensor: $sens, date: $dt, to_date: $dtt, bucket_size: $bs}')

perform_test "get_job_sensor_bucketed_data" "$sensor_payload"

# ==============================================================================
# Cleanup
# ==============================================================================
print_header "Cleanup"

if [ -n "$JOB_ID" ]; then
    echo "-> Deleting Job ID: $JOB_ID from database..."
    
    # Use PGPASSWORD for non-interactive auth if set
    export PGPASSWORD="${DB_PASSWORD}"
    
    psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "DELETE FROM public.jobs WHERE job_id = $JOB_ID;" > /dev/null 2>&1
    
    if [ $? -eq 0 ]; then
        echo -e "${GREEN}Cleanup successful. Database restored.${NC}"
    else
        echo -e "${RED}Cleanup failed. Please manually delete job_id $JOB_ID from public.jobs.${NC}"
        echo "Command attempted: psql -h $DB_HOST -U $DB_USER -d $DB_NAME -c \"DELETE FROM public.jobs WHERE job_id = $JOB_ID;\""
    fi
else
    echo "No Job ID created, skipping cleanup."
fi

echo -e "\n${BLUE}=== Test Suite Finished ===${NC}"
# ==============================================================================
# well-api.py modifications to support WellDrySense API on port 1998
# ==============================================================================