-- 008 - Re-key the seed on CI Server item names
--
-- WHY. The point list delivered in August named the published values
-- PS_STN_WET_WELL_LEVEL and the like. Those were never CI Server names: they
-- came from the PLC-side generator, and the CI Server generator ignored them.
-- A corrected delivery on 2026-09-01 is keyed on the CI Server ITEM each point
-- feeds - AID.WRPS.STN.LEVEL - which is what the historian is keyed on too.
--
-- WHY A MIGRATION AND NOT JUST A RELOAD. 001_schema.sql is CREATE TABLE IF NOT
-- EXISTS, so it will not add the three new columns to a table that already
-- exists, and deploy.sh only ever upserts - nothing deletes. Re-running the
-- seed load on its own would fail on the missing columns and, if it did not,
-- would leave 45 retired keys sitting beside their 45 replacements with two
-- foreign keys still pointing at the old ones.
--
-- SAFE TO RE-RUN. Every step is guarded. On a fresh database created by
-- 001_schema.sql this does nothing at all.

BEGIN;

-- 1. The column change 001_schema.sql cannot make on an existing table.
ALTER TABLE historian_items ADD COLUMN IF NOT EXISTS ci_station TEXT;
ALTER TABLE historian_items ADD COLUMN IF NOT EXISTS ci_point   TEXT;
ALTER TABLE historian_items ADD COLUMN IF NOT EXISTS poll_group TEXT;

-- Carry the old value across before dropping it, so the column is not simply
-- lost if the seed reload is not run immediately after this migration.
UPDATE historian_items SET ci_point = scada_point
 WHERE ci_point IS NULL
   AND EXISTS (SELECT 1 FROM information_schema.columns
                WHERE table_name = 'historian_items' AND column_name = 'scada_point');

ALTER TABLE historian_items DROP COLUMN IF EXISTS scada_point;

-- 2. Capture the mapping BEFORE anything is updated. historian_items.tag_id is
--    itself about to change, so a later lookup through it finds nothing - an
--    ordering bug that would have left alarm_bits pointing at deleted rows.
CREATE TEMP TABLE _rename ON COMMIT DROP AS
SELECT tag_id AS old_tag, item_name AS new_tag
  FROM historian_items
 WHERE tag_id LIKE 'PS!_%' ESCAPE '!';

-- Every alarm_bits key must be in that mapping, or we stop before touching
-- anything. A silently unmapped alarm is how an alarm count becomes wrong.
DO $$
DECLARE unmapped INT;
BEGIN
  SELECT count(*) INTO unmapped
    FROM alarm_bits a
   WHERE a.tag_id LIKE 'PS!_%' ESCAPE '!'
     AND NOT EXISTS (SELECT 1 FROM _rename r WHERE r.old_tag = a.tag_id);
  IF unmapped > 0 THEN
    RAISE EXCEPTION '% alarm_bits rows have no item to move to', unmapped;
  END IF;
END $$;

-- 3. Give every retired key its replacement row, copying the old row's own
--    facts. The seed reload that follows overwrites these with the delivered
--    values; they exist here so the foreign keys below have somewhere to land.
INSERT INTO tags (tag_id, equipment_id, display_name, aliases, signal_type,
                  engineering_unit, range_low, range_high, alarm_setpoint_hi,
                  alarm_setpoint_lo, trip_setpoint, description)
SELECT r.new_tag, t.equipment_id, t.display_name, t.aliases, t.signal_type,
       t.engineering_unit, t.range_low, t.range_high, t.alarm_setpoint_hi,
       t.alarm_setpoint_lo, t.trip_setpoint, t.description
  FROM _rename r JOIN tags t ON t.tag_id = r.old_tag
ON CONFLICT (tag_id) DO NOTHING;

-- 4. Repoint both foreign keys, alarm_bits first so it still reads the mapping.
UPDATE alarm_bits a SET tag_id = r.new_tag
  FROM _rename r WHERE a.tag_id = r.old_tag;

UPDATE historian_items h SET tag_id = r.new_tag
  FROM _rename r WHERE h.tag_id = r.old_tag;

-- 5. Anything still referencing a retired key is a defect, not a leftover.
DO $$
DECLARE orphans INT;
BEGIN
  SELECT count(*) INTO orphans FROM alarm_bits WHERE tag_id LIKE 'PS!_%' ESCAPE '!';
  IF orphans > 0 THEN RAISE EXCEPTION 'alarm_bits still holds % retired keys', orphans; END IF;
  SELECT count(*) INTO orphans FROM historian_items WHERE tag_id LIKE 'PS!_%' ESCAPE '!';
  IF orphans > 0 THEN RAISE EXCEPTION 'historian_items still holds % retired keys', orphans; END IF;
END $$;

-- 6. Now unreferenced, so they can go.
DELETE FROM tags WHERE tag_id LIKE 'PS!_%' ESCAPE '!';

COMMIT;
