use sea_orm_migration::{prelude::*, schema::*};

#[derive(DeriveMigrationName)]
pub struct Migration;

#[async_trait::async_trait]
impl MigrationTrait for Migration {
    async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
        // --- repos ---
        manager
            .create_table(
                Table::create()
                    .table(Repos::Table)
                    .if_not_exists()
                    .col(pk_auto(Repos::Id))
                    .col(string_uniq(Repos::Slug))
                    .col(
                        string(Repos::Provider)
                            .check(Expr::cust("provider IN ('github', 'bitbucket')")),
                    )
                    .col(string(Repos::Workspace))
                    .col(string(Repos::TargetBranch).default("develop"))
                    .col(string_null(Repos::DeveloperFocus))
                    .col(string_null(Repos::CustomPrompt))
                    .col(string(Repos::Token).default(""))
                    .col(string(Repos::CreatedAt))
                    .to_owned(),
            )
            .await?;

        // --- tasks (Jira identity only) ---
        manager
            .create_table(
                Table::create()
                    .table(Tasks::Table)
                    .if_not_exists()
                    .col(pk_auto(Tasks::Id))
                    .col(string_uniq(Tasks::JiraKey))
                    .to_owned(),
            )
            .await?;

        // --- task_executions (work item + lifecycle + per-run metadata) ---
        manager
            .create_table(
                Table::create()
                    .table(TaskExecutions::Table)
                    .if_not_exists()
                    .col(pk_auto(TaskExecutions::Id))
                    .col(integer(TaskExecutions::TaskId))
                    .col(integer(TaskExecutions::RepoId))
                    .col(string(TaskExecutions::EngineType).default("claude_code"))
                    .col(string(TaskExecutions::Summary))
                    .col(string_null(TaskExecutions::Description))
                    .col(string_null(TaskExecutions::Assignee))
                    .col(string(TaskExecutions::Status).default("pending"))
                    .col(string_null(TaskExecutions::BranchName))
                    .col(string_null(TaskExecutions::PrUrl))
                    .col(string_null(TaskExecutions::ErrorMessage))
                    .col(string(TaskExecutions::FetchedAt))
                    .col(string_null(TaskExecutions::ProcessedAt))
                    .col(string_null(TaskExecutions::StartedAt))
                    .col(string_null(TaskExecutions::FinishedAt))
                    .foreign_key(
                        ForeignKey::create()
                            .name("fk_task_executions_task")
                            .from(TaskExecutions::Table, TaskExecutions::TaskId)
                            .to(Tasks::Table, Tasks::Id)
                            .on_delete(ForeignKeyAction::Cascade),
                    )
                    .foreign_key(
                        ForeignKey::create()
                            .name("fk_task_executions_repo")
                            .from(TaskExecutions::Table, TaskExecutions::RepoId)
                            .to(Repos::Table, Repos::Id)
                            .on_delete(ForeignKeyAction::Cascade),
                    )
                    .to_owned(),
            )
            .await?;

        manager
            .create_index(
                Index::create()
                    .name("idx_task_executions_task_id")
                    .table(TaskExecutions::Table)
                    .col(TaskExecutions::TaskId)
                    .to_owned(),
            )
            .await?;

        Ok(())
    }

    async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
        manager
            .drop_table(Table::drop().table(TaskExecutions::Table).to_owned())
            .await?;
        manager
            .drop_table(Table::drop().table(Tasks::Table).to_owned())
            .await?;
        manager
            .drop_table(Table::drop().table(Repos::Table).to_owned())
            .await?;
        Ok(())
    }
}

#[derive(DeriveIden)]
enum Tasks {
    Table,
    Id,
    JiraKey,
}

#[derive(DeriveIden)]
enum Repos {
    Table,
    Id,
    Slug,
    Provider,
    Workspace,
    TargetBranch,
    DeveloperFocus,
    CustomPrompt,
    Token,
    CreatedAt,
}

#[derive(DeriveIden)]
enum TaskExecutions {
    Table,
    Id,
    TaskId,
    RepoId,
    EngineType,
    Summary,
    Description,
    Assignee,
    Status,
    BranchName,
    PrUrl,
    ErrorMessage,
    FetchedAt,
    ProcessedAt,
    StartedAt,
    FinishedAt,
}
