-- ============================================================
-- 医梦 AI 中台 统一入口客户端 MVP 数据库迁移
-- 版本: 2026-05-31
-- 原则: 不 DROP 现有表，仅 ALTER 补字段 + CREATE 新表
-- ============================================================

-- -----------------------------------------------------------
-- 1. 新表：设备注册中心
-- -----------------------------------------------------------
CREATE TABLE IF NOT EXISTS ai_device_registry (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  device_id VARCHAR(64) NOT NULL,
  project_id VARCHAR(64) NOT NULL,
  hospital_id VARCHAR(64) NOT NULL,
  device_type VARCHAR(64) NOT NULL,
  management_mode VARCHAR(32) NOT NULL DEFAULT 'emoon_managed',
  vendor VARCHAR(64),
  model VARCHAR(128),
  location_json JSON,
  capabilities_json JSON,
  status VARCHAR(32) NOT NULL DEFAULT 'pending',
  admission_level VARCHAR(8) NOT NULL DEFAULT 'B',
  client_version VARCHAR(64),
  last_heartbeat DATETIME,
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  UNIQUE KEY uk_device_id (device_id),
  KEY idx_project_hospital (project_id, hospital_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- -----------------------------------------------------------
-- 2. 新表：设备场景绑定
-- -----------------------------------------------------------
CREATE TABLE IF NOT EXISTS ai_device_scene_binding (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  device_id VARCHAR(64) NOT NULL,
  scene_code VARCHAR(64) NOT NULL,
  ui_template VARCHAR(64) NOT NULL,
  agent_bindings_json JSON NOT NULL,
  tool_scopes_json JSON,
  card_scopes_json JSON,
  status VARCHAR(32) NOT NULL DEFAULT 'enabled',
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  UNIQUE KEY uk_device_scene (device_id, scene_code)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- -----------------------------------------------------------
-- 3. 新表：设备事件日志
-- -----------------------------------------------------------
CREATE TABLE IF NOT EXISTS ai_device_event (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  event_id VARCHAR(96) NOT NULL,
  device_id VARCHAR(64) NOT NULL,
  event_type VARCHAR(64) NOT NULL,
  event_payload JSON,
  trace_id VARCHAR(96),
  occurred_at DATETIME NOT NULL,
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  UNIQUE KEY uk_device_event (device_id, event_id),
  KEY idx_device_time (device_id, occurred_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- -----------------------------------------------------------
-- 4. 新表：设备命令
-- -----------------------------------------------------------
CREATE TABLE IF NOT EXISTS ai_device_command (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  command_id VARCHAR(96) NOT NULL,
  device_id VARCHAR(64) NOT NULL,
  command_type VARCHAR(64) NOT NULL,
  payload_json JSON NOT NULL,
  status VARCHAR(32) NOT NULL DEFAULT 'PENDING',
  expire_at DATETIME NOT NULL,
  ack_at DATETIME,
  ack_result_json JSON,
  trace_id VARCHAR(96),
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  UNIQUE KEY uk_command_id (command_id),
  KEY idx_device_status (device_id, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- -----------------------------------------------------------
-- 5. 新表：会话消息
-- -----------------------------------------------------------
CREATE TABLE IF NOT EXISTS ai_conversation_message (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  message_id VARCHAR(96) NOT NULL,
  conversation_id VARCHAR(96) NOT NULL,
  role VARCHAR(32) NOT NULL,
  content TEXT,
  event_json JSON,
  trace_id VARCHAR(96),
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  UNIQUE KEY uk_message_id (message_id),
  KEY idx_conv_time (conversation_id, created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- -----------------------------------------------------------
-- 6. 新表：任务实例
-- -----------------------------------------------------------
CREATE TABLE IF NOT EXISTS ai_task_instance (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  task_id VARCHAR(96) NOT NULL,
  project_id VARCHAR(64) NOT NULL,
  conversation_id VARCHAR(96) NOT NULL,
  task_type VARCHAR(64) NOT NULL,
  status VARCHAR(32) NOT NULL,
  current_step VARCHAR(64) NOT NULL,
  agent_code VARCHAR(64),
  context_json JSON,
  patient_id VARCHAR(96),
  device_id VARCHAR(64),
  trace_id VARCHAR(96),
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  UNIQUE KEY uk_task_id (task_id),
  KEY idx_project (project_id),
  KEY idx_conv_status (conversation_id, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- -----------------------------------------------------------
-- 7. 新表：文件对象
-- -----------------------------------------------------------
CREATE TABLE IF NOT EXISTS ai_file_object (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  file_id VARCHAR(96) NOT NULL,
  project_id VARCHAR(64) NOT NULL,
  hospital_id VARCHAR(64),
  device_id VARCHAR(64),
  business_type VARCHAR(64) NOT NULL,
  sha256 VARCHAR(128),
  storage_path VARCHAR(512) NOT NULL,
  retention_policy VARCHAR(32) NOT NULL,
  sensitive_level VARCHAR(32) NOT NULL,
  status VARCHAR(32) NOT NULL DEFAULT 'available',
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  UNIQUE KEY uk_file_id (file_id),
  KEY idx_project_type (project_id, business_type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- -----------------------------------------------------------
-- 7.5 新表：卡片动作日志（幂等审计）
-- -----------------------------------------------------------
CREATE TABLE IF NOT EXISTS ai_card_action_log (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  action_id VARCHAR(96) NOT NULL,
  card_instance_id VARCHAR(96) NOT NULL,
  action_name VARCHAR(64) NOT NULL,
  idempotency_key VARCHAR(128) NOT NULL,
  action_payload_json JSON,
  status VARCHAR(32) NOT NULL DEFAULT 'submitted',
  trace_id VARCHAR(96),
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  UNIQUE KEY uk_idempotency (idempotency_key),
  KEY idx_card_action (card_instance_id, action_name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- -----------------------------------------------------------
-- 8. 存量表 ai_conversation 补字段
--    现有实体: com.emoon.mcp.domain.AiConversation
--    已有字段: id, projectId, agentId, conversationId, status 等
-- -----------------------------------------------------------
DROP PROCEDURE IF EXISTS emoon_add_column_if_absent;
DELIMITER //
CREATE PROCEDURE emoon_add_column_if_absent(
  IN p_table_name VARCHAR(128),
  IN p_column_name VARCHAR(128),
  IN p_ddl TEXT
)
BEGIN
  IF NOT EXISTS (
    SELECT 1 FROM information_schema.columns
    WHERE table_schema = DATABASE()
      AND table_name = p_table_name
      AND column_name = p_column_name
  ) THEN
    SET @sql = p_ddl;
    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
  END IF;
END//
DELIMITER ;

DROP PROCEDURE IF EXISTS emoon_add_index_if_absent;
DELIMITER //
CREATE PROCEDURE emoon_add_index_if_absent(
  IN p_table_name VARCHAR(128),
  IN p_index_name VARCHAR(128),
  IN p_ddl TEXT
)
BEGIN
  IF NOT EXISTS (
    SELECT 1 FROM information_schema.statistics
    WHERE table_schema = DATABASE()
      AND table_name = p_table_name
      AND index_name = p_index_name
  ) THEN
    SET @sql = p_ddl;
    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
  END IF;
END//
DELIMITER ;

CALL emoon_add_column_if_absent('ai_conversation', 'hospital_id',
  'ALTER TABLE ai_conversation ADD COLUMN hospital_id VARCHAR(64) NULL COMMENT ''医院标识''');
CALL emoon_add_column_if_absent('ai_conversation', 'device_id',
  'ALTER TABLE ai_conversation ADD COLUMN device_id VARCHAR(64) NULL COMMENT ''统一入口终端设备ID''');
CALL emoon_add_column_if_absent('ai_conversation', 'client_message_id',
  'ALTER TABLE ai_conversation ADD COLUMN client_message_id VARCHAR(96) NULL COMMENT ''客户端消息幂等ID''');
CALL emoon_add_index_if_absent('ai_conversation', 'idx_ai_conversation_device',
  'CREATE INDEX idx_ai_conversation_device ON ai_conversation(device_id)');

-- -----------------------------------------------------------
-- 9. 存量表 ai_card_instance 补字段
--    现有实体: com.emoon.mcp.domain.AiCardInstance
--    已有字段: id, conversationId, cardKey, instanceId, status 等
-- -----------------------------------------------------------
CALL emoon_add_column_if_absent('ai_card_instance', 'task_id',
  'ALTER TABLE ai_card_instance ADD COLUMN task_id VARCHAR(96) NULL COMMENT ''统一入口终端任务ID''');
CALL emoon_add_column_if_absent('ai_card_instance', 'trace_id',
  'ALTER TABLE ai_card_instance ADD COLUMN trace_id VARCHAR(96) NULL COMMENT ''链路追踪ID''');
CALL emoon_add_index_if_absent('ai_card_instance', 'idx_ai_card_instance_task',
  'CREATE INDEX idx_ai_card_instance_task ON ai_card_instance(task_id)');

-- -----------------------------------------------------------
-- 10. 存量表 ai_card_definition 补索引
--     现有实体: com.emoon.system.domain.AiCardDefinition
--     已有字段: cardKey, version, name, schemaJson, actionsJson, status, isSystem, isLatest
-- -----------------------------------------------------------
CALL emoon_add_index_if_absent('ai_card_definition', 'idx_ai_card_def_key',
  'CREATE INDEX idx_ai_card_def_key ON ai_card_definition(card_key)');

DROP PROCEDURE IF EXISTS emoon_add_column_if_absent;
DROP PROCEDURE IF EXISTS emoon_add_index_if_absent;

-- -----------------------------------------------------------
-- 11. Seed 数据：核心卡片定义
-- -----------------------------------------------------------
INSERT INTO ai_card_definition(card_key, version, name, schema_json, actions_json, status, is_system, is_latest)
VALUES
('department-selection', '1.0', '科室选择', JSON_OBJECT('required', JSON_ARRAY('departments')), JSON_ARRAY(JSON_OBJECT('actionName', 'select_department')), '0', '1', TRUE),
('doctor-selection', '1.0', '医生选择', JSON_OBJECT('required', JSON_ARRAY('doctors')), JSON_ARRAY(JSON_OBJECT('actionName', 'select_doctor')), '0', '1', TRUE),
('time-slot-selection', '1.0', '号源选择', JSON_OBJECT('required', JSON_ARRAY('slots')), JSON_ARRAY(JSON_OBJECT('actionName', 'select_time_slot')), '0', '1', TRUE),
('confirm-appointment', '1.0', '挂号确认', JSON_OBJECT('required', JSON_ARRAY('summary')), JSON_ARRAY(JSON_OBJECT('actionName', 'confirm_appointment', 'requiredConfirm', TRUE)), '0', '1', TRUE),
('appointment-success', '1.0', '挂号成功', JSON_OBJECT('required', JSON_ARRAY('appointmentNo')), JSON_ARRAY(), '0', '1', TRUE),
('route-card', '1.0', '路线导航', JSON_OBJECT('required', JSON_ARRAY('routeText')), JSON_ARRAY(JSON_OBJECT('actionName', 'start_navigation')), '0', '1', TRUE),
('tongue-capture', '1.0', '舌象采集', JSON_OBJECT('required', JSON_ARRAY('uploadField')), JSON_ARRAY(JSON_OBJECT('actionName', 'submit_tongue_image')), '0', '1', TRUE)
ON DUPLICATE KEY UPDATE
  name = VALUES(name),
  schema_json = VALUES(schema_json),
  actions_json = VALUES(actions_json),
  status = VALUES(status),
  is_system = VALUES(is_system),
  is_latest = VALUES(is_latest);

-- -----------------------------------------------------------
-- 12. Seed 数据：自助机设备和场景
-- -----------------------------------------------------------
INSERT IGNORE INTO ai_device_registry(device_id, project_id, hospital_id, device_type, status, admission_level, capabilities_json)
VALUES ('EMOON-KIOSK-001', 'hospital_demo', 'H001', 'self_service_kiosk', 'activated', 'A',
        JSON_ARRAY('touch','camera','id_card_ocr','file_upload'));

INSERT IGNORE INTO ai_device_scene_binding(device_id, scene_code, ui_template, agent_bindings_json, card_scopes_json)
VALUES ('EMOON-KIOSK-001', 'outpatient_kiosk', 'kiosk_home_v1',
        JSON_OBJECT('defaultAgent','opd-guide-agent','allowedAgents',JSON_ARRAY('opd-guide-agent','opd-triage-agent','opd-registration-agent','tongue-diagnosis-agent')),
        JSON_ARRAY('department-selection','doctor-selection','time-slot-selection','confirm-appointment','appointment-success','tongue-capture'));
