-- Tablas para el seguimiento de las operaciones de SIM sin importar
-- la cmpañia.

CREATE TYPE order_types AS ENUM ('activate','preactivate','cancel','pause','reactivate','unknown');
CREATE TYPE order_status AS ENUM (
    'pending',      -- Mensaje creado/enviado a RabbitMQ
    'running',      -- Consumidor ha cogido el mensaje (opcional)
    'finished',    -- Procesado correctamente
    'failed',       -- Falló, pero podría reintentarse (Pasar a delay?)
    'dlx'           -- Falló definitivamente y está en Dead Letter Exchange
);

CREATE TABLE IF NOT EXISTS order_tracking (
    id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
    correlation_id VARCHAR(255) NOT NULL,                    -- ID compartido con RabbitMQ (message_id)
    exchange VARCHAR(100),                                   -- Exchange al que se envia (de momento solo hay 1 principal sin contar delay y dlx)
    routing_key VARCHAR(100),                                -- Routing key del mensaje
    order_type order_types NOT NULL DEFAULT 'unknown',

    payload JSONB,                                          -- Duda si es optimo guardar la copia, es útil en caso de fallo
    
    -- Campos de reintentos?

    status order_status NOT NULL DEFAULT 'pending',
    retry_count INT DEFAULT 0,
    error_message TEXT,                                      -- Razón del fallo
    error_stacktrace TEXT,
    
    start_date        TIMESTAMP NOT NULL DEFAULT (now() at time zone 'utc'),
    update_date       TIMESTAMP NOT NULL DEFAULT (now() at time zone 'utc'),
    finish_date     TIMESTAMP
);

-- Busqueda según id de rabbit
CREATE INDEX IF NOT EXISTS idx_order_correlation 
  ON order_tracking(correlation_id);
-- Ordenenes que todavia no han finalizado
CREATE INDEX IF NOT EXISTS pending_orders
  ON order_tracking(start_date)
  WHERE order_tracking.finish_date IS NULL;

CREATE TABLE IF NOT EXISTS order_history(
    id                            BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
    order_id                      BIGINT NOT NULL,
    previous_status               order_status NOT NULL, -- Siempre hay un estado anterior, para casos excepcioneale "unknown"
    new_status                    order_status NOT NULL, 
    change_reason                 TEXT, 
    change_date                   TIMESTAMP NOT NULL DEFAULT (now() at time zone 'utc'),

    CONSTRAINT fk_order_id
        FOREIGN KEY(order_id) 
        REFERENCES order_tracking(id)
        ON DELETE CASCADE
);

-- fk de order
CREATE INDEX IF NOT EXISTS idx_order_id
  ON order_history(order_id);

-- busquedas por fecha
CREATE INDEX IF NOT EXISTS idx_order_change_date 
  ON order_history(change_date);


CREATE TYPE status_enum AS ENUM ('noRequestID','noMassID','running','finished','error','other');

-- Tabla para gestionar las peticiones de cambio de objenious.
-- Para una o mas lineas se pueden lanzar operacione que no sabemos
-- con certeza cuando van a terminar.
-- Estas tablas está fuertemente ligadas al sistema que usa la plataforma
-- de objenioius y no debe unsarse para otra compañia.
CREATE TABLE if not exists objenious_operation (
    id                BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
    retry_count       INT DEFAULT 0, -- No implementado en codigo
    max_retry         INT DEFAULT 5, -- No implementado en codigo
    max_date_retry    TIMESTAMP DEFAULT NULL, -- No implementado en codigo
    iccids            TEXT,
    request_id        TEXT,
    mass_action_id    TEXT,
    operation         TEXT NOT NULL,
    start_date        TIMESTAMP NOT NULL DEFAULT now(), 
    last_change_date  TIMESTAMP NOT NULL DEFAULT now(),
    end_date          TIMESTAMP,
    error             TEXT,
    status            status_enum,
    objenious_status  TEXT
);

-- operaciones pendientes para revisar
CREATE INDEX IF NOT EXISTS pending_operations
  ON objenious_operation(start_date)
WHERE end_date IS NULL;

CREATE TABLE if not exists objenious_operation_change (
    id                    BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
    operation_id          BIGINT,
    creation_date         TIMESTAMP NOT NULL DEFAULT now(),
    error                 TEXT,
    new_status            status_enum,
    previous_status       status_enum,
    new_objenious_status  TEXT,
    previous_objenious_status  TEXT,
    new_request_id        TEXT,
    new_mass_action_id    TEXT,

    CONSTRAINT fk_operation_id
        FOREIGN KEY(operation_id) REFERENCES objenious_operation(id)
);

CREATE INDEX operation_change
  ON objenious_operation_change(operation_id);
CREATE TABLE IF NOT EXISTS db_versions (
  version         TEXT PRIMARY KEY, -- version semantica x.x.x
  notes           TEXT,
  creation_date   TIMESTAMP NOT NULL DEFAULT (now() at time zone 'utc'),
  stable          BOOLEAN DEFAULT FALSE -- Si la version ha sido testada y se puede desplegar
);

INSERT INTO db_versions (
  version,
  notes
)
VALUES (
  '0.1.0',
  'Versión base'
);
