<?php

namespace HelpGent\App\BackgroundServices;

defined( 'ABSPATH' ) || exit;

use Exception;
use HelpGent\App\BackgroundProcessors\BackgroundProcessor;
use HelpGent\App\EnumeratedList\AttachmentTransferQueueType;
use HelpGent\App\DTO\AttachmentDTO;
use HelpGent\App\DTO\AttachmentTransferQueueDTO;
use HelpGent\App\Models\Attachment as AttachmentModel;
use HelpGent\App\Models\AttachmentTransferQueue as AttachmentTransferQueueModel;
use HelpGent\App\MediaDriverMigration\Migrator;

class MediaMigrationService extends BackgroundService {
    public function boot(): void {
        $this->background_processor = new BackgroundProcessor( 'media_migration' );
    }

    public static function migrate_media( array $args = [] ): bool {
        $from = $args['from'];
        $to   = $args['to'];

        $queue_type = AttachmentTransferQueueType::MIGRATION;

        // Attachment
        $attachment_data = AttachmentModel::query( 'attachment' )
            ->select( 
                [ 
                    'attachment.*',
                    'queue.id as queue_id',
                    'queue.type',
                    'queue.transfer_from',
                    'queue.transfer_to',
                    'queue.transfer_next',
                    'queue.upload_id as queue_upload_id',
                    'queue.upload_token as queue_upload_token',
                    'queue.message',
                    'queue.status as queue_status',
                ] 
            )
            ->left_join( AttachmentTransferQueueModel::get_table_name() . " as queue", 'queue.attachment_id', 'attachment.id' )
            ->where( 'attachment.storage', $from )
            ->where_raw( "( queue.type = '{$queue_type}' OR queue.type IS null )" )
            ->where_raw( "( queue.status IN ( 'transferring', 'in_queue' ) OR queue.status IS null )" )
            ->order_by_raw( 'CASE WHEN queue.status = "transferring" THEN 1 WHEN queue.status = "in_queue" THEN 2 WHEN queue.status IS null THEN 3 END ASC' )
            ->first();

        if ( empty( $attachment_data ) ) {
            return false;
        }

        /**
         * @var Migrator $migrator
         */
        $migrator = helpgent_singleton( Migrator::class );

        if ( null === $attachment_data->type ) {
            $attachment = ( new AttachmentDTO() )
                ->set_title( $attachment_data->title )
                ->set_mime_type( $attachment_data->mime_type )
                ->set_file_size( $attachment_data->file_size )
                ->set_storage( $attachment_data->storage )
                ->set_id( $attachment_data->id )
                ->set_file_id( $attachment_data->file_id )
                ->set_upload_token( $attachment_data->upload_token );

            try {
                $queue_item = $migrator->add_to_transfer_queue( $queue_type, $attachment, $to );

                $attachment_data->queue_id           = $queue_item->get_id();
                $attachment_data->type               = $queue_item->get_type();
                $attachment_data->transfer_from      = $queue_item->get_transfer_from();
                $attachment_data->transfer_to        = $queue_item->get_transfer_to();
                $attachment_data->transfer_next      = $queue_item->get_transfer_next();
                $attachment_data->queue_upload_token = $queue_item->get_upload_token();
                $attachment_data->queue_upload_id    = $queue_item->get_upload_id();
                $attachment_data->queue_status       = $queue_item->get_status();
            } catch ( Exception $e ) {
                return true;
            }
        }

        $attachment_transfer_queue = ( new AttachmentTransferQueueDTO() )
            ->set_id( $attachment_data->queue_id )
            ->set_type( $attachment_data->type )
            ->set_attachment_id( $attachment_data->id )
            ->set_transfer_from( $attachment_data->transfer_from )
            ->set_transfer_to( $attachment_data->transfer_to )
            ->set_transfer_next( $attachment_data->transfer_next )
            ->set_upload_id( $attachment_data->queue_upload_id )
            ->set_upload_token( $attachment_data->queue_upload_token )
            ->set_status( $attachment_data->queue_status )
            ->set_message( $attachment_data->message );

        try {
            $migrator->transfer_from_queue( $attachment_transfer_queue );
        } catch ( Exception $e ) {
        }

        return true;
    }

    public function add_migration_task( array $route = [] ): self {
        helpgent_option()->update( 'helpgent_media_migration_route', $route );

        return $this->add_task( [ $this, 'migrate_media' ], $route );
    }

    public static function get_route() {
        return helpgent_option()->get_by_name( 'helpgent_media_migration_route' );
    }

    public function is_cancelled(): bool {
        return $this->background_process->is_cancelled();
    }

    public function status(): string {
        return $this->background_process->status();
    }

    public function after_complete_migration(): void {
        helpgent_option()->delete( 'helpgent_media_migration_route' );
    }
}