-- =============================================================================
-- 008 - public.shift_log, the operator shift log.
--
--   ############################################################
--   ##  DEMO DATA.  NOT A REAL SHIFT LOG.  DO NOT QUOTE.       ##
--   ############################################################
--
-- WHY THIS IS A TABLE AND NOT A DOCUMENT, AND NOT THE HISTORIAN
-- -------------------------------------------------------------
-- A shift log is continuously updated, which rules out both of the stores we
-- already have:
--
--   * NOT doc_chunks. That store is built on doc_number + revision +
--     effective_date, and nothing in it is citable until a human has confirmed
--     that header. A record that changes every shift would need re-confirming
--     every shift, and a confirmation gate asked that often stops being a gate.
--     It is the same mechanism that makes a procedure citation trustworthy, so
--     wearing it out here would cost us something real elsewhere.
--
--   * NOT the historian. Three reasons and the first is decisive: we hold
--     READ-ONLY on imh and may not write to it at all. Beyond that, the
--     historian is keyed on the CI Server item and only the item - a log entry
--     has no item, no register and no scan interval, and inventing one is what
--     produced all three Phase 5 findings. And its retention is seven days,
--     so the one source that could outlive the historian would expire with it.
--
-- So it is a third evidence source alongside the historian and the document
-- library: free text, at irregular times, by a named author.
--
-- WHAT THIS DELIBERATELY DOES NOT DO
-- ----------------------------------
-- Entries are NOT citations. Citation means a controlled document with a
-- confirmed revision, and an operator note is not that however true it is.
-- Shift-log evidence is returned as rows on the historical lane, labelled as
-- an operator record, and the Citation contract is untouched. Extending
-- Citation to cover a second kind of source is a real design decision and is
-- not being made here.
--
-- There is no retention limit on this table. The seven-day query window in
-- tools/shiftlog.py is there to match the historical lane's window, not
-- because anything here expires. When the query window becomes variable
-- (REQUESTS.md), this table can answer questions the historian cannot.
--
-- WRITE PATH: none. There is no UI and no API that inserts here. The seed
-- below is the whole content, and it is demo fiction. An operator writing a
-- real entry is Phase 9 work that has not been scoped.
-- =============================================================================

CREATE TABLE IF NOT EXISTS shift_log (
    id           BIGSERIAL PRIMARY KEY,
    entry_time   TIMESTAMPTZ NOT NULL,   -- UTC. Converted to site time once, on the way out.
    shift        TEXT NOT NULL,
    author       TEXT NOT NULL,
    equipment_id TEXT REFERENCES equipment (equipment_id),
    entry_text   TEXT NOT NULL,
    -- Mirrors fixture.is_fixture and the DEMO- document numbering: an entry
    -- nobody wrote must never be indistinguishable from one somebody did.
    -- tools/shiftlog.py carries this out to used_fixture_data on the answer.
    is_demo      BOOLEAN NOT NULL DEFAULT FALSE,
    CONSTRAINT shift_log_shift_ck CHECK (shift IN ('day', 'night'))
);

CREATE INDEX IF NOT EXISTS shift_log_entry_time ON shift_log (entry_time DESC);
CREATE INDEX IF NOT EXISTS shift_log_equipment ON shift_log (equipment_id);

-- -----------------------------------------------------------------------------
-- Demo entries.
--
-- Anchored to the START OF TODAY IN SITE LOCAL TIME, then placed at fixed
-- local times on fixed days back. Two properties matter and the first is not
-- obvious:
--
--   * The shift label has to match the clock. An earlier version offset every
--     entry by a whole number of hours from now(), which is relative and
--     therefore never goes stale - but it slid every entry's local hour as the
--     day wore on, and produced night-shift entries timestamped 10:00. Demo
--     data that contradicts itself on the face of it is worse than none.
--
--   * Relative, not absolute, so re-running always lands entries inside the
--     rolling seven days. The alarm fixtures are absolute and have gone stale;
--     this does not.
--
-- ONE anchor for the whole load, not a per-statement now(), for the reason
-- 002_fixtures.sql gives: a statement-by-statement now() drifts within a load.
--
-- The site timezone is named here because this seed places entries at local
-- clock times and there is no other way to do that. It must match
-- SITE_TIMEZONE in ~/ai/api.env. The conversion still happens exactly once,
-- and never in a prompt.
--
-- Entries in the future are dropped rather than inserted: a load run at 03:00
-- would otherwise write a day-shift entry that has not happened yet.
--
-- Re-runnable: demo rows are deleted and reinserted. Only rows marked is_demo
-- are touched, so a real entry could never be removed by a re-run.
-- -----------------------------------------------------------------------------
DELETE FROM shift_log WHERE is_demo;

INSERT INTO shift_log (entry_time, shift, author, equipment_id, entry_text, is_demo)
SELECT entry_time, shift, author, equipment_id, entry_text, TRUE
  FROM (
    SELECT ((a.today - days_back * interval '1 day' + local_time)
              AT TIME ZONE 'Australia/Sydney') AS entry_time,
           v.shift, v.author, v.equipment_id, v.entry_text
      FROM (SELECT date_trunc('day', now() AT TIME ZONE 'Australia/Sydney') AS today) a,
           (VALUES
              (6, time '02:40', 'night', 'demo:J. Whitmore', 'PU-302',
               'PU-302 tripped on overload at 02:20 and was reset from the panel at 03:05. '
               'Ran up clean afterwards. Mechanical to look at the strainer next day shift.'),
              (6, time '13:15', 'day',   'demo:A. Ngata',    'PU-302',
               'Strainer on PU-302 cleared - heavy rag. No repeat of the overload trip through the shift.'),
              (5, time '09:55', 'day',   'demo:A. Ngata',    'WW-101',
               'Wet well level instrument LIT-101 dropped out briefly around 09:40. '
               'Reading recovered on its own. Logged for instrument tech to check the cable gland.'),
              (4, time '01:30', 'night', 'demo:J. Whitmore', 'PU-303',
               'PU-303 seal leak alarm came in and returned. Small weep at the seal, not running to drain. '
               'Left on duty rotation, flagged for maintenance.'),
              (3, time '15:20', 'day',   'demo:R. Patel',    'PU-301',
               'PU-301 vibration alarm during the afternoon peak. Settled once flow came off. '
               'Nothing obvious on inspection.'),
              (2, time '04:05', 'night', 'demo:J. Whitmore', NULL,
               'Quiet shift. Station on auto throughout, no alarms, no operator intervention.'),
              (1, time '11:40', 'day',   'demo:R. Patel',    'WW-101',
               'Heavy rain from mid-morning. Wet well worked hard but stayed well under the weir. '
               'All three pumps called at times.'),
              (0, time '06:10', 'day',   'demo:A. Ngata',    NULL,
               'Handover: station on auto, no outstanding alarms. '
               'PU-302 strainer still to be signed off by mechanical.')
           ) AS v(days_back, local_time, shift, author, equipment_id, entry_text)
  ) placed
 WHERE entry_time <= now();

DO $$
DECLARE n INT; newest TIMESTAMPTZ; oldest TIMESTAMPTZ;
BEGIN
    SELECT count(*), min(entry_time), max(entry_time)
      INTO n, oldest, newest FROM shift_log WHERE is_demo;
    RAISE NOTICE 'shift_log: % demo entries, % to %', n, oldest, newest;
    -- Every entry must be inside the rolling seven days the historical lane
    -- asks for, or the demo shows an empty log.
    IF n < 6 THEN
        RAISE EXCEPTION 'expected at least 6 demo shift log entries, loaded %', n;
    END IF;
    IF oldest <= now() - interval '7 days' THEN
        RAISE EXCEPTION 'oldest demo entry % is outside the 7 day query window', oldest;
    END IF;
    IF newest > now() THEN
        RAISE EXCEPTION 'demo entry % is in the future', newest;
    END IF;
END $$;
