use loco_rs::schema::*;
use sea_orm_migration::prelude::*;

#[derive(DeriveMigrationName)]
pub struct Migration;

#[async_trait::async_trait]
impl MigrationTrait for Migration {
    async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
        create_table(
            manager,
            "worker_jobs",
            &[
                ("id", ColType::PkAuto),
                ("parent_job_id", ColType::IntegerNull),
                ("job_kind", ColType::String),
                ("worker_name", ColType::String),
                ("display_name", ColType::StringNull),
                ("status", ColType::String),
                ("queue_name", ColType::StringNull),
                ("requested_by", ColType::StringNull),
                ("requested_source", ColType::StringNull),
                ("trigger_mode", ColType::StringNull),
                ("payload", ColType::JsonBinaryNull),
                ("result", ColType::JsonBinaryNull),
                ("error_text", ColType::TextNull),
                ("tags", ColType::JsonBinaryNull),
                ("related_entity_type", ColType::StringNull),
                ("related_entity_id", ColType::StringNull),
                ("attempts_count", ColType::Integer),
                ("max_attempts", ColType::Integer),
                ("cancel_requested", ColType::Boolean),
                ("queued_at", ColType::StringNull),
                ("started_at", ColType::StringNull),
                ("finished_at", ColType::StringNull),
            ],
            &[],
        )
        .await?;

        for (name, columns) in [
            (
                "idx_worker_jobs_status_created_at",
                vec![Alias::new("status"), Alias::new("created_at")],
            ),
            (
                "idx_worker_jobs_worker_status_created_at",
                vec![
                    Alias::new("worker_name"),
                    Alias::new("status"),
                    Alias::new("created_at"),
                ],
            ),
            (
                "idx_worker_jobs_kind_created_at",
                vec![Alias::new("job_kind"), Alias::new("created_at")],
            ),
            (
                "idx_worker_jobs_related_entity",
                vec![Alias::new("related_entity_type"), Alias::new("related_entity_id")],
            ),
            (
                "idx_worker_jobs_parent_job_id",
                vec![Alias::new("parent_job_id")],
            ),
        ] {
            let mut statement = Index::create();
            statement.name(name).table(Alias::new("worker_jobs"));
            for column in columns {
                statement.col(column);
            }
            manager.create_index(statement.to_owned()).await?;
        }

        Ok(())
    }

    async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
        for index_name in [
            "idx_worker_jobs_parent_job_id",
            "idx_worker_jobs_related_entity",
            "idx_worker_jobs_kind_created_at",
            "idx_worker_jobs_worker_status_created_at",
            "idx_worker_jobs_status_created_at",
        ] {
            manager
                .drop_index(
                    Index::drop()
                        .name(index_name)
                        .table(Alias::new("worker_jobs"))
                        .to_owned(),
                )
                .await?;
        }

        drop_table(manager, "worker_jobs").await
    }
}
