-- 03_fuel_timezone_eat.sql — fleetfuel · standardize fuel times to Africa/Nairobi
-- ─────────────────────────────────────────────────────────────────────────────
-- The source feed stamps record_datetime in UTC ("…Z"). The fleet operates in
-- Kenya (EAT, UTC+3), so storing UTC `timestamptz` made record_datetime::date
-- bucket by UTC day — an evening fill (e.g. 22:00 EAT = 19:00 UTC, fine, but
-- 01:00 EAT = 22:00 prev-day UTC) lands on the wrong calendar day in the daily
-- trend. Standardize every fuel timestamp to Africa/Nairobi WALL-CLOCK stored as
-- `timestamp` (without time zone): the value you read in the table is EAT, and
-- record_datetime::date is the EAT day.
--
-- Runs only after 01/02 (columns are still timestamptz here), so the USING
-- conversion `col AT TIME ZONE 'Africa/Nairobi'` (timestamptz -> local EAT
-- timestamp) is always correct. Idempotent in effect; safe to re-apply.
-- ─────────────────────────────────────────────────────────────────────────────

-- EAT-local cast: source UTC text -> Africa/Nairobi wall-clock timestamp (or NULL).
CREATE OR REPLACE FUNCTION fuel.to_ts_eat(p text)
 RETURNS timestamp LANGUAGE plpgsql STABLE AS $fn$
BEGIN
  RETURN (NULLIF(btrim(p), '')::timestamptz) AT TIME ZONE 'Africa/Nairobi';
EXCEPTION WHEN others THEN
  RETURN NULL;
END $fn$;

-- Views depend on record_datetime, so drop them before the column type change.
DROP VIEW IF EXISTS reporting.v_fuel_efficiency;
DROP VIEW IF EXISTS reporting.v_fuel_fills;

-- Convert existing data (timestamptz instant -> EAT wall-clock) and switch types.
ALTER TABLE fuel.records
  ALTER COLUMN record_datetime TYPE timestamp USING (record_datetime AT TIME ZONE 'Africa/Nairobi'),
  ALTER COLUMN deleted_at      TYPE timestamp USING (deleted_at      AT TIME ZONE 'Africa/Nairobi'),
  ALTER COLUMN ingested_at     TYPE timestamp USING (ingested_at     AT TIME ZONE 'Africa/Nairobi'),
  ALTER COLUMN updated_at      TYPE timestamp USING (updated_at      AT TIME ZONE 'Africa/Nairobi');
ALTER TABLE fuel.records
  ALTER COLUMN ingested_at SET DEFAULT (now() AT TIME ZONE 'Africa/Nairobi'),
  ALTER COLUMN updated_at  SET DEFAULT (now() AT TIME ZONE 'Africa/Nairobi');

ALTER TABLE fuel.ingest_state
  ALTER COLUMN updated_at TYPE timestamp USING (updated_at AT TIME ZONE 'Africa/Nairobi'),
  ALTER COLUMN updated_at SET DEFAULT (now() AT TIME ZONE 'Africa/Nairobi');

-- Trigger now derives EAT-local timestamps from raw.
CREATE OR REPLACE FUNCTION fuel.tg_records_derive()
 RETURNS trigger LANGUAGE plpgsql AS $fn$
BEGIN
  NEW.record_datetime     := fuel.to_ts_eat(NEW.raw->>'record_datetime');
  NEW.car_raw             := NEW.raw->>'car';
  NEW.plate               := fuel.norm_plate(NEW.raw->>'car');
  NEW.liters              := fuel.to_num(NEW.raw->>'liters');
  NEW.amount              := fuel.to_num(NEW.raw->>'amount');
  NEW.fuel_type           := fuel.canon_fuel_type(NEW.raw->>'fuel_type');
  NEW.fuel_type_raw       := NEW.raw->>'fuel_type';
  NEW.department          := fuel.canon_department(NEW.raw->>'department');
  NEW.driver              := NULLIF(btrim(NEW.raw->>'driver'), '');
  NEW.odometer            := fuel.to_num(NEW.raw->>'odometer');
  NEW.deleted_at          := fuel.to_ts_eat(NEW.raw->>'deleted_at');
  NEW.message_fingerprint := NEW.raw->>'message_fingerprint';
  NEW.updated_at          := now() AT TIME ZONE 'Africa/Nairobi';
  RETURN NEW;
END $fn$;

-- Recreate the read views (record_datetime is now EAT-local; fuel_date follows).
CREATE OR REPLACE VIEW reporting.v_fuel_fills AS
 SELECT r.id,
        r.record_datetime,
        r.record_datetime::date AS fuel_date,
        r.plate,
        d.vehicle_number,
        d.cost_centre,
        d.assigned_city,
        d.assigned_driver,
        d.imei,
        r.department,
        r.driver,
        r.liters,
        r.amount,
        r.fuel_type,
        r.odometer
   FROM fuel.records r
   LEFT JOIN LATERAL (
        SELECT dv.vehicle_number, dv.cost_centre, dv.assigned_city,
               dv.driver_name AS assigned_driver, dv.imei
          FROM tracksolid.devices dv
         WHERE r.plate IS NOT NULL
           AND fuel.norm_plate(dv.vehicle_number) = r.plate
         ORDER BY dv.enabled_flag DESC NULLS LAST, dv.updated_at DESC NULLS LAST
         LIMIT 1
   ) d ON true
  WHERE r.deleted_at IS NULL;

CREATE OR REPLACE VIEW reporting.v_fuel_efficiency AS
 WITH seq AS (
   SELECT id, plate, vehicle_number, cost_centre, assigned_city,
          record_datetime, fuel_date, odometer, liters, amount, fuel_type,
          odometer - lag(odometer) OVER (PARTITION BY plate ORDER BY record_datetime, id) AS km_since_last
     FROM reporting.v_fuel_fills
    WHERE plate IS NOT NULL AND odometer IS NOT NULL AND odometer > 0
 )
 SELECT seq.*,
        CASE WHEN liters > 0 AND km_since_last > 0 AND km_since_last < 5000
             THEN round(km_since_last / liters, 2)
        END AS km_per_litre
   FROM seq;

-- Dropping the views dropped their grants — re-grant to the read-only role.
DO $grants$
BEGIN
  IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'grafana_ro') THEN
    GRANT USAGE ON SCHEMA reporting TO grafana_ro;
    GRANT SELECT ON reporting.v_fuel_fills, reporting.v_fuel_efficiency TO grafana_ro;
  END IF;
END $grants$;
