#!/bin/bash
BASE_URL="http://localhost:8080/api"
TOKEN=""
PROJECT_ID=""
PASS_COUNT=0
FAIL_COUNT=0
TOTAL_COUNT=0

assert_eq() {
  local actual="$1"
  local expected="$2"
  local name="$3"
  TOTAL_COUNT=$((TOTAL_COUNT + 1))
  if [ "$actual" = "$expected" ]; then
    echo "  PASS: $name"
    PASS_COUNT=$((PASS_COUNT + 1))
  else
    echo "  FAIL: $name (expected=$expected, actual=$actual)"
    FAIL_COUNT=$((FAIL_COUNT + 1))
  fi
}

assert_contains() {
  local haystack="$1"
  local needle="$2"
  local name="$3"
  TOTAL_COUNT=$((TOTAL_COUNT + 1))
  if echo "$haystack" | grep -q "$needle"; then
    echo "  PASS: $name"
    PASS_COUNT=$((PASS_COUNT + 1))
  else
    echo "  FAIL: $name (expected to contain: $needle)"
    FAIL_COUNT=$((FAIL_COUNT + 1))
  fi
}

login() {
  echo "=== 登录获取Token ==="
  local response=$(curl -s -X POST "$BASE_URL/auth/login" \
    -H "Content-Type: application/json" \
    -d '{"username":"admin","password":"admin123"}')
  TOKEN=$(echo "$response" | grep -o '"token":"[^"]*"' | cut -d'"' -f4)
  if [ -z "$TOKEN" ]; then
    echo "FATAL: 登录失败，无法获取Token"
    exit 1
  fi
  echo "Token获取成功"
}

setup_project() {
  echo "=== 创建测试项目 ==="
  local response=$(curl -s -X POST "$BASE_URL/mdm/projects" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Project-ID: " \
    -d "{\"code\":\"TEST-OPS-$$\",\"name\":\"OPS测试项目\",\"projectType\":\"RESIDENTIAL\"}")
  PROJECT_ID=$(echo "$response" | grep -o '"id":"[^"]*"' | head -1 | cut -d'"' -f4)
  if [ -z "$PROJECT_ID" ]; then
    echo "FATAL: 创建测试项目失败"
    exit 1
  fi
  echo "测试项目创建成功: $PROJECT_ID"
}

test_create_work_order() {
  echo "--- TC-OPS-001: 创建工单 ---"
  local response=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/wo/work-orders" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Project-ID: $PROJECT_ID" \
    -d "{\"title\":\"测试工单-$$\",\"source\":\"MANUAL\",\"type\":\"REPAIR\",\"priority\":\"MEDIUM\",\"description\":\"API测试工单\"}")
  local status=$(echo "$response" | tail -n 1)
  local body=$(echo "$response" | head -n -1)
  assert_eq "$status" "201" "TC-OPS-001: 创建工单返回201"
  assert_contains "$body" '"workNo"' "TC-OPS-001: 响应包含workNo"
  WORK_ORDER_ID=$(echo "$body" | grep -o '"id":"[^"]*"' | head -1 | cut -d'"' -f4)
}

test_query_work_orders() {
  echo "--- TC-OPS-002: 查询工单列表 ---"
  local response=$(curl -s -w "\n%{http_code}" -X GET "$BASE_URL/wo/work-orders?projectId=$PROJECT_ID" \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Project-ID: $PROJECT_ID")
  local status=$(echo "$response" | tail -n 1)
  assert_eq "$status" "200" "TC-OPS-002: 查询工单列表返回200"
}

test_assign_work_order() {
  echo "--- TC-OPS-003: 工单派单 ---"
  if [ -z "$WORK_ORDER_ID" ]; then
    echo "  SKIP: TC-OPS-003 (无工单ID)"
    return
  fi
  local response=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/wo/work-orders/$WORK_ORDER_ID/assign" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Project-ID: $PROJECT_ID" \
    -d '{"assignedTo":"test_maintainer","assignedDate":"2026-05-18"}')
  local status=$(echo "$response" | tail -n 1)
  assert_eq "$status" "200" "TC-OPS-003: 工单派单返回200"
}

test_start_work_order() {
  echo "--- TC-OPS-004: 工单开始执行 ---"
  if [ -z "$WORK_ORDER_ID" ]; then
    echo "  SKIP: TC-OPS-004 (无工单ID)"
    return
  fi
  local response=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/wo/work-orders/$WORK_ORDER_ID/start" \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Project-ID: $PROJECT_ID")
  local status=$(echo "$response" | tail -n 1)
  assert_eq "$status" "200" "TC-OPS-004: 工单开始执行返回200"
}

test_complete_work_order() {
  echo "--- TC-OPS-005: 工单完成 ---"
  if [ -z "$WORK_ORDER_ID" ]; then
    echo "  SKIP: TC-OPS-005 (无工单ID)"
    return
  fi
  local response=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/wo/work-orders/$WORK_ORDER_ID/complete" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Project-ID: $PROJECT_ID" \
    -d '{"faultCause":"测试故障原因","solution":"测试解决方案","result":"已修复","laborCost":100,"partsCost":50}')
  local status=$(echo "$response" | tail -n 1)
  assert_eq "$status" "200" "TC-OPS-005: 工单完成返回200"
}

test_verify_work_order() {
  echo "--- TC-OPS-006: 工单验收 ---"
  if [ -z "$WORK_ORDER_ID" ]; then
    echo "  SKIP: TC-OPS-006 (无工单ID)"
    return
  fi
  local response=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/wo/work-orders/$WORK_ORDER_ID/verify" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Project-ID: $PROJECT_ID" \
    -d '{"verifiedBy":"admin","rating":5,"remark":"验收通过"}')
  local status=$(echo "$response" | tail -n 1)
  assert_eq "$status" "200" "TC-OPS-006: 工单验收返回200"
}

test_cancel_completed_work_order() {
  echo "--- TC-OPS-007: 工单取消-已完成拒绝 ---"
  if [ -z "$WORK_ORDER_ID" ]; then
    echo "  SKIP: TC-OPS-007 (无工单ID)"
    return
  fi
  local response=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/wo/work-orders/$WORK_ORDER_ID/cancel" \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Project-ID: $PROJECT_ID")
  local status=$(echo "$response" | tail -n 1)
  assert_eq "$status" "400" "TC-OPS-007: 已完成工单取消返回400"
}

test_work_order_statistics() {
  echo "--- TC-OPS-008: 工单统计 ---"
  local response=$(curl -s -w "\n%{http_code}" -X GET "$BASE_URL/wo/work-orders/statistics?projectId=$PROJECT_ID" \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Project-ID: $PROJECT_ID")
  local status=$(echo "$response" | tail -n 1)
  assert_eq "$status" "200" "TC-OPS-008: 工单统计返回200"
}

test_create_maintenance_task() {
  echo "--- TC-OPS-009: 创建维保任务 ---"
  local response=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/wo/maintenance-tasks" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Project-ID: $PROJECT_ID" \
    -d "{\"equipmentId\":\"00000000-0000-0000-0000-000000000000\",\"taskType\":\"PREVENTIVE\",\"triggerType\":\"MANUAL\",\"title\":\"测试维保任务-$$\"}")
  local status=$(echo "$response" | tail -n 1)
  local body=$(echo "$response" | head -n -1)
  if [ "$status" = "201" ] || [ "$status" = "200" ]; then
    assert_eq "$status" "$status" "TC-OPS-009: 创建维保任务成功"
    MAINT_TASK_ID=$(echo "$body" | grep -o '"id":"[^"]*"' | head -1 | cut -d'"' -f4)
  else
    assert_contains "$body" "equipment" "TC-OPS-009: 创建维保任务(设备不存在时返回错误)"
  fi
}

test_spare_part_crud() {
  echo "--- TC-OPS-010: 备件CRUD ---"
  local create_response=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/ops/spare-parts" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Project-ID: $PROJECT_ID" \
    -d "{\"partCode\":\"TEST-SP-$$_$RANDOM\",\"partName\":\"测试备件\",\"unit\":\"个\",\"safeStock\":10,\"currentStock\":100,\"unitPrice\":25.00}")
  local create_status=$(echo "$create_response" | tail -n 1)
  local create_body=$(echo "$create_response" | head -n -1)
  assert_eq "$create_status" "201" "TC-OPS-010: 创建备件返回201"
  SPARE_PART_ID=$(echo "$create_body" | grep -o '"id":"[^"]*"' | head -1 | cut -d'"' -f4)
}

test_spare_part_in_stock() {
  echo "--- TC-OPS-011: 备件入库 ---"
  if [ -z "$SPARE_PART_ID" ]; then
    echo "  SKIP: TC-OPS-011 (无备件ID)"
    return
  fi
  local response=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/ops/spare-parts/in-stock" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Project-ID: $PROJECT_ID" \
    -d "{\"sparePartId\":\"$SPARE_PART_ID\",\"quantity\":50,\"operator\":\"admin\",\"remark\":\"API测试入库\"}")
  local status=$(echo "$response" | tail -n 1)
  assert_eq "$status" "200" "TC-OPS-011: 备件入库返回200"
}

test_spare_part_out_stock() {
  echo "--- TC-OPS-012: 备件出库 ---"
  if [ -z "$SPARE_PART_ID" ]; then
    echo "  SKIP: TC-OPS-012 (无备件ID)"
    return
  fi
  local response=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/ops/spare-parts/out-stock" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Project-ID: $PROJECT_ID" \
    -d "{\"sparePartId\":\"$SPARE_PART_ID\",\"quantity\":10,\"operator\":\"admin\",\"remark\":\"API测试出库\"}")
  local status=$(echo "$response" | tail -n 1)
  assert_eq "$status" "200" "TC-OPS-012: 备件出库返回200"
}

test_spare_part_out_stock_insufficient() {
  echo "--- TC-OPS-013: 备件出库-库存不足 ---"
  if [ -z "$SPARE_PART_ID" ]; then
    echo "  SKIP: TC-OPS-013 (无备件ID)"
    return
  fi
  local response=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/ops/spare-parts/out-stock" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Project-ID: $PROJECT_ID" \
    -d "{\"sparePartId\":\"$SPARE_PART_ID\",\"quantity\":99999,\"operator\":\"admin\",\"remark\":\"库存不足测试\"}")
  local status=$(echo "$response" | tail -n 1)
  assert_eq "$status" "400" "TC-OPS-013: 库存不足出库返回400"
}

test_low_stock_warning() {
  echo "--- TC-OPS-014: 低库存预警 ---"
  local response=$(curl -s -w "\n%{http_code}" -X GET "$BASE_URL/ops/spare-parts/low-stock?projectId=$PROJECT_ID" \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Project-ID: $PROJECT_ID")
  local status=$(echo "$response" | tail -n 1)
  assert_eq "$status" "200" "TC-OPS-014: 低库存预警返回200"
}

test_energy_consumption() {
  echo "--- TC-OPS-015: 能耗抄表录入 ---"
  local meter_response=$(curl -s -X POST "$BASE_URL/ops/energy/meters" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Project-ID: $PROJECT_ID" \
    -d "{\"meterName\":\"测试计量点-$$\",\"energyType\":\"LIGHTING\",\"unitPrice\":0.85}")
  local meter_id=$(echo "$meter_response" | grep -o '"id":"[^"]*"' | head -1 | cut -d'"' -f4)
  if [ -z "$meter_id" ]; then
    echo "  SKIP: TC-OPS-015 (无法创建计量点)"
    return
  fi
  local response=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/ops/energy/consumption" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Project-ID: $PROJECT_ID" \
    -d "{\"meterId\":\"$meter_id\",\"currentReading\":100,\"recordedBy\":\"admin\"}")
  local status=$(echo "$response" | tail -n 1)
  assert_eq "$status" "201" "TC-OPS-015: 能耗抄表录入返回201"
  ENERGY_METER_ID="$meter_id"
}

test_energy_decreasing_reading() {
  echo "--- TC-OPS-016: 能耗抄表-读数递减 ---"
  if [ -z "$ENERGY_METER_ID" ]; then
    echo "  SKIP: TC-OPS-016 (无计量点ID)"
    return
  fi
  local response=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/ops/energy/consumption" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Project-ID: $PROJECT_ID" \
    -d "{\"meterId\":\"$ENERGY_METER_ID\",\"currentReading\":50,\"recordedBy\":\"admin\"}")
  local status=$(echo "$response" | tail -n 1)
  assert_eq "$status" "400" "TC-OPS-016: 读数递减返回400"
}

test_maintenance_plan() {
  echo "--- TC-OPS-017: 维保计划管理 ---"
  local response=$(curl -s -w "\n%{http_code}" -X GET "$BASE_URL/wo/maintenance-plans?projectId=$PROJECT_ID" \
    -H "Authorization: Bearer $TOKEN" \
    -H "X-Project-ID: $PROJECT_ID")
  local status=$(echo "$response" | tail -n 1)
  assert_eq "$status" "200" "TC-OPS-017: 查询维保计划返回200"
}

cleanup() {
  echo "=== 清理测试数据 ==="
  if [ -n "$PROJECT_ID" ]; then
    curl -s -X DELETE "$BASE_URL/mdm/projects/$PROJECT_ID" \
      -H "Authorization: Bearer $TOKEN" > /dev/null 2>&1
  fi
}

print_summary() {
  echo ""
  echo "=========================================="
  echo "  Ops Domain API Test Summary"
  echo "=========================================="
  echo "  Total:  $TOTAL_COUNT"
  echo "  Passed: $PASS_COUNT"
  echo "  Failed: $FAIL_COUNT"
  if [ "$TOTAL_COUNT" -gt 0 ]; then
    local rate=$(echo "scale=1; $PASS_COUNT * 100 / $TOTAL_COUNT" | bc)
    echo "  Rate:   ${rate}%"
  fi
  echo "=========================================="
  if [ "$FAIL_COUNT" -gt 0 ]; then
    return 1
  fi
  return 0
}

WORK_ORDER_ID=""
MAINT_TASK_ID=""
SPARE_PART_ID=""
ENERGY_METER_ID=""

echo "=========================================="
echo "  Ether PMS - Ops Domain API Tests"
echo "=========================================="
echo ""

login
setup_project

test_create_work_order
test_query_work_orders
test_assign_work_order
test_start_work_order
test_complete_work_order
test_verify_work_order
test_cancel_completed_work_order
test_work_order_statistics
test_create_maintenance_task
test_spare_part_crud
test_spare_part_in_stock
test_spare_part_out_stock
test_spare_part_out_stock_insufficient
test_low_stock_warning
test_energy_consumption
test_energy_decreasing_reading
test_maintenance_plan

cleanup
print_summary
