defmodule Berrypod.Repo.Migrations.CreateActivityLog do
  use Ecto.Migration

  def up do
    create table(:activity_log, primary_key: false) do
      add :id, :binary_id, primary_key: true
      add :event_type, :string, null: false
      add :level, :string, null: false, default: "info"
      add :order_id, references(:orders, type: :binary_id, on_delete: :nilify_all)
      add :payload, :map, default: %{}
      add :message, :string, null: false
      add :resolved_at, :utc_datetime
      add :occurred_at, :utc_datetime, null: false

      timestamps(type: :utc_datetime)
    end

    create index(:activity_log, [:order_id])
    create index(:activity_log, [:occurred_at])
    create index(:activity_log, [:level, :resolved_at])

    # Backfill from existing orders
    flush()
    backfill_from_orders()
  end

  def down do
    drop table(:activity_log)
  end

  defp backfill_from_orders do
    now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)

    # order.created for all paid orders
    execute("""
    INSERT INTO activity_log (id, event_type, level, order_id, payload, message, occurred_at, inserted_at, updated_at)
    SELECT
      lower(hex(randomblob(4)) || '-' || hex(randomblob(2)) || '-4' || substr(hex(randomblob(2)),2) || '-' || substr('89ab', abs(random()) % 4 + 1, 1) || substr(hex(randomblob(2)),2) || '-' || hex(randomblob(6))),
      'order.created',
      'info',
      id,
      '{}',
      'Order placed',
      inserted_at,
      '#{now}',
      '#{now}'
    FROM orders
    WHERE payment_status = 'paid'
    """)

    # order.submitted
    execute("""
    INSERT INTO activity_log (id, event_type, level, order_id, payload, message, occurred_at, inserted_at, updated_at)
    SELECT
      lower(hex(randomblob(4)) || '-' || hex(randomblob(2)) || '-4' || substr(hex(randomblob(2)),2) || '-' || substr('89ab', abs(random()) % 4 + 1, 1) || substr(hex(randomblob(2)),2) || '-' || hex(randomblob(6))),
      'order.submitted',
      'info',
      id,
      '{}',
      'Submitted to provider',
      submitted_at,
      '#{now}',
      '#{now}'
    FROM orders
    WHERE submitted_at IS NOT NULL
    """)

    # order.shipped
    execute("""
    INSERT INTO activity_log (id, event_type, level, order_id, payload, message, occurred_at, inserted_at, updated_at)
    SELECT
      lower(hex(randomblob(4)) || '-' || hex(randomblob(2)) || '-4' || substr(hex(randomblob(2)),2) || '-' || substr('89ab', abs(random()) % 4 + 1, 1) || substr(hex(randomblob(2)),2) || '-' || hex(randomblob(6))),
      'order.shipped',
      'info',
      id,
      '{}',
      'Shipped',
      shipped_at,
      '#{now}',
      '#{now}'
    FROM orders
    WHERE shipped_at IS NOT NULL
    """)

    # order.delivered
    execute("""
    INSERT INTO activity_log (id, event_type, level, order_id, payload, message, occurred_at, inserted_at, updated_at)
    SELECT
      lower(hex(randomblob(4)) || '-' || hex(randomblob(2)) || '-4' || substr(hex(randomblob(2)),2) || '-' || substr('89ab', abs(random()) % 4 + 1, 1) || substr(hex(randomblob(2)),2) || '-' || hex(randomblob(6))),
      'order.delivered',
      'info',
      id,
      '{}',
      'Delivered',
      delivered_at,
      '#{now}',
      '#{now}'
    FROM orders
    WHERE delivered_at IS NOT NULL
    """)
  end
end
