CREATE OR REPLACE FUNCTION set_updated_at() RETURNS trigger AS $$
BEGIN
  NEW.updated_at = NOW();
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'trg_case_updated_at') THEN
    CREATE TRIGGER trg_case_updated_at BEFORE UPDATE ON br_case FOR EACH ROW EXECUTE FUNCTION set_updated_at();
    CREATE TRIGGER trg_deadline_updated_at BEFORE UPDATE ON deadline FOR EACH ROW EXECUTE FUNCTION set_updated_at();
    CREATE TRIGGER trg_meeting_updated_at BEFORE UPDATE ON meeting FOR EACH ROW EXECUTE FUNCTION set_updated_at();
    CREATE TRIGGER trg_decision_updated_at BEFORE UPDATE ON decision FOR EACH ROW EXECUTE FUNCTION set_updated_at();
    CREATE TRIGGER trg_task_updated_at BEFORE UPDATE ON task FOR EACH ROW EXECUTE FUNCTION set_updated_at();
    CREATE TRIGGER trg_document_updated_at BEFORE UPDATE ON document_item FOR EACH ROW EXECUTE FUNCTION set_updated_at();
    CREATE TRIGGER trg_template_updated_at BEFORE UPDATE ON template_item FOR EACH ROW EXECUTE FUNCTION set_updated_at();
  END IF;
END $$;

CREATE OR REPLACE FUNCTION audit_if_changed() RETURNS trigger AS $$
BEGIN
  INSERT INTO audit_log(actor_user_id, action, entity_type, entity_id, metadata)
  VALUES (
    NULL,
    TG_OP,
    TG_TABLE_NAME,
    COALESCE(NEW.id, OLD.id),
    jsonb_build_object('old', to_jsonb(OLD), 'new', to_jsonb(NEW))
  );
  RETURN COALESCE(NEW, OLD);
END;
$$ LANGUAGE plpgsql;

DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'trg_audit_case') THEN
    CREATE TRIGGER trg_audit_case AFTER INSERT OR UPDATE OR DELETE ON br_case FOR EACH ROW EXECUTE FUNCTION audit_if_changed();
    CREATE TRIGGER trg_audit_deadline AFTER INSERT OR UPDATE OR DELETE ON deadline FOR EACH ROW EXECUTE FUNCTION audit_if_changed();
    CREATE TRIGGER trg_audit_meeting AFTER INSERT OR UPDATE OR DELETE ON meeting FOR EACH ROW EXECUTE FUNCTION audit_if_changed();
    CREATE TRIGGER trg_audit_decision AFTER INSERT OR UPDATE OR DELETE ON decision FOR EACH ROW EXECUTE FUNCTION audit_if_changed();
    CREATE TRIGGER trg_audit_task AFTER INSERT OR UPDATE OR DELETE ON task FOR EACH ROW EXECUTE FUNCTION audit_if_changed();
    CREATE TRIGGER trg_audit_document AFTER INSERT OR UPDATE OR DELETE ON document_item FOR EACH ROW EXECUTE FUNCTION audit_if_changed();
  END IF;
END $$;

CREATE OR REPLACE FUNCTION app_user_id() RETURNS BIGINT AS $$
  SELECT COALESCE(NULLIF(current_setting('app.user_id', true), ''), '0')::BIGINT;
$$ LANGUAGE SQL STABLE;

CREATE OR REPLACE FUNCTION app_role() RETURNS TEXT AS $$
  SELECT COALESCE(NULLIF(current_setting('app.user_role', true), ''), 'anonymous');
$$ LANGUAGE SQL STABLE;

CREATE OR REPLACE FUNCTION app_committee_id() RETURNS BIGINT AS $$
  SELECT COALESCE(NULLIF(current_setting('app.committee_id', true), ''), '0')::BIGINT;
$$ LANGUAGE SQL STABLE;

CREATE OR REPLACE FUNCTION can_read_conf_level(level conf_level, owner BIGINT, committee BIGINT) RETURNS BOOLEAN AS $$
BEGIN
  IF app_role() = 'admin' THEN RETURN TRUE; END IF;
  IF level = 'intern' THEN RETURN TRUE; END IF;
  IF level = 'vertraulich' THEN
    RETURN owner = app_user_id() OR committee = app_committee_id() OR app_role() IN ('chair','secretary');
  END IF;
  RETURN owner = app_user_id() OR app_role() IN ('chair');
END;
$$ LANGUAGE plpgsql STABLE;

CREATE OR REPLACE VIEW v_case_masked AS
SELECT
  id,
  case_number,
  title,
  case_type,
  status,
  priority,
  confidentiality_level,
  CASE
    WHEN confidentiality_level = 'streng_vertraulich' AND app_role() NOT IN ('admin','chair') AND owner_user_id <> app_user_id()
      THEN '***'
    ELSE COALESCE(affected_employee_name, '')
  END AS affected_employee_name_masked,
  department,
  committee_id,
  owner_user_id,
  created_at
FROM br_case
WHERE deleted_at IS NULL;
