<?php

namespace CrowdinApiClient\Tests\Api;

use CrowdinApiClient\Model\DownloadFile;
use CrowdinApiClient\Model\Task;
use CrowdinApiClient\Model\TaskForUpdate;
use CrowdinApiClient\Model\TaskSettingsTemplate;
use CrowdinApiClient\ModelCollection;

class TaskApiTest extends AbstractTestApi
{
    public function testList()
    {
        $this->mockRequest([
            'path' => '/projects/2/tasks',
            'method' => 'get',
            'response' => json_encode([
                'data' => [
                    [
                        'data' => [
                            'id' => 2,
                            'projectId' => 2,
                            'creatorId' => 6,
                            'type' => 1,
                            'vendor' => null,
                            'status' => 'todo',
                            'title' => 'French',
                            'assignees' => [
                                [
                                    'id' => 1,
                                    'wordsCount' => 5,
                                ],
                            ],
                            'fileIds' => [1],
                            'progress' => [
                                'total' => 24,
                                'done' => 15,
                                'percent' => 62,
                            ],
                            'sourceLanguageId' => 'en',
                            'targetLanguageId' => 'fr',
                            'description' => 'Proofread all French strings',
                            'hash' => 'dac37aff364d83899128e68afe0de4994',
                            'translationUrl' => '/proofread/9092638ac9f2a2d1b5571d08edc53763/all/en-fr/10?task=dac37aff364d83899128e68afe0de4994',
                            'wordsCount' => 24,
                            'filesCount' => 2,
                            'commentsCount' => 0,
                            'deadline' => '2019-09-27T07:00:14+00:00',
                            'timeRange' => 'string',
                            'workflowStepId' => 10,
                            'buyUrl' => null,
                            'createdAt' => '2019-09-23T09:04:29+00:00',
                            'updatedAt' => '2019-09-23T09:04:29+00:00',
                        ],
                    ],
                ],
                'pagination' => [
                    [
                        'offset' => 0,
                        'limit' => 0,
                    ],
                ],
            ]),
        ]);

        $tasks = $this->crowdin->task->list(2);
        $this->assertInstanceOf(ModelCollection::class, $tasks);
        $this->assertCount(1, $tasks);
        $this->assertInstanceOf(Task::class, $tasks[0]);
        $this->assertEquals(2, $tasks[0]->getId());
        $this->assertEquals(null, $tasks[0]->getBuyUrl());
    }

    public function testCreate()
    {
        $params = [
            'title' => 'string',
            'languageId' => 'es',
            'fileIds' => [0],
            'type' => 0,
            'status' => 'todo',
            'description' => 'string',
            'splitFiles' => false,
            'assignees' => [
                [
                    'id' => 0,
                    'wordsCount' => 0,
                ],
            ],
            'deadline' => '2100-12-31T23:59:59+00:00',
            'dateFrom' => '2100-12-31T23:59:59+00:00',
            'dateTo' => '2100-12-31T23:59:59+00:00',
        ];

        $this->mockRequest([
            'path' => '/projects/2/tasks',
            'method' => 'post',
            'body' => json_encode($params),
            'response' => json_encode([
                'data' => [
                    'id' => 2,
                    'projectId' => 2,
                    'creatorId' => 6,
                    'type' => 1,
                    'status' => 'todo',
                    'title' => 'French',
                    'assignees' => [
                        [
                            'id' => 1,
                            'wordsCount' => 5,
                        ],
                    ],
                    'fileIds' => [1],
                    'progress' => [
                        'total' => 24,
                        'done' => 15,
                        'percent' => 62,
                    ],
                    'sourceLanguageId' => 'en',
                    'targetLanguageId' => 'fr',
                    'description' => 'Proofread all French strings',
                    'hash' => 'dac37aff364d83899128e68afe0de4994',
                    'translationUrl' => '/proofread/9092638ac9f2a2d1b5571d08edc53763/all/en-fr/10?task=dac37aff364d83899128e68afe0de4994',
                    'wordsCount' => 24,
                    'filesCount' => 2,
                    'commentsCount' => 0,
                    'deadline' => '2019-09-27T07:00:14+00:00',
                    'timeRange' => 'string',
                    'workflowStepId' => 10,
                    'createdAt' => '2019-09-23T09:04:29+00:00',
                    'updatedAt' => '2019-09-23T09:04:29+00:00',
                ],
            ]),
        ]);

        $task = $this->crowdin->task->create(2, $params);
        $this->assertInstanceOf(Task::class, $task);
        $this->assertEquals(2, $task->getId());
    }

    public function testGetAndUpdate()
    {
        $this->mockRequestGet(
            '/projects/2/tasks/2',
            json_encode([
                'data' => [
                    'id' => 2,
                    'projectId' => 2,
                    'creatorId' => 6,
                    'type' => 1,
                    'vendor' => 'gengo',
                    'status' => 'todo',
                    'title' => 'French',
                    'assignees' => [
                        [
                            'id' => 1,
                            'wordsCount' => 5,
                        ],
                    ],
                    'fileIds' => [1],
                    'labelIds' => [],
                    'progress' => [
                        'total' => 24,
                        'done' => 15,
                        'percent' => 62,
                    ],
                    'sourceLanguageId' => 'en',
                    'targetLanguageId' => 'fr',
                    'description' => 'Proofread all French strings',
                    'hash' => 'dac37aff364d83899128e68afe0de4994',
                    'translationUrl' => '/proofread/9092638ac9f2a2d1b5571d08edc53763/all/en-fr/10?task=dac37aff364d83899128e68afe0de4994',
                    'wordsCount' => 24,
                    'filesCount' => 2,
                    'commentsCount' => 0,
                    'deadline' => '2019-09-27T07:00:14+00:00',
                    'timeRange' => 'string',
                    'workflowStepId' => 10,
                    'createdAt' => '2019-09-23T09:04:29+00:00',
                    'updatedAt' => '2019-09-23T09:04:29+00:00',
                ],
            ])
        );

        $task = $this->crowdin->task->get(2, 2);

        $this->assertInstanceOf(Task::class, $task);
        $this->assertEquals(2, $task->getId());
        $this->assertEquals('gengo', $task->getVendor());

        $newTitle = 'New title';
        $newLabelIds = [1, 3];

        $this->mockRequestPatch(
            '/projects/2/tasks/2',
            json_encode([
                'data' => [
                    'id' => 2,
                    'projectId' => 2,
                    'creatorId' => 6,
                    'type' => 1,
                    'vendor' => 'gengo',
                    'status' => 'todo',
                    'title' => $newTitle,
                    'assignees' => [
                        [
                            'id' => 1,
                            'wordsCount' => 5,
                        ],
                    ],
                    'fileIds' => [1],
                    'labelIds' => $newLabelIds,
                    'progress' => [
                        'total' => 24,
                        'done' => 15,
                        'percent' => 62,
                    ],
                    'sourceLanguageId' => 'en',
                    'targetLanguageId' => 'fr',
                    'description' => 'Proofread all French strings',
                    'hash' => 'dac37aff364d83899128e68afe0de4994',
                    'translationUrl' => '/proofread/9092638ac9f2a2d1b5571d08edc53763/all/en-fr/10?task=dac37aff364d83899128e68afe0de4994',
                    'wordsCount' => 24,
                    'filesCount' => 2,
                    'commentsCount' => 0,
                    'deadline' => '2019-09-27T07:00:14+00:00',
                    'timeRange' => 'string',
                    'workflowStepId' => 10,
                    'createdAt' => '2019-09-23T09:04:29+00:00',
                    'updatedAt' => '2019-09-23T09:04:29+00:00',
                ],
            ])
        );

        $taskForUpdate = new TaskForUpdate($task->getData());
        $taskForUpdate->setTitle($newTitle);
        $taskForUpdate->setLabelIds($newLabelIds);

        $task = $this->crowdin->task->update($taskForUpdate);

        $this->assertInstanceOf(Task::class, $task);
        $this->assertEquals($newTitle, $task->getTitle());
        $this->assertEquals($newLabelIds, $task->getLabelIds());
        $this->assertEquals('gengo', $task->getVendor());
    }

    public function testDelete()
    {
        $this->mockRequestDelete('/projects/2/tasks/2');
        $this->crowdin->task->delete(2, 2);
    }

    public function testExportStrings()
    {
        $this->mockRequest([
            'path' => '/projects/2/tasks/3/exports',
            'method' => 'post',
            'response' => json_encode([
                'data' => [
                    'url' => 'https://production-enterprise-importer.downloads.crowdin.com/992000002/2/14.xliff?response-content-disposition=attachment%3B%20filename%3D%22APP.xliff%22&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIGJKLQV66ZXPMMEA%2F20190920%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20190920T093121Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3600&X-Amz-Signature=439ebd69a1b7e4c23e6d17891a491c94f832e0c82e4692dedb35a6cd1e624b62',
                    'expireIn' => '2019-09-20T10:31:21+00:00',
                ],
            ]),
        ]);

        $export = $this->crowdin->task->exportStrings(2, 3);
        $this->assertInstanceOf(DownloadFile::class, $export);
        $this->assertEquals(
            'https://production-enterprise-importer.downloads.crowdin.com/992000002/2/14.xliff?response-content-disposition=attachment%3B%20filename%3D%22APP.xliff%22&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIGJKLQV66ZXPMMEA%2F20190920%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20190920T093121Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3600&X-Amz-Signature=439ebd69a1b7e4c23e6d17891a491c94f832e0c82e4692dedb35a6cd1e624b62',
            $export->getUrl()
        );
    }

    public function testListTasks()
    {
        $this->mockRequestGet(
            '/users/6/tasks',
            json_encode([
                'data' => [
                    [
                        'data' => [
                            'id' => 2,
                            'projectId' => 2,
                            'creatorId' => 6,
                            'type' => 1,
                            'status' => 'todo',
                            'title' => 'French',
                            'assignees' => [
                                [
                                    'id' => 1,
                                    'wordsCount' => 5,
                                ],
                            ],
                            'fileIds' => [1],
                            'progress' => [
                                'total' => 24,
                                'done' => 15,
                                'percent' => 62,
                            ],
                            'sourceLanguageId' => 'en',
                            'targetLanguageId' => 'fr',
                            'description' => 'Proofread all French strings',
                            'hash' => 'dac37aff364d83899128e68afe0de4994',
                            'translationUrl' => '/proofread/9092638ac9f2a2d1b5571d08edc53763/all/en-fr/10?task=dac37aff364d83899128e68afe0de4994',
                            'wordsCount' => 24,
                            'filesCount' => 2,
                            'commentsCount' => 0,
                            'deadline' => '2019-09-27T07:00:14+00:00',
                            'timeRange' => 'string',
                            'workflowStepId' => 10,
                            'createdAt' => '2019-09-23T09:04:29+00:00',
                            'updatedAt' => '2019-09-23T09:04:29+00:00',
                        ],
                    ],
                ],
                'pagination' => [
                    [
                        'offset' => 0,
                        'limit' => 25,
                    ],
                ],
            ])
        );

        $tasks = $this->crowdin->task->listTasks(6);

        $this->assertInstanceOf(ModelCollection::class, $tasks);
        $this->assertCount(1, $tasks);
        $this->assertInstanceOf(Task::class, $tasks[0]);
        $this->assertEquals(2, $tasks[0]->getId());
    }

    public function testListUserTasks()
    {
        $this->mockRequestGet(
            '/user/tasks',
            json_encode([
                'data' => [
                    [
                        'data' => [
                            'id' => 2,
                            'projectId' => 2,
                            'creatorId' => 6,
                            'type' => 1,
                            'status' => 'todo',
                            'title' => 'French',
                            'assignees' => [
                                [
                                    'id' => 1,
                                    'wordsCount' => 5,
                                ],
                            ],
                            'fileIds' => [1],
                            'progress' => [
                                'total' => 24,
                                'done' => 15,
                                'percent' => 62,
                            ],
                            'sourceLanguageId' => 'en',
                            'targetLanguageId' => 'fr',
                            'description' => 'Proofread all French strings',
                            'hash' => 'dac37aff364d83899128e68afe0de4994',
                            'translationUrl' => '/proofread/9092638ac9f2a2d1b5571d08edc53763/all/en-fr/10?task=dac37aff364d83899128e68afe0de4994',
                            'wordsCount' => 24,
                            'filesCount' => 2,
                            'commentsCount' => 0,
                            'deadline' => '2019-09-27T07:00:14+00:00',
                            'timeRange' => 'string',
                            'workflowStepId' => 10,
                            'createdAt' => '2019-09-23T09:04:29+00:00',
                            'updatedAt' => '2019-09-23T09:04:29+00:00',
                            'isArchived' => false,
                        ],
                    ],
                ],
                'pagination' => [
                    [
                        'offset' => 0,
                        'limit' => 25,
                    ],
                ],
            ])
        );

        $tasks = $this->crowdin->task->listUserTasks();
        $this->assertInstanceOf(ModelCollection::class, $tasks);
        $this->assertCount(1, $tasks);
        $this->assertInstanceOf(Task::class, $tasks[0]);
        $this->assertEquals(2, $tasks[0]->getId());
    }

    public function testUserTaskArchivedStatus()
    {
        $this->mockRequestPatch(
            '/user/tasks/2?projectId=2',
            json_encode([
                'data' => [
                    'id' => 2,
                    'projectId' => 2,
                    'creatorId' => 6,
                    'type' => 1,
                    'status' => 'todo',
                    'title' => 'French',
                    'assignees' => [
                        [
                            'id' => 1,
                            'wordsCount' => 5,
                        ],
                    ],
                    'fileIds' => [1],
                    'progress' => [
                        'total' => 24,
                        'done' => 15,
                        'percent' => 62,
                    ],
                    'sourceLanguageId' => 'en',
                    'targetLanguageId' => 'fr',
                    'description' => 'Proofread all French strings',
                    'hash' => 'dac37aff364d83899128e68afe0de4994',
                    'translationUrl' => '/proofread/9092638ac9f2a2d1b5571d08edc53763/all/en-fr/10?task=dac37aff364d83899128e68afe0de4994',
                    'wordsCount' => 24,
                    'filesCount' => 2,
                    'commentsCount' => 0,
                    'deadline' => '2019-09-27T07:00:14+00:00',
                    'timeRange' => 'string',
                    'workflowStepId' => 10,
                    'createdAt' => '2019-09-23T09:04:29+00:00',
                    'updatedAt' => '2019-09-23T09:04:29+00:00',
                    'isArchived' => true,
                ],
            ])
        );

        $task = $this->crowdin->task->userTaskArchivedStatus(2, 2);

        $this->assertInstanceOf(Task::class, $task);
        $this->assertEquals(2, $task->getId());
        $this->assertTrue($task->isArchived());
    }

    public function testListSettingsTemplate()
    {
        $this->mockRequestGet(
            '/projects/2/tasks/settings-templates',
            json_encode([
                'data' => [
                    [
                        'data' => [
                            'id' => 1,
                            'name' => 'Default template',
                            'config' => [
                                'languages' => [
                                    [
                                        'languageId' => 'uk',
                                        'userIds' => [1],
                                    ],
                                ],
                            ],
                            'createdAt' => '2019-09-23T09:35:31+00:00',
                            'updatedAt' => '2020-09-23T09:35:31+00:00',
                        ],
                    ],
                ],
                'pagination' => [
                    [
                        'offset' => 0,
                        'limit' => 25,
                    ],
                ],
            ])
        );

        $taskSettingsTemplates = $this->crowdin->task->listSettingsTemplates(2);
        $this->assertInstanceOf(ModelCollection::class, $taskSettingsTemplates);
        $this->assertCount(1, $taskSettingsTemplates);
        $this->assertInstanceOf(TaskSettingsTemplate::class, $taskSettingsTemplates[0]);
        $this->assertEquals(1, $taskSettingsTemplates[0]->getId());
    }

    public function testAddSettingsTemplate()
    {
        $params = [
            'name' => 'string',
            'config' => [
                'languages' => [
                    [
                        'languageId' => 'uk',
                        'userIds' => [1],
                    ],
                ],
            ],
        ];

        $this->mockRequest([
            'path' => '/projects/2/tasks/settings-templates',
            'method' => 'post',
            'body' => json_encode($params),
            'response' => json_encode([
                'data' => [
                    'id' => 1,
                    'name' => 'Default template',
                    'config' => [
                        'languages' => [
                            [
                                'languageId' => 'uk',
                                'userIds' => [1],
                            ],
                        ],
                    ],
                    'createdAt' => '2019-09-23T09:35:31+00:00',
                    'updatedAt' => '2020-09-23T09:35:31+00:00',
                ],
            ]),
        ]);

        $taskSettingsTemplate = $this->crowdin->task->addSettingsTemplate(2, $params);
        $this->assertInstanceOf(TaskSettingsTemplate::class, $taskSettingsTemplate);
        $this->assertEquals(1, $taskSettingsTemplate->getId());
    }

    public function testGetAndUpdateSettingsTemplate()
    {
        $this->mockRequestGet(
            '/projects/2/tasks/settings-templates/1',
            json_encode([
                'data' => [
                    'id' => 1,
                    'name' => 'Default template',
                    'config' => [
                        'languages' => [
                            [
                                'languageId' => 'uk',
                                'userIds' => [1],
                            ],
                        ],
                    ],
                    'createdAt' => '2019-09-23T09:35:31+00:00',
                    'updatedAt' => '2020-09-23T09:35:31+00:00',
                ],
            ])
        );

        $taskSettingsTemplate = $this->crowdin->task->getSettingsTemplate(2, 1);
        $this->assertInstanceOf(TaskSettingsTemplate::class, $taskSettingsTemplate);
        $this->assertEquals(1, $taskSettingsTemplate->getId());

        $this->mockRequest([
            'path' => '/projects/2/tasks/settings-templates/1',
            'method' => 'patch',
            'response' => json_encode([
                'data' => [
                    'id' => 1,
                    'name' => 'Test template',
                    'config' => [
                        'languages' => [
                            [
                                'languageId' => 'fr',
                                'userIds' => [1],
                            ],
                        ],
                    ],
                    'createdAt' => '2019-09-23T09:35:31+00:00',
                    'updatedAt' => '2020-09-23T09:35:31+00:00',
                ],
            ]),
        ]);

        $params = new TaskSettingsTemplate($taskSettingsTemplate->getData());
        $params->setName('Test template');
        $params->setConfig([
            'languages' => [
                [
                    'languageId' => 'fr',
                    'userIds' => [1],
                ],
            ],
        ]);

        $taskSettingsTemplate = $this->crowdin->task->updateSettingsTemplate(2, $params);
        $this->assertInstanceOf(TaskSettingsTemplate::class, $taskSettingsTemplate);
        $this->assertEquals(1, $taskSettingsTemplate->getId());
    }

    public function testDeleteSettingsTemplate()
    {
        $this->mockRequestDelete('/projects/2/tasks/settings-templates/1');
        $this->crowdin->task->deleteSettingsTemplate(2, 1);
    }
}
