use sea_orm_migration::prelude::*;
use sea_orm_migration::sea_query::table::ColumnDef;

#[derive(DeriveMigrationName)]
pub struct Migration;

#[async_trait::async_trait]
impl MigrationTrait for Migration {
    async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
        // create a table for rpc request accounting
        manager
            .create_table(
                Table::create()
                    .table(RpcAccounting::Table)
                    .col(
                        ColumnDef::new(RpcAccounting::Id)
                            .big_unsigned()
                            .not_null()
                            .auto_increment()
                            .primary_key(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::UserKeyId)
                            .big_unsigned()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::ChainId)
                            .big_unsigned()
                            .not_null(),
                    )
                    .col(ColumnDef::new(RpcAccounting::Method).string().not_null())
                    .col(
                        ColumnDef::new(RpcAccounting::ErrorResponse)
                            .boolean()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::PeriodDatetime)
                            .timestamp()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::FrontendRequests)
                            .big_unsigned()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::BackendRequests)
                            .big_unsigned()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::BackendRetries)
                            .big_unsigned()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::NoServers)
                            .big_unsigned()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::CacheMisses)
                            .big_unsigned()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::CacheHits)
                            .big_unsigned()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::SumRequestBytes)
                            .big_unsigned()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::MinRequestBytes)
                            .big_unsigned()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::MeanRequestBytes)
                            .double()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::P50RequestBytes)
                            .big_unsigned()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::P90RequestBytes)
                            .big_unsigned()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::P99RequestBytes)
                            .big_unsigned()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::MaxRequestBytes)
                            .big_unsigned()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::SumResponseMillis)
                            .big_unsigned()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::MinResponseMillis)
                            .big_unsigned()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::MeanResponseMillis)
                            .double()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::P50ResponseMillis)
                            .big_unsigned()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::P90ResponseMillis)
                            .big_unsigned()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::P99ResponseMillis)
                            .big_unsigned()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::MaxResponseMillis)
                            .big_unsigned()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::SumResponseBytes)
                            .big_unsigned()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::MinResponseBytes)
                            .big_unsigned()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::MeanResponseBytes)
                            .double()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::P50ResponseBytes)
                            .big_unsigned()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::P90ResponseBytes)
                            .big_unsigned()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::P99ResponseBytes)
                            .big_unsigned()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(RpcAccounting::MaxResponseBytes)
                            .big_unsigned()
                            .not_null(),
                    )
                    .foreign_key(
                        sea_query::ForeignKey::create()
                            .from(RpcAccounting::Table, RpcAccounting::UserKeyId)
                            .to(UserKeys::Table, UserKeys::Id),
                    )
                    .index(sea_query::Index::create().col(RpcAccounting::PeriodDatetime))
                    .index(sea_query::Index::create().col(RpcAccounting::Method))
                    .to_owned(),
            )
            .await
    }

    async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
        manager
            .drop_table(Table::drop().table(RpcAccounting::Table).to_owned())
            .await
    }
}

/// Partial table definition
#[derive(Iden)]
pub enum UserKeys {
    Table,
    Id,
}

#[derive(Iden)]
enum RpcAccounting {
    Table,
    Id,
    UserKeyId,
    ChainId,
    Method,
    ErrorResponse,
    PeriodDatetime,
    FrontendRequests,
    BackendRequests,
    BackendRetries,
    NoServers,
    CacheMisses,
    CacheHits,
    SumRequestBytes,
    MinRequestBytes,
    MeanRequestBytes,
    P50RequestBytes,
    P90RequestBytes,
    P99RequestBytes,
    MaxRequestBytes,
    SumResponseMillis,
    MinResponseMillis,
    MeanResponseMillis,
    P50ResponseMillis,
    P90ResponseMillis,
    P99ResponseMillis,
    MaxResponseMillis,
    SumResponseBytes,
    MinResponseBytes,
    MeanResponseBytes,
    P50ResponseBytes,
    P90ResponseBytes,
    P99ResponseBytes,
    MaxResponseBytes,
}
