-- Saga Manager (Sprint 4-6). Coordoneaza procese cu mai multi pasi care nu
-- incap intr-o tranzactie. Garantia nu e atomicitatea, ci compensarea in
-- ordine inversa a pasilor deja executati.

DO $$ BEGIN
  CREATE TYPE "saga_status" AS ENUM
    ('RUNNING','COMPLETED','COMPENSATING','COMPENSATED','FAILED','TIMED_OUT');
EXCEPTION WHEN duplicate_object THEN NULL; END $$;

DO $$ BEGIN
  CREATE TYPE "saga_step_status" AS ENUM
    ('PENDING','RUNNING','COMPLETED','FAILED','COMPENSATED','SKIPPED');
EXCEPTION WHEN duplicate_object THEN NULL; END $$;

CREATE TABLE IF NOT EXISTS "saga_instances" (
  "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
  "tenant_id" uuid NOT NULL,
  "workspace_id" uuid,
  "saga_name" text NOT NULL,
  "saga_version" integer NOT NULL,
  "status" "saga_status" DEFAULT 'RUNNING' NOT NULL,
  "current_step" integer DEFAULT 0 NOT NULL,
  "trigger_event_id" uuid NOT NULL,
  "correlation_id" uuid,
  "context" jsonb DEFAULT '{}'::jsonb NOT NULL,
  "attempt" integer DEFAULT 0 NOT NULL,
  "next_attempt_at" timestamp DEFAULT now() NOT NULL,
  "timeout_at" timestamp,
  "last_error" text,
  "locked_until" timestamp,
  "created_at" timestamp DEFAULT now() NOT NULL,
  "updated_at" timestamp DEFAULT now() NOT NULL,
  "completed_at" timestamp
);

-- Un eveniment porneste o singura instanta dintr-o saga data. Aceasta
-- constrangere e ce face pornirea idempotenta, nu o verificare in cod.
CREATE UNIQUE INDEX IF NOT EXISTS "saga_trigger_uq"
  ON "saga_instances" ("saga_name","saga_version","trigger_event_id");
CREATE INDEX IF NOT EXISTS "saga_due_idx"
  ON "saga_instances" ("status","next_attempt_at");
CREATE INDEX IF NOT EXISTS "saga_tenant_idx"
  ON "saga_instances" ("tenant_id","created_at");

CREATE TABLE IF NOT EXISTS "saga_steps" (
  "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
  "saga_instance_id" uuid NOT NULL,
  "step_name" text NOT NULL,
  "sequence" integer NOT NULL,
  "status" "saga_step_status" DEFAULT 'PENDING' NOT NULL,
  "attempts" integer DEFAULT 0 NOT NULL,
  "output" jsonb,
  "last_error" text,
  "started_at" timestamp,
  "completed_at" timestamp,
  "compensated_at" timestamp
);

-- Un pas apare o singura data per instanta: baza idempotentei la avans.
CREATE UNIQUE INDEX IF NOT EXISTS "saga_step_uq"
  ON "saga_steps" ("saga_instance_id","sequence");
