DO $$
DECLARE
    cancel_violations BIGINT;
    move_violations BIGINT;
    replace_violations BIGINT;
    format_violations BIGINT;
BEGIN
    SELECT count(*)
    INTO cancel_violations
    FROM schedule_overrides
    WHERE action = 'CANCEL'
      AND (new_time_slot_id IS NOT NULL
        OR new_classroom_id IS NOT NULL
        OR new_teacher_id IS NOT NULL
        OR new_lesson_format IS NOT NULL);

    SELECT count(*)
    INTO move_violations
    FROM schedule_overrides
    WHERE action = 'MOVE'
      AND new_time_slot_id IS NULL
      AND new_classroom_id IS NULL;

    SELECT count(*)
    INTO replace_violations
    FROM schedule_overrides
    WHERE action = 'REPLACE'
      AND new_teacher_id IS NULL
      AND new_classroom_id IS NULL
      AND new_lesson_format IS NULL;

    SELECT count(*)
    INTO format_violations
    FROM schedule_overrides
    WHERE new_lesson_format IS NOT NULL
      AND new_lesson_format NOT IN ('Очно', 'Онлайн');

    IF cancel_violations > 0
        OR move_violations > 0
        OR replace_violations > 0
        OR format_violations > 0 THEN
        RAISE EXCEPTION USING
            ERRCODE = '23514',
            MESSAGE = format(
                'Невозможно применить инварианты точечных изменений: CANCEL=%s, MOVE=%s, REPLACE=%s, формат=%s. Исправьте данные tenant-БД и повторите миграцию.',
                cancel_violations,
                move_violations,
                replace_violations,
                format_violations
            );
    END IF;
END $$;

ALTER TABLE schedule_overrides
    ADD CONSTRAINT chk_schedule_overrides_cancel_payload
        CHECK (
            action <> 'CANCEL'
            OR (
                new_time_slot_id IS NULL
                AND new_classroom_id IS NULL
                AND new_teacher_id IS NULL
                AND new_lesson_format IS NULL
            )
        ) NOT VALID,
    ADD CONSTRAINT chk_schedule_overrides_move_payload
        CHECK (
            action <> 'MOVE'
            OR new_time_slot_id IS NOT NULL
            OR new_classroom_id IS NOT NULL
        ) NOT VALID,
    ADD CONSTRAINT chk_schedule_overrides_replace_payload
        CHECK (
            action <> 'REPLACE'
            OR new_teacher_id IS NOT NULL
            OR new_classroom_id IS NOT NULL
            OR new_lesson_format IS NOT NULL
        ) NOT VALID,
    ADD CONSTRAINT chk_schedule_overrides_format
        CHECK (
            new_lesson_format IS NULL
            OR new_lesson_format IN ('Очно', 'Онлайн')
        ) NOT VALID;

ALTER TABLE schedule_overrides
    VALIDATE CONSTRAINT chk_schedule_overrides_cancel_payload;

ALTER TABLE schedule_overrides
    VALIDATE CONSTRAINT chk_schedule_overrides_move_payload;

ALTER TABLE schedule_overrides
    VALIDATE CONSTRAINT chk_schedule_overrides_replace_payload;

ALTER TABLE schedule_overrides
    VALIDATE CONSTRAINT chk_schedule_overrides_format;
