defmodule WhoNeedHelp.Repo.Migrations.CreateActivityMode do
  use Ecto.Migration

  def change do
    alter table(:categories) do
      add :mode, :string, null: false, default: "help"
    end

    create index(:categories, [:mode, :active, :sort_order])

    alter table(:category_proposals) do
      add :mode, :string, null: false, default: "help"
    end

    create index(:category_proposals, [:mode, :status])

    create table(:activities, primary_key: false) do
      add :id, :binary_id, primary_key: true
      add :title, :string, null: false
      add :description, :text, null: false
      add :structured_data, :map, null: false, default: %{}
      add :location_label, :string, null: false
      add :location, :geometry, null: false
      add :location_visibility, :string, null: false, default: "approximate_public"
      add :status, :string, null: false, default: "open"
      add :starts_at, :utc_datetime, null: false
      add :join_deadline, :utc_datetime, null: false
      add :capacity, :integer, null: false
      add :cancelled_at, :utc_datetime
      add :completed_at, :utc_datetime
      add :hidden_at, :utc_datetime
      add :hidden_reason, :text
      add :creator_id, references(:users, type: :binary_id, on_delete: :restrict), null: false

      add :category_id, references(:categories, type: :binary_id, on_delete: :restrict),
        null: false

      timestamps(type: :utc_datetime)
    end

    create index(:activities, [:creator_id, :starts_at])
    create index(:activities, [:category_id, :status, :starts_at])
    create index(:activities, [:status, :hidden_at, :join_deadline])
    create index(:activities, [:location], using: :gist)
    create constraint(:activities, :activity_capacity_at_least_two, check: "capacity >= 2")

    create constraint(:activities, :activity_join_before_start,
             check: "join_deadline <= starts_at"
           )

    create table(:activity_participants, primary_key: false) do
      add :id, :binary_id, primary_key: true
      add :role, :string, null: false, default: "participant"
      add :status, :string, null: false, default: "requested"
      add :reviewed_at, :utc_datetime
      add :left_at, :utc_datetime

      add :activity_id, references(:activities, type: :binary_id, on_delete: :delete_all),
        null: false

      add :user_id, references(:users, type: :binary_id, on_delete: :restrict), null: false

      timestamps(type: :utc_datetime)
    end

    create unique_index(:activity_participants, [:activity_id, :user_id])
    create index(:activity_participants, [:user_id, :status])
    create index(:activity_participants, [:activity_id, :status])

    create table(:activity_messages, primary_key: false) do
      add :id, :binary_id, primary_key: true
      add :body, :text, null: false

      add :activity_id, references(:activities, type: :binary_id, on_delete: :delete_all),
        null: false

      add :sender_id, references(:users, type: :binary_id, on_delete: :restrict), null: false

      timestamps(type: :utc_datetime)
    end

    create index(:activity_messages, [:activity_id, :inserted_at])
  end
end
