-- 0090_water_log_completion.sql
--
-- Water Log feature completion. The original `0001_init.sql` shipped the
-- core five tables (headgates, irrigators, sessions, log entries, alerts)
-- with RLS, but the SaaS rebuild's actions and UIs depend on a wider
-- surface that this migration adds:
--
--   - `water_headgates.headgate_token`       — opaque per-gate token for QR
--   - `water_headgates.status`               — open / closed / maintenance
--   - `water_headgates.max_flow_gpm`         — optional high-water marker
--   - `water_headgates.notes`                — free-form location notes
--   - `water_headgates.last_used_at`         — denormalized for display
--   - `water_headgates.high_threshold`       — optional alert ceiling
--   - `water_headgates.low_threshold`        — optional alert floor
--   - `water_headgates.unit`                 — display unit (CFS/GPM/etc.)
--
--   - `water_irrigators.role`                — "irrigator" | "water_admin"
--   - `water_irrigators.phone`               — optional contact
--   - `water_irrigators.notes`               — free-form
--
--   - `water_log_entries.method`             — "manual" | "meter" | "estimate" | "qr"
--   - `water_log_entries.total_gallons`      — derived when computable
--   - `water_log_entries.photo_url`          — link to storage object
--   - `water_log_entries.logged_date`        — date-only (YYYY-MM-DD) for fast grouping
--   - `water_log_entries.latitude`/`longitude` — optional GPS pin
--   - `water_log_entries.brand_id` index upgrade
--
--   - NEW `water_admin_settings` (per-brand admin PIN + alert config)
--   - NEW `water_admin_sessions` (admin sign-in sessions, separate cookie)
--   - NEW `water_audit_log` (who changed what, when)
--
-- All new tables follow project conventions:
--   - TIMESTAMPTZ for timestamps
--   - UUID PKs via gen_random_uuid()
--   - brand_id scoped, RLS enabled, FORCE'd
--   - CREATE TABLE IF NOT EXISTS for re-runnability
--
-- ============================================================================

-- ─── 1. Extend water_headgates ──────────────────────────────────────────────

ALTER TABLE water_headgates
  ADD COLUMN IF NOT EXISTS headgate_token TEXT UNIQUE
    DEFAULT encode(gen_random_bytes(12), 'hex'),
  ADD COLUMN IF NOT EXISTS status TEXT NOT NULL DEFAULT 'open'
    CHECK (status IN ('open', 'closed', 'maintenance')),
  ADD COLUMN IF NOT EXISTS max_flow_gpm NUMERIC,
  ADD COLUMN IF NOT EXISTS notes TEXT,
  ADD COLUMN IF NOT EXISTS last_used_at TIMESTAMPTZ,
  ADD COLUMN IF NOT EXISTS high_threshold NUMERIC,
  ADD COLUMN IF NOT EXISTS low_threshold NUMERIC,
  ADD COLUMN IF NOT EXISTS unit TEXT NOT NULL DEFAULT 'CFS';

-- Backfill any existing rows that pre-date the default expression
UPDATE water_headgates
  SET headgate_token = encode(gen_random_bytes(12), 'hex')
  WHERE headgate_token IS NULL;

-- ─── 2. Extend water_irrigators ─────────────────────────────────────────────

ALTER TABLE water_irrigators
  ADD COLUMN IF NOT EXISTS role TEXT NOT NULL DEFAULT 'irrigator'
    CHECK (role IN ('irrigator', 'water_admin')),
  ADD COLUMN IF NOT EXISTS phone TEXT,
  ADD COLUMN IF NOT EXISTS notes TEXT;

-- ─── 3. Extend water_log_entries ────────────────────────────────────────────

ALTER TABLE water_log_entries
  ADD COLUMN IF NOT EXISTS method TEXT NOT NULL DEFAULT 'manual'
    CHECK (method IN ('manual', 'meter', 'estimate', 'qr')),
  ADD COLUMN IF NOT EXISTS total_gallons NUMERIC,
  ADD COLUMN IF NOT EXISTS photo_url TEXT,
  ADD COLUMN IF NOT EXISTS logged_date DATE,
  ADD COLUMN IF NOT EXISTS latitude DOUBLE PRECISION,
  ADD COLUMN IF NOT EXISTS longitude DOUBLE PRECISION;

-- Backfill logged_date for any rows that pre-date the column
UPDATE water_log_entries
  SET logged_date = (logged_at AT TIME ZONE 'UTC')::date
  WHERE logged_date IS NULL AND logged_at IS NOT NULL;

-- Index for fast "today's entries" + "this week's entries" queries
CREATE INDEX IF NOT EXISTS water_log_entries_brand_date_idx
  ON water_log_entries (brand_id, logged_date DESC);
CREATE INDEX IF NOT EXISTS water_log_entries_irrigator_idx
  ON water_log_entries (irrigator_id, logged_at DESC);

-- ─── 4. water_admin_settings (per brand) ───────────────────────────────────

CREATE TABLE IF NOT EXISTS water_admin_settings (
  brand_id UUID PRIMARY KEY REFERENCES brands(id) ON DELETE CASCADE,
  enabled BOOLEAN NOT NULL DEFAULT true,
  session_duration_hours INTEGER NOT NULL DEFAULT 4
    CHECK (session_duration_hours BETWEEN 1 AND 168),
  can_edit_entries BOOLEAN NOT NULL DEFAULT true,
  can_delete_entries BOOLEAN NOT NULL DEFAULT true,
  can_export_csv BOOLEAN NOT NULL DEFAULT true,
  alert_phone TEXT,
  alerts_enabled BOOLEAN NOT NULL DEFAULT false,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_by UUID REFERENCES admin_users(id)
);

DO $$
BEGIN
  IF NOT EXISTS (
    SELECT 1 FROM pg_trigger t
    JOIN pg_class c ON t.tgrelid = c.oid
    JOIN pg_namespace n ON c.relnamespace = n.oid
    WHERE t.tgname = 'water_admin_settings_updated_at' AND n.nspname = current_schema()
  ) THEN
    CREATE TRIGGER water_admin_settings_updated_at BEFORE UPDATE ON water_admin_settings
      FOR EACH ROW EXECUTE FUNCTION set_updated_at();
  END IF;
END $$;

-- ─── 5. water_admin_sessions (separate from irrigator sessions) ───────────

CREATE TABLE IF NOT EXISTS water_admin_sessions (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  brand_id UUID NOT NULL REFERENCES brands(id) ON DELETE CASCADE,
  admin_user_id UUID NOT NULL REFERENCES admin_users(id) ON DELETE CASCADE,
  pin_hash_used TEXT NOT NULL,
  expires_at TIMESTAMPTZ NOT NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS water_admin_sessions_admin_idx
  ON water_admin_sessions (admin_user_id, expires_at DESC);

-- ─── 6. water_audit_log (who changed what, when) ───────────────────────────

CREATE TABLE IF NOT EXISTS water_audit_log (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  brand_id UUID NOT NULL REFERENCES brands(id) ON DELETE CASCADE,
  actor_id UUID REFERENCES admin_users(id),
  actor_label TEXT NOT NULL,
  action TEXT NOT NULL,
  entity_type TEXT NOT NULL,
  entity_id UUID,
  details JSONB,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS water_audit_log_brand_recent_idx
  ON water_audit_log (brand_id, created_at DESC);

-- ─── 7. RLS for new tables ────────────────────────────────────────────────

ALTER TABLE water_admin_settings ENABLE ROW LEVEL SECURITY;
ALTER TABLE water_admin_sessions ENABLE ROW LEVEL SECURITY;
ALTER TABLE water_audit_log ENABLE ROW LEVEL SECURITY;

ALTER TABLE water_admin_settings FORCE ROW LEVEL SECURITY;
ALTER TABLE water_admin_sessions FORCE ROW LEVEL SECURITY;
ALTER TABLE water_audit_log FORCE ROW LEVEL SECURITY;

DROP POLICY IF EXISTS tenant_isolation ON water_admin_settings;
CREATE POLICY tenant_isolation ON water_admin_settings FOR ALL
  USING (brand_id = current_brand_id() OR is_platform_admin())
  WITH CHECK (brand_id = current_brand_id() OR is_platform_admin());

DROP POLICY IF EXISTS tenant_isolation ON water_admin_sessions;
CREATE POLICY tenant_isolation ON water_admin_sessions FOR ALL
  USING (brand_id = current_brand_id() OR is_platform_admin())
  WITH CHECK (brand_id = current_brand_id() OR is_platform_admin());

DROP POLICY IF EXISTS tenant_isolation ON water_audit_log;
CREATE POLICY tenant_isolation ON water_audit_log FOR ALL
  USING (brand_id = current_brand_id() OR is_platform_admin())
  WITH CHECK (brand_id = current_brand_id() OR is_platform_admin());
