-- ============================================
-- 数据模型统一重构脚本
-- 目标：统一vehicle_id为数字ID，license_plate为车牌号
-- 创建时间：2025-01-15
-- 执行模式：方案B - 完全统一数据模型
-- ============================================

-- 开始事务
BEGIN;

-- 设置错误处理
\set ON_ERROR_STOP on

-- ============================================
-- 第一阶段：数据结构准备
-- ============================================

-- 创建车辆ID映射表（临时）
CREATE TABLE IF NOT EXISTS vehicle_id_mapping (
    license_plate VARCHAR(50) PRIMARY KEY,
    old_vehicle_id VARCHAR(50),
    new_vehicle_id BIGINT
);

-- 填充映射表数据
INSERT INTO vehicle_id_mapping (license_plate, old_vehicle_id, new_vehicle_id)
SELECT 
    license_plate_number as license_plate,
    NULL as old_vehicle_id,
    vehicle_id as new_vehicle_id
FROM sys_vehicle_info
ON CONFLICT (license_plate) DO NOTHING;

-- 从CollisionAvoidanceSystem表中获取现有车牌号
INSERT INTO vehicle_id_mapping (license_plate, old_vehicle_id, new_vehicle_id)
SELECT DISTINCT 
    vehicle_id as license_plate,
    vehicle_id as old_vehicle_id,
    NULL::BIGINT as new_vehicle_id
FROM vehicle_locations
WHERE vehicle_id NOT IN (SELECT license_plate FROM vehicle_id_mapping)
ON CONFLICT (license_plate) DO NOTHING;

-- 为新车牌号分配数字ID
DO $$
DECLARE
    max_id BIGINT;
    rec RECORD;
BEGIN
    -- 获取当前最大车辆ID
    SELECT COALESCE(MAX(vehicle_id), 0) INTO max_id FROM sys_vehicle_info;
    
    -- 为没有数字ID的车牌号分配新ID
    FOR rec IN 
        SELECT license_plate FROM vehicle_id_mapping 
        WHERE new_vehicle_id IS NULL 
        ORDER BY license_plate
    LOOP
        max_id := max_id + 1;
        UPDATE vehicle_id_mapping 
        SET new_vehicle_id = max_id 
        WHERE license_plate = rec.license_plate;
    END LOOP;
END $$;

-- ============================================
-- 第二阶段：QAUP-Management表结构变更
-- ============================================

-- 1. 重命名sys_vehicle_info表中的字段
ALTER TABLE sys_vehicle_info RENAME COLUMN license_plate_number TO license_plate;

-- 2. 为新车牌号添加车辆记录
INSERT INTO sys_vehicle_info (
    vehicle_id, license_plate, vin_number, type_id, brand, 
    owning_unit, contact_person, phone_number, image_url, 
    create_by, create_time, update_by, update_time, remark
)
SELECT 
    vim.new_vehicle_id,
    vim.license_plate,
    'AUTO_' || vim.license_plate as vin_number,
    1 as type_id, -- 默认类型，需要根据实际情况调整
    '未知' as brand,
    '自动导入' as owning_unit,
    '系统' as contact_person,
    '' as phone_number,
    '' as image_url,
    'system' as create_by,
    NOW() as create_time,
    'system' as update_by,
    NOW() as update_time,
    '数据模型统一时自动创建' as remark
FROM vehicle_id_mapping vim
WHERE vim.new_vehicle_id NOT IN (SELECT vehicle_id FROM sys_vehicle_info)
AND vim.old_vehicle_id IS NOT NULL;

-- ============================================
-- 第三阶段：CollisionAvoidanceSystem表结构变更
-- ============================================

-- 1. 处理vehicle_locations表
-- 添加新字段
ALTER TABLE vehicle_locations ADD COLUMN IF NOT EXISTS license_plate VARCHAR(50);
ALTER TABLE vehicle_locations ADD COLUMN IF NOT EXISTS vehicle_id_new BIGINT;

-- 填充新字段数据
UPDATE vehicle_locations vl
SET 
    license_plate = vl.vehicle_id,
    vehicle_id_new = vim.new_vehicle_id
FROM vehicle_id_mapping vim
WHERE vl.vehicle_id = vim.license_plate;

-- 2. 处理vehicle_trajectories表
-- 添加新字段
ALTER TABLE vehicle_trajectories ADD COLUMN IF NOT EXISTS license_plate VARCHAR(50);
ALTER TABLE vehicle_trajectories ADD COLUMN IF NOT EXISTS vehicle_id_new BIGINT;

-- 填充新字段数据
UPDATE vehicle_trajectories vt
SET 
    license_plate = vt.vehicle_id,
    vehicle_id_new = vim.new_vehicle_id
FROM vehicle_id_mapping vim
WHERE vt.vehicle_id = vim.license_plate;

-- 3. 处理vehicle_commands表
-- 添加新字段
ALTER TABLE vehicle_commands ADD COLUMN IF NOT EXISTS license_plate VARCHAR(50);
ALTER TABLE vehicle_commands ADD COLUMN IF NOT EXISTS vehicle_id_new BIGINT;

-- 填充新字段数据
UPDATE vehicle_commands vc
SET 
    license_plate = vc.vehicle_id,
    vehicle_id_new = vim.new_vehicle_id
FROM vehicle_id_mapping vim
WHERE vc.vehicle_id = vim.license_plate;

-- 4. 处理rule_violation_events表
-- 添加新字段
ALTER TABLE rule_violation_events ADD COLUMN IF NOT EXISTS license_plate VARCHAR(50);
ALTER TABLE rule_violation_events ADD COLUMN IF NOT EXISTS vehicle_id_new BIGINT;

-- 填充新字段数据（只处理车辆类型的事件）
UPDATE rule_violation_events rve
SET 
    license_plate = rve.subject_id,
    vehicle_id_new = vim.new_vehicle_id
FROM vehicle_id_mapping vim
WHERE rve.subject_id = vim.license_plate 
AND rve.subject_type = 'VEHICLE';

-- ============================================
-- 第四阶段：数据完整性验证
-- ============================================

-- 验证数据完整性
DO $$
DECLARE
    missing_data_count INTEGER;
    total_records INTEGER;
BEGIN
    -- 检查vehicle_locations表
    SELECT COUNT(*) INTO missing_data_count
    FROM vehicle_locations
    WHERE license_plate IS NULL OR vehicle_id_new IS NULL;
    
    SELECT COUNT(*) INTO total_records FROM vehicle_locations;
    
    IF missing_data_count > 0 THEN
        RAISE EXCEPTION 'vehicle_locations表数据迁移不完整: %/%', missing_data_count, total_records;
    END IF;
    
    -- 检查vehicle_trajectories表
    SELECT COUNT(*) INTO missing_data_count
    FROM vehicle_trajectories
    WHERE license_plate IS NULL OR vehicle_id_new IS NULL;
    
    SELECT COUNT(*) INTO total_records FROM vehicle_trajectories;
    
    IF missing_data_count > 0 THEN
        RAISE EXCEPTION 'vehicle_trajectories表数据迁移不完整: %/%', missing_data_count, total_records;
    END IF;
    
    -- 检查vehicle_commands表
    SELECT COUNT(*) INTO missing_data_count
    FROM vehicle_commands
    WHERE license_plate IS NULL OR vehicle_id_new IS NULL;
    
    SELECT COUNT(*) INTO total_records FROM vehicle_commands;
    
    IF missing_data_count > 0 THEN
        RAISE EXCEPTION 'vehicle_commands表数据迁移不完整: %/%', missing_data_count, total_records;
    END IF;
    
    RAISE NOTICE '数据完整性验证通过！';
END $$;

-- ============================================
-- 第五阶段：结构清理和字段重命名
-- ============================================

-- 1. 删除旧字段，重命名新字段 - vehicle_locations
ALTER TABLE vehicle_locations DROP COLUMN vehicle_id;
ALTER TABLE vehicle_locations RENAME COLUMN vehicle_id_new TO vehicle_id;

-- 2. 删除旧字段，重命名新字段 - vehicle_trajectories
ALTER TABLE vehicle_trajectories DROP COLUMN vehicle_id;
ALTER TABLE vehicle_trajectories RENAME COLUMN vehicle_id_new TO vehicle_id;

-- 3. 删除旧字段，重命名新字段 - vehicle_commands
ALTER TABLE vehicle_commands DROP COLUMN vehicle_id;
ALTER TABLE vehicle_commands RENAME COLUMN vehicle_id_new TO vehicle_id;

-- 4. 删除旧字段，重命名新字段 - rule_violation_events
-- 注意：这里需要谨慎处理，因为subject_id可能不只是车辆ID
ALTER TABLE rule_violation_events ADD COLUMN IF NOT EXISTS subject_id_new VARCHAR(50);
UPDATE rule_violation_events SET subject_id_new = 
    CASE 
        WHEN subject_type = 'VEHICLE' THEN vehicle_id_new::VARCHAR
        ELSE subject_id
    END;
ALTER TABLE rule_violation_events DROP COLUMN subject_id;
ALTER TABLE rule_violation_events RENAME COLUMN subject_id_new TO subject_id;

-- ============================================
-- 第六阶段：重建索引和约束
-- ============================================

-- 1. vehicle_locations表索引
DROP INDEX IF EXISTS idx_vehicle_locations_vehicle_id;
DROP INDEX IF EXISTS idx_vehicle_locations_license_plate;
CREATE INDEX idx_vehicle_locations_vehicle_id ON vehicle_locations(vehicle_id);
CREATE INDEX idx_vehicle_locations_license_plate ON vehicle_locations(license_plate);

-- 2. vehicle_trajectories表索引
DROP INDEX IF EXISTS idx_vehicle_trajectories_vehicle_id;
DROP INDEX IF EXISTS idx_vehicle_trajectories_license_plate;
CREATE INDEX idx_vehicle_trajectories_vehicle_id ON vehicle_trajectories(vehicle_id);
CREATE INDEX idx_vehicle_trajectories_license_plate ON vehicle_trajectories(license_plate);

-- 3. vehicle_commands表索引
DROP INDEX IF EXISTS idx_vehicle_commands_vehicle_id;
DROP INDEX IF EXISTS idx_vehicle_commands_license_plate;
CREATE INDEX idx_vehicle_commands_vehicle_id ON vehicle_commands(vehicle_id);
CREATE INDEX idx_vehicle_commands_license_plate ON vehicle_commands(license_plate);

-- 4. rule_violation_events表索引
DROP INDEX IF EXISTS idx_rule_violations_license_plate;
CREATE INDEX idx_rule_violations_license_plate ON rule_violation_events(license_plate) WHERE subject_type = 'VEHICLE';

-- ============================================
-- 第七阶段：添加外键约束
-- ============================================

-- 添加外键约束（可选，根据需要启用）
-- ALTER TABLE vehicle_locations ADD CONSTRAINT fk_vehicle_locations_vehicle_id 
--     FOREIGN KEY (vehicle_id) REFERENCES sys_vehicle_info(vehicle_id);

-- ALTER TABLE vehicle_trajectories ADD CONSTRAINT fk_vehicle_trajectories_vehicle_id 
--     FOREIGN KEY (vehicle_id) REFERENCES sys_vehicle_info(vehicle_id);

-- ALTER TABLE vehicle_commands ADD CONSTRAINT fk_vehicle_commands_vehicle_id 
--     FOREIGN KEY (vehicle_id) REFERENCES sys_vehicle_info(vehicle_id);

-- ============================================
-- 第八阶段：更新业务视图
-- ============================================

-- 删除旧视图
DROP VIEW IF EXISTS vehicle_complete_info;
DROP VIEW IF EXISTS vehicle_status_summary;
DROP VIEW IF EXISTS vehicle_info_with_location;
DROP VIEW IF EXISTS vehicle_trajectory_view;

-- 重新创建统一的业务视图
CREATE VIEW vehicle_complete_info AS
SELECT 
    vi.vehicle_id,
    vi.license_plate,
    vi.vin_number,
    vi.type_id,
    vt.type_name,
    vi.brand,
    vi.owning_unit,
    vi.contact_person,
    vi.phone_number,
    vi.image_url,
    vl.location,
    vl.altitude,
    vl.heading,
    vl.speed,
    vl.timestamp as last_location_time,
    vl.data_quality,
    vi.create_time,
    vi.update_time
FROM sys_vehicle_info vi
LEFT JOIN sys_vehicle_type vt ON vi.type_id = vt.type_id
LEFT JOIN LATERAL (
    SELECT * FROM vehicle_locations 
    WHERE vehicle_id = vi.vehicle_id 
    ORDER BY timestamp DESC 
    LIMIT 1
) vl ON true;

-- 车辆状态统计视图
CREATE VIEW vehicle_status_summary AS
SELECT 
    vehicle_type,
    COUNT(*) as total_vehicles,
    COUNT(CASE WHEN timestamp > NOW() - INTERVAL '5 minutes' THEN 1 END) as active_vehicles,
    COUNT(CASE WHEN timestamp <= NOW() - INTERVAL '5 minutes' THEN 1 END) as inactive_vehicles,
    AVG(speed) as avg_speed,
    MAX(speed) as max_speed
FROM vehicle_locations vl
WHERE timestamp > NOW() - INTERVAL '24 hours'
GROUP BY vehicle_type;

-- 车辆信息与位置关联视图
CREATE VIEW vehicle_info_with_location AS
SELECT 
    vi.vehicle_id,
    vi.license_plate,
    vi.brand,
    vi.owning_unit,
    vt.type_name as vehicle_type_name,
    vl.vehicle_type as location_vehicle_type,
    vl.location,
    ST_X(vl.location) as longitude,
    ST_Y(vl.location) as latitude,
    vl.altitude,
    vl.heading,
    vl.speed,
    vl.timestamp as last_update_time,
    CASE 
        WHEN vl.timestamp > NOW() - INTERVAL '5 minutes' THEN 'ACTIVE'
        WHEN vl.timestamp > NOW() - INTERVAL '30 minutes' THEN 'INACTIVE'
        ELSE 'OFFLINE'
    END as status
FROM sys_vehicle_info vi
LEFT JOIN sys_vehicle_type vt ON vi.type_id = vt.type_id
LEFT JOIN LATERAL (
    SELECT * FROM vehicle_locations 
    WHERE vehicle_id = vi.vehicle_id 
    ORDER BY timestamp DESC 
    LIMIT 1
) vl ON true;

-- 车辆轨迹查询视图
CREATE VIEW vehicle_trajectory_view AS
SELECT 
    vi.vehicle_id,
    vi.license_plate,
    vi.brand,
    vt.trajectory_date,
    vt.trajectory_line,
    vt.total_distance,
    vt.max_speed,
    vt.avg_speed,
    vt.duration_seconds,
    vt.start_time,
    vt.end_time
FROM sys_vehicle_info vi
INNER JOIN vehicle_trajectories vt ON vt.vehicle_id = vi.vehicle_id
LEFT JOIN sys_vehicle_type vtype ON vi.type_id = vtype.type_id;

-- ============================================
-- 第九阶段：添加字段注释
-- ============================================

-- sys_vehicle_info表字段注释
COMMENT ON COLUMN sys_vehicle_info.license_plate IS '车牌号（统一字段名）';

-- vehicle_locations表字段注释
COMMENT ON COLUMN vehicle_locations.vehicle_id IS '车辆ID（数字主键，关联sys_vehicle_info.vehicle_id）';
COMMENT ON COLUMN vehicle_locations.license_plate IS '车牌号（业务标识符）';

-- vehicle_trajectories表字段注释
COMMENT ON COLUMN vehicle_trajectories.vehicle_id IS '车辆ID（数字主键，关联sys_vehicle_info.vehicle_id）';
COMMENT ON COLUMN vehicle_trajectories.license_plate IS '车牌号（业务标识符）';

-- vehicle_commands表字段注释
COMMENT ON COLUMN vehicle_commands.vehicle_id IS '车辆ID（数字主键，关联sys_vehicle_info.vehicle_id）';
COMMENT ON COLUMN vehicle_commands.license_plate IS '车牌号（业务标识符）';

-- rule_violation_events表字段注释
COMMENT ON COLUMN rule_violation_events.license_plate IS '车牌号（仅当subject_type为VEHICLE时有效）';

-- ============================================
-- 第十阶段：清理临时数据
-- ============================================

-- 删除临时映射表
DROP TABLE IF EXISTS vehicle_id_mapping;

-- ============================================
-- 最终验证
-- ============================================

DO $$
DECLARE
    qaup_count INTEGER;
    locations_count INTEGER;
    trajectories_count INTEGER;
    commands_count INTEGER;
    violations_count INTEGER;
BEGIN
    -- 统计各表记录数
    SELECT COUNT(*) INTO qaup_count FROM sys_vehicle_info;
    SELECT COUNT(*) INTO locations_count FROM vehicle_locations;
    SELECT COUNT(*) INTO trajectories_count FROM vehicle_trajectories;
    SELECT COUNT(*) INTO commands_count FROM vehicle_commands;
    SELECT COUNT(*) INTO violations_count FROM rule_violation_events WHERE subject_type = 'VEHICLE';
    
    -- 输出统计信息
    RAISE NOTICE '==============================================';
    RAISE NOTICE '数据模型统一重构完成！';
    RAISE NOTICE '==============================================';
    RAISE NOTICE '车辆信息记录: %', qaup_count;
    RAISE NOTICE '位置记录: %', locations_count;
    RAISE NOTICE '轨迹记录: %', trajectories_count;
    RAISE NOTICE '指令记录: %', commands_count;
    RAISE NOTICE '违规事件记录: %', violations_count;
    RAISE NOTICE '==============================================';
    RAISE NOTICE '主要改进：';
    RAISE NOTICE '1. 统一vehicle_id为数字主键';
    RAISE NOTICE '2. 统一license_plate为车牌号字段名';
    RAISE NOTICE '3. 消除所有字段名不一致';
    RAISE NOTICE '4. 重建了所有业务视图';
    RAISE NOTICE '5. 优化了索引结构';
    RAISE NOTICE '==============================================';
END $$;

-- 提交事务
COMMIT;

-- 显示完成消息
\echo '数据模型统一重构脚本执行完成！'
\echo '请验证数据完整性和功能正常性。' 