<?php

namespace CrowdinApiClient\Tests\Api;

use CrowdinApiClient\Model\Alignment;
use CrowdinApiClient\Model\DownloadFile;
use CrowdinApiClient\Model\PreTranslation;
use CrowdinApiClient\Model\PreTranslationReport;
use CrowdinApiClient\Model\PreTranslationReportFile;
use CrowdinApiClient\Model\PreTranslationReportLanguage;
use CrowdinApiClient\Model\TranslationAlignment;
use CrowdinApiClient\Model\TranslationImport;
use CrowdinApiClient\Model\TranslationImportReport;
use CrowdinApiClient\Model\TranslationProjectBuild;
use CrowdinApiClient\Model\WordAlignment;
use CrowdinApiClient\ModelCollection;

class TranslationApiTest extends AbstractTestApi
{
    public function testListPreTranslations(): void
    {
        $this->mockRequestGet(
            '/projects/8/pre-translations',
            json_encode([
                'data' => [
                    [
                        'data' => [
                            'identifier' => '55eff5b7-b21e-4620-9cb0-c46e31902af6',
                            'status' => 'in_progress',
                            'progress' => 0,
                            'attributes' => [
                                'method' => 'tm',
                                'fileIds' => [
                                    12,
                                ],
                                'labelIds' => [],
                                'languageIds' => [
                                    'uk',
                                ],
                                'excludeLabelIds' => [],
                                'autoApproveOption' => 'none',
                                'fallbackLanguages' => null,
                                'duplicateTranslations' => false,
                                'skipApprovedTranslations' => false,
                                'translateUntranslatedOnly' => true,
                                'translateWithPerfectMatchOnly' => false,
                            ],
                            'createdAt' => '2025-03-04T15:58:12+00:00',
                            'updatedAt' => '2025-03-04T15:58:57+00:00',
                            'startedAt' => '2025-03-04T15:58:13+00:00',
                            'finishedAt' => null,
                            'eta' => '44 seconds',
                        ],
                    ],
                ],
                'pagination' => [
                    'offset' => 0,
                    'limit' => 25,
                ],
            ])
        );

        $preTranslations = $this->crowdin->translation->listPreTranslations(8);

        $this->assertInstanceOf(ModelCollection::class, $preTranslations);
        $this->assertCount(1, $preTranslations);
        $this->assertSame('55eff5b7-b21e-4620-9cb0-c46e31902af6', $preTranslations[0]->getIdentifier());
    }

    public function testApplyPreTranslation(): void
    {
        $params = [
            'languageIds' => ['uk'],
            'fileIds' => [0],
        ];

        $this->mockRequest([
            'path' => '/projects/2/pre-translations',
            'method' => 'post',
            'body' => json_encode($params),
            'response' => json_encode([
                'data' => [
                    'identifier' => '9e7de270-4f83-41cb-b606-2f90631f26e2',
                    'status' => 'created',
                    'progress' => 90,
                    'attributes' => [
                        'languageIds' => ['uk'],
                        'fileIds' => [0],
                        'method' => 'tm',
                        'autoApproveOption' => 'all',
                        'duplicateTranslations' => true,
                        'translateUntranslatedOnly' => true,
                        'translateWithPerfectMatchOnly' => true,
                        'organizationId' => 200000299,
                        'projectId' => 2,
                        'userId' => 6,
                    ],
                    'createdAt' => '2019-09-20T14:05:50+00:00',
                    'updatedAt' => '2019-09-20T14:05:50+00:00',
                    'startedAt' => '2019-11-13T08:17:22Z',
                    'finishedAt' => '2019-11-13T08:17:22Z',
                ],
            ]),
        ]);

        $preTranslation = $this->crowdin->translation->applyPreTranslation(2, $params);

        $this->assertInstanceOf(PreTranslation::class, $preTranslation);
        $this->assertEquals('9e7de270-4f83-41cb-b606-2f90631f26e2', $preTranslation->getIdentifier());
    }

    public function testGetPreTranslation(): void
    {
        $this->mockRequestGet(
            '/projects/2/pre-translations/9e7de270-4f83-41cb-b606-2f90631f26e2',
            json_encode([
                'data' => [
                    'identifier' => '9e7de270-4f83-41cb-b606-2f90631f26e2',
                    'status' => 'created',
                    'progress' => 90,
                    'attributes' => [
                        'languageIds' => ['uk'],
                        'fileIds' => [0],
                        'method' => 'tm',
                        'autoApproveOption' => 'all',
                        'duplicateTranslations' => true,
                        'translateUntranslatedOnly' => true,
                        'translateWithPerfectMatchOnly' => true,
                        'organizationId' => 200000299,
                        'projectId' => 2,
                        'userId' => 6,
                    ],
                    'createdAt' => '2019-09-20T14:05:50+00:00',
                    'updatedAt' => '2019-09-20T14:05:50+00:00',
                    'startedAt' => '2019-11-13T08:17:22Z',
                    'finishedAt' => '2019-11-13T08:17:22Z',
                ],
            ])
        );

        $preTranslation = $this->crowdin->translation->getPreTranslation(2, '9e7de270-4f83-41cb-b606-2f90631f26e2');

        $this->assertInstanceOf(PreTranslation::class, $preTranslation);
        $this->assertEquals('9e7de270-4f83-41cb-b606-2f90631f26e2', $preTranslation->getIdentifier());
    }

    public function testUpdatePreTranslation(): void
    {
        $this->mockRequest([
            'path' => '/projects/8/pre-translations/9e7de270-4f83-41cb-b606-2f90631f26e2',
            'method' => 'patch',
            'body' => json_encode([
                [
                    'op' => 'replace',
                    'path' => '/status',
                    'value' => 'canceled',
                ],
            ]),
            'response' => json_encode([
                'data' => [
                    'identifier' => '9e7de270-4f83-41cb-b606-2f90631f26e2',
                    'status' => 'canceled',
                    'progress' => 0,
                    'attributes' => [
                        'languageIds' => ['uk'],
                        'fileIds' => [10],
                    ],
                    'createdAt' => '2019-09-20T14:05:50+00:00',
                    'updatedAt' => '2019-09-20T14:05:50+00:00',
                    'startedAt' => '2019-11-13T08:17:22Z',
                    'finishedAt' => '2019-11-13T08:17:22Z',
                ],
            ]),
        ]);

        $preTranslation = new PreTranslation([
            'identifier' => '9e7de270-4f83-41cb-b606-2f90631f26e2',
            'status' => 'in_progress',
            'progress' => 90,
            'attributes' => [
                'languageIds' => ['uk'],
                'fileIds' => [10],
            ],
            'createdAt' => '2019-09-20T14:05:50+00:00',
            'updatedAt' => '2019-09-20T14:05:50+00:00',
            'startedAt' => '2019-11-13T08:17:22Z',
            'finishedAt' => '2019-11-13T08:17:22Z',
        ]);
        $preTranslation->setStatus('canceled');

        $actual = $this->crowdin->translation->updatePreTranslation(8, $preTranslation);

        $this->assertInstanceOf(PreTranslation::class, $actual);
        $this->assertSame('canceled', $actual->getStatus());
        $this->assertSame(0, $actual->getProgress());
    }

    public function testGetPreTranslationReport(): void
    {
        $this->mockRequestGet(
            '/projects/2/pre-translations/9e7de270-4f83-41cb-b606-2f90631f26e2/report',
            json_encode([
                'data' => [
                    'languages' => [
                        [
                            'id' => 'es',
                            'files' => [
                                [
                                    'id' => '10191',
                                    'statistics' => [
                                        'phrases' => 6,
                                        'words' => 13,
                                    ],
                                ],
                            ],
                            'skipped' => [
                                'translation_eq_source' => 2,
                                'qa_check' => 1,
                                'hidden_strings' => 0,
                                'ai_error' => 6,
                            ],
                            'skippedQaCheckCategories' => [
                                'duplicate' => 1,
                                'spellcheck' => 1,
                            ],
                        ],
                    ],
                    'preTranslateType' => 'ai',
                ],
            ])
        );

        $preTranslationReport = $this->crowdin->translation->getPreTranslationReport(
            2,
            '9e7de270-4f83-41cb-b606-2f90631f26e2'
        );

        $this->assertInstanceOf(PreTranslationReport::class, $preTranslationReport);
        $this->assertEquals('ai', $preTranslationReport->getPreTranslationType());
        $this->assertIsArray($preTranslationReport->getLanguages());
        $this->assertInstanceOf(PreTranslationReportLanguage::class, $preTranslationReport->getLanguages()[0]);
        $this->assertSame('es', $preTranslationReport->getLanguages()[0]->getId());
        $this->assertInstanceOf(
            PreTranslationReportFile::class,
            $preTranslationReport->getLanguages()[0]->getFiles()[0]
        );
        $this->assertIsArray($preTranslationReport->getLanguages()[0]->getSkippedInfo());
        $this->assertIsArray($preTranslationReport->getLanguages()[0]->getSkippedQaCheckCategories());
    }

    public function testBuildProjectFileTranslation(): void
    {
        $this->mockRequest([
            'uri' => 'https://api.crowdin.com/api/v2/projects/1/translations/builds/files/2',
            'method' => 'post',
            'headers' => [
                'content-type' => 'application/json',
                'if-none-match' => 'bfc13a64729c4290ef5b2c2730249c88ca92d82d',
                'Authorization' => 'Bearer access_token',
            ],
            'response' => json_encode([
                'data' => [
                    'url' => 'https://foo.com/file',
                    'expireIn' => '2019-09-20T10:31:21+00:00',
                ],
            ]),
        ]);

        $file = $this->crowdin->translation->buildProjectFileTranslation(
            1,
            2,
            ['targetLanguageId' => 'uk'],
            'bfc13a64729c4290ef5b2c2730249c88ca92d82d'
        );

        $this->assertInstanceOf(DownloadFile::class, $file);
        $this->assertEquals('https://foo.com/file', $file->getUrl());
    }

    public function testListProjectBuilds(): void
    {
        $this->mockRequestGet(
            '/projects/2/translations/builds',
            json_encode([
                'data' => [
                    [
                        'data' => [
                            'id' => 2,
                            'projectId' => 2,
                            'branchId' => 34,
                            'languagesId' => [15],
                            'status' => 'finished',
                            'progress' => [
                                'percent' => 90,
                                'currentLanguageId' => 'uk',
                                'currentFileId' => 1,
                            ],
                        ],
                    ],
                ],
                'pagination' => [
                    [
                        'offset' => 0,
                        'limit' => 0,
                    ],
                ],
            ])
        );

        $translationProjectBuilds = $this->crowdin->translation->getProjectBuilds(2);

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

    public function testBuildProject(): void
    {
        $this->mockRequest([
            'uri' => 'https://api.crowdin.com/api/v2/projects/2/translations/builds',
            'method' => 'post',
            'response' => json_encode([
                'data' => [
                    'id' => 2,
                    'projectId' => 2,
                    'branchId' => 34,
                    'languagesId' => [15],
                    'status' => 'finished',
                    'progress' => [
                        'percent' => 90,
                        'currentLanguageId' => 'uk',
                        'currentFileId' => 1,
                    ],
                ],
            ]),
            'options' => [
                'body' => [
                    'branchId' => 2,
                    'targetLanguageIds' => ['uk'],
                ],
            ],
        ]);

        $params = [
            'branchId' => 2,
            'targetLanguageIds' =>
                [
                    0 => 'uk',
                ],
            'skipUntranslatedStrings' => false,
            'skipUntranslatedFiles' => false,
            'exportApprovedOnly' => false,
        ];

        $projectBuild = $this->crowdin->translation->buildProject(2, $params);

        $this->assertInstanceOf(TranslationProjectBuild::class, $projectBuild);
        $this->assertEquals(2, $projectBuild->getId());
    }

    public function testGetProjectBuildStatus(): void
    {
        $this->mockRequestGet(
            '/projects/2/translations/builds/2',
            json_encode([
                'data' => [
                    'id' => 2,
                    'projectId' => 2,
                    'branchId' => 34,
                    'languagesId' => [15],
                    'status' => 'finished',
                    'progress' => [
                        'percent' => 90,
                        'currentLanguageId' => 'uk',
                        'currentFileId' => 1,
                    ],
                ],
            ])
        );

        $projectBuild = $this->crowdin->translation->getProjectBuildStatus(2, 2);

        $this->assertInstanceOf(TranslationProjectBuild::class, $projectBuild);
        $this->assertEquals(2, $projectBuild->getId());
    }

    public function testDownloadProjectBuild(): void
    {
        $this->mockRequestGet(
            '/projects/2/translations/builds/2/download',
            json_encode([
                'data' => [
                    'url' => 'https://production-enterprise-importer.downloads.crowdin.com/992000002/2/14.xliff',
                    'expireIn' => '2019-09-20T10:31:21+00:00',
                ],
            ])
        );

        $file = $this->crowdin->translation->downloadProjectBuild(2, 2);

        $this->assertInstanceOf(DownloadFile::class, $file);
        $this->assertEquals(
            'https://production-enterprise-importer.downloads.crowdin.com/992000002/2/14.xliff',
            $file->getUrl()
        );
    }

    public function testDeleteProjectBuild(): void
    {
        $this->mockRequest([
            'path' => '/projects/2/translations/builds/2',
            'method' => 'delete',
        ]);

        $this->crowdin->translation->deleteProjectBuild(2, 2);
    }

    public function testUploadTranslations(): void
    {
        $params = [
            'storageId' => 13,
            'fileId' => 2,
        ];

        $this->mockRequest([
            'path' => '/projects/8/translations/uk',
            'method' => 'post',
            'response' => json_encode([
                'data' => [
                    'projectId' => 8,
                    'storageId' => 34,
                    'languageId' => 'uk',
                    'fileId' => 56,
                ],
            ]),
            'options' => [
                'body' => [
                    'storageId' => 13,
                    'fileId' => 2,
                ],
            ],
        ]);

        $data = $this->crowdin->translation->uploadTranslations(8, 'uk', $params);

        $this->assertIsArray($data);
        $this->assertEquals([
            'projectId' => 8,
            'storageId' => 34,
            'languageId' => 'uk',
            'fileId' => 56,
        ], $data);
    }

    public function testExportProjectTranslation(): void
    {
        $params = [
            'targetLanguageId' => 'en',
            'fileIds' => [7, 14, 15],
        ];

        $this->mockRequest(
            [
                'path' => '/projects/2/translations/exports',
                'method' => 'post',
                'response' => json_encode([
                    'data' => [
                        'url' => 'https://production-enterprise-importer.downloads.crowdin.com/992000002/2/14.xliff',
                        'expireIn' => '2019-09-20T10:31:21+00:00',
                    ],
                ]),
            ]
        );

        $file = $this->crowdin->translation->exportProjectTranslation(2, $params);

        $this->assertInstanceOf(DownloadFile::class, $file);
        $this->assertEquals(
            'https://production-enterprise-importer.downloads.crowdin.com/992000002/2/14.xliff',
            $file->getUrl()
        );
    }

    public function testAlignment(): void
    {
        $params = [
            'sourceLanguageId' => 'en',
            'targetLanguageId' => 'de',
            'text' => 'Your password has been reset successfully!',
        ];

        $this->mockRequest([
            'path' => '/projects/8/translations/alignment',
            'method' => 'post',
            'response' => json_encode([
                'data' => [
                    'words' => [
                        [
                            'text' => 'password',
                            'alignments' => [
                                [
                                    'sourceWord' => 'Password',
                                    'sourceLemma' => 'password',
                                    'targetWord' => 'Пароль',
                                    'targetLemma' => 'пароль',
                                    'match' => 2,
                                    'probability' => 2.0,
                                ],
                            ],
                        ],
                    ],
                ],
            ]),
            'options' => [
                'body' => [
                    'sourceLanguageId' => 'en',
                    'targetLanguageId' => 'de',
                    'text' => 'Your password has been reset successfully!',
                ],
            ],
        ]);

        $alignment = $this->crowdin->translation->alignment(8, $params);

        $this->assertInstanceOf(TranslationAlignment::class, $alignment);
        $this->assertIsArray($alignment->getWords());
        $this->assertCount(1, $alignment->getWords());
        $this->assertInstanceOf(WordAlignment::class, $alignment->getWords()[0]);
        $this->assertEquals('password', $alignment->getWords()[0]->getText());
        $this->assertCount(1, $alignment->getWords()[0]->getAlignments());
        $this->assertInstanceOf(Alignment::class, $alignment->getWords()[0]->getAlignments()[0]);
        $this->assertEquals('Password', $alignment->getWords()[0]->getAlignments()[0]->getSourceWord());
        $this->assertEquals('Пароль', $alignment->getWords()[0]->getAlignments()[0]->getTargetWord());
    }

    public function testImportTranslations(): void
    {
        $params = [
            'storageId' => 13,
            'branchId' => 34,
            'languageIds' => ['uk'],
            'fileId' => 2,
        ];

        $this->mockRequest([
            'path' => '/projects/8/translations/imports',
            'method' => 'post',
            'body' => json_encode($params),
            'response' => json_encode([
                'data' => [
                    'identifier' => 'b5215a34-1305-4b21-8054-fc2eb252842f',
                    'status' => 'created',
                    'progress' => 0,
                    'attributes' => [
                        'storageId' => 13,
                        'fileId' => 2,
                        'importEqSuggestions' => false,
                        'autoApproveImported' => false,
                        'translateHidden' => false,
                        'addToTm' => true,
                        'languageIds' => ['uk'],
                    ],
                    'createdAt' => '2025-09-23T11:51:08+00:00',
                    'updatedAt' => '2025-09-23T11:51:08+00:00',
                    'startedAt' => null,
                    'finishedAt' => null,
                ],
            ]),
        ]);

        $translationImport = $this->crowdin->translation->importTranslations(8, $params);

        $this->assertInstanceOf(TranslationImport::class, $translationImport);
        $this->assertEquals('b5215a34-1305-4b21-8054-fc2eb252842f', $translationImport->getIdentifier());
        $this->assertEquals('created', $translationImport->getStatus());
        $this->assertEquals(0, $translationImport->getProgress());
    }

    public function testGetTranslationImportStatus(): void
    {
        $this->mockRequestGet(
            '/projects/8/translations/imports/b5215a34-1305-4b21-8054-fc2eb252842f',
            json_encode([
                'data' => [
                    'identifier' => 'b5215a34-1305-4b21-8054-fc2eb252842f',
                    'status' => 'finished',
                    'progress' => 100,
                    'attributes' => [
                        'storageId' => 13,
                        'fileId' => 2,
                        'importEqSuggestions' => false,
                        'autoApproveImported' => false,
                        'translateHidden' => false,
                        'addToTm' => true,
                        'languageIds' => ['uk'],
                    ],
                    'createdAt' => '2025-09-23T11:51:08+00:00',
                    'updatedAt' => '2025-09-23T11:51:08+00:00',
                    'startedAt' => '2025-09-23T11:51:09+00:00',
                    'finishedAt' => '2025-09-23T11:51:20+00:00',
                ],
            ])
        );

        $translationImport = $this->crowdin->translation->getTranslationImportStatus(
            8,
            'b5215a34-1305-4b21-8054-fc2eb252842f'
        );

        $this->assertInstanceOf(TranslationImport::class, $translationImport);
        $this->assertEquals('b5215a34-1305-4b21-8054-fc2eb252842f', $translationImport->getIdentifier());
        $this->assertEquals('finished', $translationImport->getStatus());
        $this->assertEquals(100, $translationImport->getProgress());
    }

    public function testDownloadTranslationImportReport(): void
    {
        $this->mockRequestGet(
            '/projects/8/translations/imports/b5215a34-1305-4b21-8054-fc2eb252842f/report',
            json_encode([
                'data' => [
                    'languages' => [
                        [
                            'id' => 'uk',
                            'files' => [
                                [
                                    'id' => '10191',
                                    'statistics' => [
                                        'phrases' => 6,
                                        'words' => 45,
                                    ],
                                ],
                            ],
                            'skipped' => [
                                'translationEqSource' => 0,
                                'hiddenStrings' => 0,
                                'qaCheck' => 647,
                            ],
                            'skippedQaCheckCategories' => [
                                'size' => 1,
                                'duplicate' => 648,
                            ],
                        ],
                    ],
                ],
            ])
        );

        $report = $this->crowdin->translation->downloadTranslationImportReport(
            8,
            'b5215a34-1305-4b21-8054-fc2eb252842f'
        );

        $this->assertInstanceOf(TranslationImportReport::class, $report);
        $this->assertIsArray($report->getLanguages());
        $this->assertInstanceOf(PreTranslationReportLanguage::class, $report->getLanguages()[0]);
        $this->assertSame('uk', $report->getLanguages()[0]->getId());
    }

    public function testUpdatePreTranslations(): void
    {
        $this->mockRequest([
            'uri' => 'https://api.crowdin.com/api/v2/projects/1/pre-translations',
            'method' => 'patch',
            'response' => json_encode([
                'data' => [
                    [
                        'data' => [
                            'identifier' => '9e7de270-4f83-41cb-b606-2f90631f26e2',
                            'status' => 'canceled',
                            'progress' => 50,
                            'attributes' => [
                                'languageIds' => ['uk'],
                                'fileIds' => [742],
                                'method' => 'tm',
                                'autoApproveOption' => 'all',
                                'duplicateTranslations' => true,
                                'skipApprovedTranslations' => true,
                                'translateUntranslatedOnly' => true,
                                'translateWithPerfectMatchOnly' => true,
                                'priority' => 'high',
                            ],
                            'createdAt' => '2019-09-20T14:05:50+00:00',
                            'updatedAt' => '2019-09-20T14:05:50+00:00',
                            'startedAt' => '2019-09-20T14:05:50+00:00',
                            'finishedAt' => '2019-09-20T14:06:50+00:00',
                        ],
                    ],
                ],
            ]),
        ]);

        $data = [
            [
                'op' => 'replace',
                'path' => '/9e7de270-4f83-41cb-b606-2f90631f26e2/status',
                'value' => 'canceled',
            ],
            [
                'op' => 'replace',
                'path' => '/9e7de270-4f83-41cb-b606-2f90631f26e2/priority',
                'value' => 'high',
            ],
        ];

        $preTranslations = $this->crowdin->translation->updatePreTranslations(1, $data);

        $this->assertInstanceOf(ModelCollection::class, $preTranslations);
        $this->assertCount(1, $preTranslations);
        $this->assertInstanceOf(PreTranslation::class, $preTranslations[0]);
        $this->assertEquals('9e7de270-4f83-41cb-b606-2f90631f26e2', $preTranslations[0]->getIdentifier());
        $this->assertEquals('canceled', $preTranslations[0]->getStatus());
    }
}
