# Copyright (c) 2016 Mirantis Inc.
# All Rights Reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.


"""Init migration

Revision ID: ca3626f62937
Revises:
Create Date: 2016-01-07 00:27:39.687814

"""

import typing as t

from alembic import op
import sqlalchemy as sa

from rally import exceptions
from rally.common.db import api
from rally.common.db import sa_types


if t.TYPE_CHECKING:
    import sqlalchemy.schema


# revision identifiers, used by Alembic.
revision = "ca3626f62937"
down_revision = None
branch_labels = None
depends_on = None


def upgrade() -> None:
    dialect = api.get_engine().dialect

    deployments_columns: list[sa.schema.SchemaItem] = [
        sa.Column("created_at", sa.DateTime(), nullable=True),
        sa.Column("updated_at", sa.DateTime(), nullable=True),
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("uuid", sa.String(length=36), nullable=False),
        sa.Column("parent_uuid", sa.String(length=36), nullable=True),
        sa.Column("name", sa.String(length=255), nullable=True),
        sa.Column("started_at", sa.DateTime(), nullable=True),
        sa.Column("completed_at", sa.DateTime(), nullable=True),
        sa.Column("config", sa_types.MutableJSONEncodedDict(), nullable=False),
        sa.Column("admin", sa.PickleType(), nullable=True),
        sa.Column("users", sa.PickleType(), nullable=False),
        sa.Column(
            "enum_deployments_status",
            sa.Enum(
                "cleanup->failed",
                "cleanup->finished",
                "cleanup->started",
                "deploy->failed",
                "deploy->finished",
                "deploy->inconsistent",
                "deploy->init",
                "deploy->started",
                "deploy->subdeploy",
                name="enum_deploy_status",
            ),
            nullable=False,
        ),
        sa.PrimaryKeyConstraint("id"),
        sa.UniqueConstraint("name"),
    ]

    if dialect.name.startswith("sqlite"):
        deployments_columns.append(
            sa.ForeignKeyConstraint(
                ["parent_uuid"],
                ["deployments.uuid"],
                name="fk_parent_uuid",
                use_alter=True,
            )
        )

    # commands auto generated by Alembic - please adjust!
    op.create_table("deployments", *deployments_columns)

    op.create_index(
        "deployment_parent_uuid", "deployments", ["parent_uuid"], unique=False
    )

    op.create_index("deployment_uuid", "deployments", ["uuid"], unique=True)

    if not dialect.name.startswith("sqlite"):
        op.create_foreign_key(
            "fk_parent_uuid",
            "deployments",
            "deployments",
            ["parent_uuid"],
            ["uuid"],
        )

    op.create_table(
        "workers",
        sa.Column("created_at", sa.DateTime(), nullable=True),
        sa.Column("updated_at", sa.DateTime(), nullable=True),
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("hostname", sa.String(length=255), nullable=True),
        sa.PrimaryKeyConstraint("id"),
        sa.UniqueConstraint("hostname", name="uniq_worker@hostname"),
    )

    op.create_table(
        "resources",
        sa.Column("created_at", sa.DateTime(), nullable=True),
        sa.Column("updated_at", sa.DateTime(), nullable=True),
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("provider_name", sa.String(length=255), nullable=True),
        sa.Column("type", sa.String(length=255), nullable=True),
        sa.Column("info", sa_types.MutableJSONEncodedDict(), nullable=False),
        sa.Column("deployment_uuid", sa.String(length=36), nullable=False),
        sa.ForeignKeyConstraint(["deployment_uuid"], ["deployments.uuid"]),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        "resource_deployment_uuid",
        "resources",
        ["deployment_uuid"],
        unique=False,
    )

    op.create_index(
        "resource_provider_name",
        "resources",
        ["deployment_uuid", "provider_name"],
        unique=False,
    )

    op.create_index(
        "resource_provider_name_and_type",
        "resources",
        ["deployment_uuid", "provider_name", "type"],
        unique=False,
    )

    op.create_index(
        "resource_type", "resources", ["deployment_uuid", "type"], unique=False
    )

    op.create_table(
        "tasks",
        sa.Column("created_at", sa.DateTime(), nullable=True),
        sa.Column("updated_at", sa.DateTime(), nullable=True),
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("uuid", sa.String(length=36), nullable=False),
        sa.Column(
            "status",
            sa.Enum(
                "aborted",
                "aborting",
                "cleaning up",
                "failed",
                "finished",
                "init",
                "paused",
                "running",
                "setting up",
                "soft_aborting",
                "verifying",
                name="enum_tasks_status",
            ),
            nullable=False,
        ),
        sa.Column("verification_log", sa.Text(), nullable=True),
        sa.Column("tag", sa.String(length=64), nullable=True),
        sa.Column("deployment_uuid", sa.String(length=36), nullable=False),
        sa.ForeignKeyConstraint(
            ["deployment_uuid"],
            ["deployments.uuid"],
        ),
        sa.PrimaryKeyConstraint("id"),
    )

    op.create_index(
        "task_deployment", "tasks", ["deployment_uuid"], unique=False
    )

    op.create_index("task_status", "tasks", ["status"], unique=False)

    op.create_index("task_uuid", "tasks", ["uuid"], unique=True)

    op.create_table(
        "verifications",
        sa.Column("created_at", sa.DateTime(), nullable=True),
        sa.Column("updated_at", sa.DateTime(), nullable=True),
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("uuid", sa.String(length=36), nullable=False),
        sa.Column("deployment_uuid", sa.String(length=36), nullable=False),
        sa.Column(
            "status",
            sa.Enum(
                "aborted",
                "aborting",
                "cleaning up",
                "failed",
                "finished",
                "init",
                "paused",
                "running",
                "setting up",
                "soft_aborting",
                "verifying",
                name="enum_tasks_status",
            ),
            nullable=False,
        ),
        sa.Column("set_name", sa.String(length=20), nullable=True),
        sa.Column("tests", sa.Integer(), nullable=True),
        sa.Column("errors", sa.Integer(), nullable=True),
        sa.Column("failures", sa.Integer(), nullable=True),
        sa.Column("time", sa.Float(), nullable=True),
        sa.ForeignKeyConstraint(
            ["deployment_uuid"],
            ["deployments.uuid"],
        ),
        sa.PrimaryKeyConstraint("id"),
    )

    op.create_index(
        "verification_uuid", "verifications", ["uuid"], unique=True
    )

    op.create_table(
        "task_results",
        sa.Column("created_at", sa.DateTime(), nullable=True),
        sa.Column("updated_at", sa.DateTime(), nullable=True),
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("key", sa_types.MutableJSONEncodedDict(), nullable=False),
        sa.Column("data", sa_types.MutableJSONEncodedDict(), nullable=False),
        sa.Column("task_uuid", sa.String(length=36), nullable=True),
        sa.ForeignKeyConstraint(
            ["task_uuid"],
            ["tasks.uuid"],
        ),
        sa.PrimaryKeyConstraint("id"),
    )

    op.create_table(
        "verification_results",
        sa.Column("created_at", sa.DateTime(), nullable=True),
        sa.Column("updated_at", sa.DateTime(), nullable=True),
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("verification_uuid", sa.String(length=36), nullable=True),
        sa.Column("data", sa_types.MutableJSONEncodedDict(), nullable=False),
        sa.ForeignKeyConstraint(["verification_uuid"], ["verifications.uuid"]),
        sa.PrimaryKeyConstraint("id"),
    )
    # end Alembic commands


def downgrade() -> None:
    raise exceptions.DowngradeNotSupported()
