<?php
/**
 * 事务
 * User: Administrator
 * Date: 2020/2/12 0012
 * Time: 22:32
 */

namespace EasySwoole\ORM\Tests;


use EasySwoole\Mysqli\QueryBuilder;
use EasySwoole\ORM\Db\ClientInterface;
use PHPUnit\Framework\TestCase;
use EasySwoole\ORM\Db\Config;
use EasySwoole\ORM\Db\Connection;
use EasySwoole\ORM\DbManager;


use EasySwoole\ORM\Tests\models\TestTimeStampModel;

class TransactionTest extends TestCase
{
    /**
     * @var $connection Connection
     */
    protected $connection;
    protected $tableName = 'user_test_list';

    protected function setUp(): void
    {
        parent::setUp(); // TODO: Change the autogenerated stub
        $config = new Config(MYSQL_CONFIG);
        $config->setMinObjectNum(1);
        $config->setMaxObjectNum(5);
        $this->connection = new Connection($config);
        DbManager::getInstance()->addConnection($this->connection);
        $connection = DbManager::getInstance()->getConnection();
        $this->assertTrue($connection === $this->connection);
    }

    /**
     * @throws \EasySwoole\ORM\Exception\Exception
     * @throws \EasySwoole\Pool\Exception\PoolEmpty
     * @throws \Throwable
     */
    public function testInvoke()
    {
        TestTimeStampModel::create()->destroy([], true);
        DbManager::getInstance()->invoke(function ($client) {
            DbManager::getInstance()->startTransaction($client);
            $model = TestTimeStampModel::invoke($client);

            $model->name = 'siam';
            $model->age = 21;
            $model->save();
            $this->assertIsInt($model->id);

            DbManager::getInstance()->rollback($client);

            // 此时查找 为空
            $has = TestTimeStampModel::invoke($client)->get([
                'name' => 'siam'
            ]);
            $this->assertNull($has);
        });
        TestTimeStampModel::create()->destroy([], true);
    }

    public function testWhileCommit()
    {
        TestTimeStampModel::create()->destroy([], true);
        $i = $count = 10;
        $ids = [];
        while ($i--) {
            DbManager::getInstance()->startTransaction();
            $model = TestTimeStampModel::create();
            $model->name = 'siam';
            $model->age = 21;
            $model->save();
            $ids[] = $model->id;
            DbManager::getInstance()->commit();
        }

        $ret = TestTimeStampModel::create()->where('id', $ids, 'IN')->all();
        $this->assertEquals($count, count($ret));
        TestTimeStampModel::create()->destroy([], true);
    }

    public function testWhileCommitInvoke()
    {
        TestTimeStampModel::create()->destroy([], true);
        $i = $count = 10;
        while ($i--) {
            DbManager::getInstance()->invoke(function (ClientInterface $client) use (&$ids) {
                DbManager::getInstance()->startTransaction($client);
                $model = TestTimeStampModel::invoke($client);
                $model->name = 'siam';
                $model->age = 21;
                $model->save();
                $ids[] = $model->id;
                DbManager::getInstance()->commit($client);
            });
        }

        $ret = TestTimeStampModel::create()->where('id', $ids, 'IN')->all();
        $this->assertEquals($count, count($ret));
        TestTimeStampModel::create()->destroy([], true);
    }

    public function testWhileRollback()
    {
        TestTimeStampModel::create()->destroy([], true);
        $i = $count = 10;
        $ids = [];
        while ($i--) {
            try {
                DbManager::getInstance()->startTransaction();
                $model = TestTimeStampModel::create();
                $model->name = 'siam';
                $model->age = 21;
                $model->save();
                $ids[] = $model->id;

                $builder = new QueryBuilder();
                $builder->insert('tiamstamp_test', ['a' => 1]);
                DbManager::getInstance()->query($builder, true);
                DbManager::getInstance()->commit();
            } catch (\Throwable $throwable) {
                try {
                    DbManager::getInstance()->rollback();
                } catch (\Throwable $throwable) {
                }
            }
        }

        $ret = TestTimeStampModel::create()->where('id', $ids, 'IN')->all();
        $this->assertEquals(0, count($ret));
        TestTimeStampModel::create()->destroy([], true);
    }

    public function testWhileRollbackInvoke()
    {
        $i = $count = 10;
        while ($i--) {
            DbManager::getInstance()->invoke(function ($client) use (&$ids) {
                try {
                    DbManager::getInstance()->startTransaction($client);
                    $model = TestTimeStampModel::invoke($client);
                    $model->name = 'siam';
                    $model->age = 21;
                    $model->save();
                    $ids[] = $model->id;

                    $builder = new QueryBuilder();
                    $builder->insert('tiamstamp_test', ['a' => 1]);
                    DbManager::getInstance()->query($builder, true, $client);
                    DbManager::getInstance()->commit($client);
                } catch (\Throwable $throwable) {
                    try {
                        DbManager::getInstance()->rollback($client);
                    } catch (\Throwable $throwable) {
                    }
                }
            });
        }

        $ret = TestTimeStampModel::create()->where('id', $ids, 'IN')->all();
        $this->assertEquals(0, count($ret));
        TestTimeStampModel::create()->destroy([], true);
    }

}