--[[----------------------------------------------------------------------------

WFCatSimpleDocStoreUpdaterTest.lua

--------------------------------------------------------------------------------

ADOBE CONFIDENTIAL
------------------
Copyright 2024 Adobe
All Rights Reserved.

NOTICE: All information contained herein is, and remains
the property of Adobe and its suppliers, if any. The intellectual
and technical concepts contained herein are proprietary to Adobe
and its suppliers and are protected by all applicable intellectual
property laws, including trade secret and copyright laws.
Dissemination of this information or reproduction of this material
is strictly forbidden unless prior written permission is obtained
from Adobe.

------------------------------------------------------------------------------]]

	-- WF.core.os
local WFFileUtils = require 'WFFileUtils'
local KSTableUtils = require 'KSTableUtils'
local WFPlatformInfo = require 'WFPlatformInfo'

	-- WF.core.self_test
local WFRxTestCase = require 'WFRxTestCase'
local WFCatMockCatalog = require 'WFCatMockCatalog'

	-- WF.core.utils
local KSIdGenerator = require 'KSIdGenerator'

	-- oz_client.managed_catalog
local WFCatAssetTestUtils = require 'WFCatAssetTestUtils'
local WFCatSimpleDocStoreUpdater = require 'WFCatSimpleDocStoreUpdater'
local WFCatVersionTestUtils = require 'WFCatVersionTestUtils'

--------------------------------------------------------------------------------

local KSTableUtils_setNested = KSTableUtils.setNested
local KSTableUtils_derefOpt = KSTableUtils.derefOpt

--------------------------------------------------------------------------------

local WFCatSimpleDocStoreUpdaterTest = {}

--------------------------------------------------------------------------------

local function maybeFixXmpDevelopFileLocationAndGetExpectedPath( wfCatalog, localOnlySettings )

	local expectedXmpDevelopPath
	local absolutePath = localOnlySettings.xmpDevelopSettingsFilePath

	if WFPlatformInfo.isMobile() then
		expectedXmpDevelopPath = localOnlySettings.xmpDevelopSettingsRelPath
	else
		expectedXmpDevelopPath = wfCatalog:fileSpec():pathForSettingsXmp( localOnlySettings.developSettingsSha256 )
		absolutePath = expectedXmpDevelopPath
		WFFileUtils.move( localOnlySettings.xmpDevelopSettingsFilePath, expectedXmpDevelopPath )
			-- by default desktop tests write xmp_develop to an arbitrary directory, need to write to correct place for this
			-- test since link is missing and code will look for it in the expected place.
	end

	return expectedXmpDevelopPath, absolutePath

end

--------------------------------------------------------------------------------

local expectedSha256Key = 'sha256'
if WFPlatformInfo.isiOS then
	expectedSha256Key = 'contentId'
end

--------------------------------------------------------------------------------

local function confirmMissingLocalXmpDevelopFixed( rxTest, docStore, docValue, localOnlySettings, expectedXmpDevelopPath )

	local docObserver = rxTest:observe( docStore:ongoingDocValue( docValue._id )
		:map( function( doc )
			return KSTableUtils_derefOpt( doc, '_localOnly', 'files', 'xmp_develop', 'path' ) == expectedXmpDevelopPath and
				KSTableUtils_derefOpt( doc, '_localOnly', 'files', 'xmp_develop', expectedSha256Key ) == localOnlySettings.developSettingsSha256 and
				KSTableUtils_derefOpt( doc, '_localOnly', 'files', 'xmp_develop', 'fileSize' ) == localOnlySettings.xmpDevelopSettingsFileSize and
				KSTableUtils_derefOpt( doc, '_changeCounter' ) ~= KSTableUtils_derefOpt( docValue, '_changeCounter' )
		end ) )
	docObserver:expectDataWithinTime( 3, true )

end

--------------------------------------------------------------------------------

local function testResolveMissingLocalOnlyXmpDevelopWithErrorAnnotation( rxTest, errorName )

	local wfCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest )
	local docStore = wfCatalog:docStore()

	-- will be fixed because error annotation is present and xmp develop link sha256 is different from local value

	local optArguments = {
		noLocalDevelopSettings = true,
	}

	local sha256MismatchDocValue, sha256MismatchLocalOnlySettings = WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog, nil, optArguments )
	KSTableUtils_setNested( sha256MismatchDocValue, errorName, '_localOnly', 'ozError', 'subtype' )

	local otherSha256 = KSIdGenerator.uuidInLowercaseHex() .. KSIdGenerator.uuidInLowercaseHex()
	KSTableUtils_setNested( sha256MismatchDocValue, otherSha256, '_serverProvidedMetadata', 'links', '/rels/xmp/develop', 'sha256' )

	local sha256MismatchExpectedXmpDevelopPath = maybeFixXmpDevelopFileLocationAndGetExpectedPath( wfCatalog, sha256MismatchLocalOnlySettings )

	rxTest:waitFor( docStore:setDocValue( sha256MismatchDocValue ) )
	sha256MismatchDocValue = rxTest:getFirstValue( docStore:docValue( sha256MismatchDocValue._id ) )

	-- will be fixed because error annotation is present and xmp develop link is missing sha256 info

	local xmpLinkMissingSha256DocValue, xmpLinkMissingSha256LocalOnlySettings = WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog, nil, optArguments )
	KSTableUtils_setNested( xmpLinkMissingSha256DocValue, errorName, '_localOnly', 'ozError', 'subtype' )
	KSTableUtils_setNested( xmpLinkMissingSha256DocValue, nil, '_serverProvidedMetadata', 'links', '/rels/xmp/develop', 'sha256' )

	local xmpLinkMissingSha256ExpectedXmpDevelopPath = maybeFixXmpDevelopFileLocationAndGetExpectedPath( wfCatalog, xmpLinkMissingSha256LocalOnlySettings )

	rxTest:waitFor( docStore:setDocValue( xmpLinkMissingSha256DocValue ) )
	xmpLinkMissingSha256DocValue = rxTest:getFirstValue( docStore:docValue( xmpLinkMissingSha256DocValue._id ) )

	-- will not be fixed despite error annotation because /rels/temp/xmp/develop/.. link is also present

	local relsTempLinkDocValue, relsTempLinkLocalOnlySettings = WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog, nil, optArguments )
	KSTableUtils_setNested( relsTempLinkDocValue, errorName, '_localOnly', 'ozError', 'subtype' )

	otherSha256 = KSIdGenerator.uuidInLowercaseHex() .. KSIdGenerator.uuidInLowercaseHex()
	KSTableUtils_setNested( relsTempLinkDocValue, otherSha256, '_serverProvidedMetadata', 'links', '/rels/xmp/develop', 'sha256' )

	local relsTempLink = '/rels/temp/xmp/develop/' .. relsTempLinkLocalOnlySettings.developSettingsSha256
	KSTableUtils_setNested( relsTempLinkDocValue, true, '_serverProvidedMetadata', 'links', relsTempLink, 'exists' )

	maybeFixXmpDevelopFileLocationAndGetExpectedPath( wfCatalog, relsTempLinkLocalOnlySettings )

	rxTest:waitFor( docStore:setDocValue( relsTempLinkDocValue ) )
	relsTempLinkDocValue = rxTest:getFirstValue( docStore:docValue( relsTempLinkDocValue._id ) )

	-- will not be fixed because sha256 in /rels/xmp/develop link matches

	local sha256MatchDocValue, sha256MatchLocalOnlySettings = WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog, nil, optArguments )
	KSTableUtils_setNested( sha256MatchDocValue, errorName, '_localOnly', 'ozError', 'subtype' )

	maybeFixXmpDevelopFileLocationAndGetExpectedPath( wfCatalog, sha256MatchLocalOnlySettings )

	rxTest:waitFor( docStore:setDocValue( sha256MatchDocValue ) )
	sha256MatchDocValue = rxTest:getFirstValue( docStore:docValue( sha256MatchDocValue._id ) )

	-- will not be fixed but will be annotated because file cannot be found on disk

	local fnfDocValue, fnfLocalOnlySettings = WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog, nil, optArguments )
	KSTableUtils_setNested( fnfDocValue, errorName, '_localOnly', 'ozError', 'subtype' )

	otherSha256 = KSIdGenerator.uuidInLowercaseHex() .. KSIdGenerator.uuidInLowercaseHex()
	KSTableUtils_setNested( fnfDocValue, otherSha256, '_serverProvidedMetadata', 'links', '/rels/xmp/develop', 'sha256' )

	local _, fnfAbsolutePath = maybeFixXmpDevelopFileLocationAndGetExpectedPath( wfCatalog, fnfLocalOnlySettings )
	WFFileUtils.delete( fnfAbsolutePath )

	rxTest:waitFor( docStore:setDocValue( fnfDocValue ) )
	fnfDocValue = rxTest:getFirstValue( docStore:docValue( fnfDocValue._id ) )

	-- will not be fixed because current xmpDevelop already uploaded to Oz

	local xmpDevelopUploadedDocValue, xmpDevelopUploadedLocalOnlySettings = WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog, nil, optArguments )
	KSTableUtils_setNested( xmpDevelopUploadedDocValue, errorName, '_localOnly', 'ozError', 'subtype' )

	maybeFixXmpDevelopFileLocationAndGetExpectedPath( wfCatalog, xmpDevelopUploadedLocalOnlySettings )

	rxTest:waitFor( docStore:setDocValue( xmpDevelopUploadedDocValue ) )
	xmpDevelopUploadedDocValue = rxTest:getFirstValue( docStore:docValue( xmpDevelopUploadedDocValue._id ) )

	-- will not be fixed because it has been annotated that file with sha256 was not found

	local annotatedDocValue, annotatedLocalOnlySettings = WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog, nil, optArguments )
	KSTableUtils_setNested( annotatedDocValue, errorName, '_localOnly', 'ozError', 'subtype' )

	maybeFixXmpDevelopFileLocationAndGetExpectedPath( wfCatalog, annotatedLocalOnlySettings )
	KSTableUtils_setNested( annotatedDocValue, annotatedLocalOnlySettings.developSettingsSha256, '_localOnly', 'universal', 'simpleDocStoreUpdater', 'missingXmpDevelopFileSha256' )

	otherSha256 = KSIdGenerator.uuidInLowercaseHex() .. KSIdGenerator.uuidInLowercaseHex()
	KSTableUtils_setNested( annotatedDocValue, otherSha256, '_serverProvidedMetadata', 'links', '/rels/xmp/develop', 'sha256' )

	rxTest:waitFor( docStore:setDocValue( annotatedDocValue ) )
	annotatedDocValue = rxTest:getFirstValue( docStore:docValue( annotatedDocValue._id ) )

	-- will be fixed despite annotation that file was not found because sha256 is different

	local annotatedDifferentSha256DocValue, annotatedDifferentSha256LocalOnlySettings = WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog, nil, optArguments )
	KSTableUtils_setNested( annotatedDifferentSha256DocValue, errorName, '_localOnly', 'ozError', 'subtype' )

	local annotatedDifferentSha256ExpectedXmpDevelopPath = maybeFixXmpDevelopFileLocationAndGetExpectedPath( wfCatalog, annotatedDifferentSha256LocalOnlySettings )
	otherSha256 = KSIdGenerator.uuidInLowercaseHex() .. KSIdGenerator.uuidInLowercaseHex()
	KSTableUtils_setNested( annotatedDifferentSha256DocValue, otherSha256, '_localOnly', 'universal', 'simpleDocStoreUpdater', 'missingXmpDevelopFileSha256' )

	otherSha256 = KSIdGenerator.uuidInLowercaseHex() .. KSIdGenerator.uuidInLowercaseHex()
	KSTableUtils_setNested( annotatedDifferentSha256DocValue, otherSha256, '_serverProvidedMetadata', 'links', '/rels/xmp/develop', 'sha256' )

	rxTest:waitFor( docStore:setDocValue( annotatedDifferentSha256DocValue ) )
	annotatedDifferentSha256DocValue = rxTest:getFirstValue( docStore:docValue( annotatedDifferentSha256DocValue._id ) )

	-- will not be fixed even though file is present because file path is already written to _localOnly section

	local inLocalOnlyAlreadyDocValue, inLocalOnlyAlreadyLocalOnlySettings = WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog )
	KSTableUtils_setNested( inLocalOnlyAlreadyDocValue, errorName, '_localOnly', 'ozError', 'subtype' )

	otherSha256 = KSIdGenerator.uuidInLowercaseHex() .. KSIdGenerator.uuidInLowercaseHex()
	KSTableUtils_setNested( inLocalOnlyAlreadyDocValue, otherSha256, '_serverProvidedMetadata', 'links', '/rels/xmp/develop', 'sha256' )

	rxTest:waitFor( docStore:setDocValue( inLocalOnlyAlreadyDocValue ) )
	inLocalOnlyAlreadyDocValue = rxTest:getFirstValue( docStore:docValue( inLocalOnlyAlreadyDocValue._id ) )

	-- will be fixed even though _localOnly has path because sha256 is different

	local localOnlySha256MismatchDocValue, localOnlySha256MismatchLocalOnlySettings = WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog )
	KSTableUtils_setNested( localOnlySha256MismatchDocValue, errorName, '_localOnly', 'ozError', 'subtype' )

	otherSha256 = KSIdGenerator.uuidInLowercaseHex() .. KSIdGenerator.uuidInLowercaseHex()
	KSTableUtils_setNested( localOnlySha256MismatchDocValue, otherSha256, '_serverProvidedMetadata', 'links', '/rels/xmp/develop', 'sha256' )
	KSTableUtils_setNested( localOnlySha256MismatchDocValue, otherSha256, '_localOnly', 'files', 'xmp_develop', expectedSha256Key )
	KSTableUtils_setNested( localOnlySha256MismatchDocValue, 'other/path', '_localOnly', 'files', 'xmp_develop', 'path' )

	local localOnlySha256MismatchExpectedXmpDevelopPath = maybeFixXmpDevelopFileLocationAndGetExpectedPath( wfCatalog, localOnlySha256MismatchLocalOnlySettings )

	rxTest:waitFor( docStore:setDocValue( localOnlySha256MismatchDocValue ) )
	localOnlySha256MismatchDocValue = rxTest:getFirstValue( docStore:docValue( localOnlySha256MismatchDocValue._id ) )


	-- start the WFCatSimpleDocStoreUpdater

	local updater = WFCatSimpleDocStoreUpdater( docStore, wfCatalog:indexStore(), wfCatalog )
	updater:start()
	rxTest:finally( function()
		updater:close()
	end )


	-- check that asset with different sha256 in xmp develop link was fixed

	confirmMissingLocalXmpDevelopFixed( rxTest, docStore, sha256MismatchDocValue, sha256MismatchLocalOnlySettings, sha256MismatchExpectedXmpDevelopPath )

	-- check that asset with sha256 missing from /rels/xmp/develop link was fixed

	confirmMissingLocalXmpDevelopFixed( rxTest, docStore, xmpLinkMissingSha256DocValue, xmpLinkMissingSha256LocalOnlySettings, xmpLinkMissingSha256ExpectedXmpDevelopPath )

	-- check that file not found asset path is not updated and missingXmpDevelopFile annotation has been added

	local docObserver = rxTest:observe( docStore:ongoingDocValue( fnfDocValue._id )
		:map( function( docValue )
			return KSTableUtils_derefOpt( docValue, '_localOnly', 'files', 'xmp_develop', 'path' ) == nil and
				KSTableUtils_derefOpt( docValue, '_localOnly', 'universal', 'simpleDocStoreUpdater', 'missingXmpDevelopFileSha256' ) == fnfLocalOnlySettings.developSettingsSha256
		end ) )
	docObserver:expectDataWithinTime( 3, true )

	-- check that asset with different sha256 in file not found annotation is fixed

	confirmMissingLocalXmpDevelopFixed( rxTest, docStore, annotatedDifferentSha256DocValue, annotatedDifferentSha256LocalOnlySettings, annotatedDifferentSha256ExpectedXmpDevelopPath )

	-- check that asset with different sha256 in _localOnly is fixed

	confirmMissingLocalXmpDevelopFixed( rxTest, docStore, localOnlySha256MismatchDocValue, localOnlySha256MismatchLocalOnlySettings, localOnlySha256MismatchExpectedXmpDevelopPath )

	-- check that assets with missing paths that should not have been updated at all were not updated

	for _, unchangedDoc in ipairs( { relsTempLinkDocValue, sha256MatchDocValue, xmpDevelopUploadedDocValue, annotatedDocValue } ) do

		rxTest:expectSingleValue( docStore:docValue( unchangedDoc._id )
			:map( function( docValue )
				return KSTableUtils_derefOpt( docValue, '_localOnly', 'files', 'xmp_develop', 'path' ) == nil and
					KSTableUtils_derefOpt( docValue, '_changeCounter' ) == KSTableUtils_derefOpt( unchangedDoc, '_changeCounter' )
			end ),
			true
		)

	end

	-- ensure asset that did not need to be fixed at all because file is in _localOnly was not touched

	for unchangedDoc, localOnlySettings in pairs( { [ inLocalOnlyAlreadyDocValue ] = inLocalOnlyAlreadyLocalOnlySettings } ) do
		rxTest:expectSingleValue( docStore:docValue( unchangedDoc._id )
			:map( function( docValue )
				return KSTableUtils_derefOpt( docValue, '_localOnly', 'files', 'xmp_develop', 'path' ) == localOnlySettings.xmpDevelopSettingsRelPath and
					KSTableUtils_derefOpt( docValue, '_localOnly', 'files', 'xmp_develop', 'fileSize' ) == localOnlySettings.xmpDevelopSettingsFileSize and
					KSTableUtils_derefOpt( docValue, '_localOnly', 'files', 'xmp_develop', expectedSha256Key ) == localOnlySettings.developSettingsSha256 and
					KSTableUtils_derefOpt( docValue, '_changeCounter' ) == KSTableUtils_derefOpt( unchangedDoc, '_changeCounter' )
			end ),
			true
		)
	end

	-- check that the correct number of overlays were applied

	rxTest:expectEqual(
		{ missingLocalOnlyXmpDevelop = 5, numOverlaysApplied = 5 },
		updater:DEBUG_getUpdatesApplied()
	)


end

--------------------------------------------------------------------------------

function WFCatSimpleDocStoreUpdaterTest.rxTestResolveMissingOnlyXmpDevelopWithBinaryMissingErrorAnnotation( rxTest )

	rxTest:setTimeLimit( 5 )

	testResolveMissingLocalOnlyXmpDevelopWithErrorAnnotation( rxTest, 'BinaryMissingError' )

end

--------------------------------------------------------------------------------

function WFCatSimpleDocStoreUpdaterTest.rxTestResolveMissingOnlyXmpDevelopWithDirectUploadCompleteAnnotation( rxTest )

	rxTest:setTimeLimit( 5 )

	testResolveMissingLocalOnlyXmpDevelopWithErrorAnnotation( rxTest, 'DirectUploadComplete' )

end

--------------------------------------------------------------------------------

function WFCatSimpleDocStoreUpdaterTest.rxTestResolveMissingLocalOnlyXmpDevelopOther( rxTest )

	rxTest:setTimeLimit( 5 )

	local wfCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest )
	local docStore = wfCatalog:docStore()

	-- will be fixed because xmp develop link is invalid and file is present

	local optArguments = {
		ozDevelopSettingsAreInvalid = true,
		noLocalDevelopSettings = true,
	}

	local invalidDocValue, invalidLocalOnlySettings = WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog, nil, optArguments )
	local invalidExpectedXmpDevelopPath = maybeFixXmpDevelopFileLocationAndGetExpectedPath( wfCatalog, invalidLocalOnlySettings )

	rxTest:waitFor( docStore:setDocValue( invalidDocValue ) )
	invalidDocValue = rxTest:getFirstValue( docStore:docValue( invalidDocValue._id ) )

	-- will not be fixed because xmp develop link is valid and no BinaryMissingError or DirectUploadComplete annotation is present

	optArguments = {
		noLocalDevelopSettings = true,
	}

	local validNoErrorDocValue, validNoErrorLocalOnlySettings = WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog, nil, optArguments )
	maybeFixXmpDevelopFileLocationAndGetExpectedPath( wfCatalog, validNoErrorLocalOnlySettings )

	rxTest:waitFor( docStore:setDocValue( validNoErrorDocValue ) )
	validNoErrorDocValue = rxTest:getFirstValue( docStore:docValue( validNoErrorDocValue._id ) )

	-- will not be fixed because xmp develop link is valid and ozError annotation not BinaryMissingError or DirectUploadComplete

	local validDifferentErrorDocValue, validDifferentErrorLocalOnlySettings = WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog, nil, optArguments )
	KSTableUtils_setNested( validDifferentErrorDocValue, 'RevisionAlreadyExists', '_localOnly', 'ozError', 'subtype' )
	maybeFixXmpDevelopFileLocationAndGetExpectedPath( wfCatalog, validDifferentErrorLocalOnlySettings )

	rxTest:waitFor( docStore:setDocValue( validDifferentErrorDocValue ) )
	validDifferentErrorDocValue = rxTest:getFirstValue( docStore:docValue( validDifferentErrorDocValue._id ) )

	-- will not be fixed because xmp develop link is valid with exists = true and no BinaryMissingError or DirectUploadComplete annotation is present

	local validWithExistsDocValue, validWithExistsLocalOnlySettings = WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog, nil, optArguments )
	KSTableUtils_setNested( validWithExistsDocValue, true, '_serverProvidedMetadata', 'links', '/rels/xmp/develop', 'exists' )
	KSTableUtils_setNested( validWithExistsDocValue, nil, '_serverProvidedMetadata', 'links', '/rels/xmp/develop', 'href' )

	maybeFixXmpDevelopFileLocationAndGetExpectedPath( wfCatalog, validWithExistsLocalOnlySettings )

	rxTest:waitFor( docStore:setDocValue( validWithExistsDocValue ) )
	validWithExistsDocValue = rxTest:getFirstValue( docStore:docValue( validWithExistsDocValue._id ) )

	-- will be fixed because xmp develop link is missing and file is present

	optArguments = {
		noDevelopSettingsLink = true,
		noLocalDevelopSettings = true,
	}

	local missingLinkDocValue, missingLinkLocalOnlySettings = WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog, nil, optArguments )
	local missingLinkExpectedXmpDevelopPath = maybeFixXmpDevelopFileLocationAndGetExpectedPath( wfCatalog, missingLinkLocalOnlySettings )

	rxTest:waitFor( docStore:setDocValue( missingLinkDocValue ) )
	missingLinkDocValue = rxTest:getFirstValue( docStore:docValue( missingLinkDocValue._id ) )

	-- version should be fixed because it has no develop settings link from Oz and it is missing path to develop settings

	local versionDocValue, versionLocalOnlySettings = WFCatVersionTestUtils.createVersionDocument( rxTest, wfCatalog, nil, optArguments )
	local versionExpectedXmpDevelopPath = maybeFixXmpDevelopFileLocationAndGetExpectedPath( wfCatalog, versionLocalOnlySettings )

	rxTest:waitFor( docStore:setDocValue( versionDocValue ) )
	versionDocValue = rxTest:getFirstValue( docStore:docValue( versionDocValue._id ) )

	-- will not be fixed because it does not have externalized xmp develop

	optArguments = {
		internalXmpCameraRaw = true,
	}

	local inlineXmpDocValue = WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog, nil, optArguments )
	rxTest:waitFor( docStore:setDocValue( inlineXmpDocValue ) )
	inlineXmpDocValue = rxTest:getFirstValue( docStore:docValue( inlineXmpDocValue._id ) )

	-- version will not be fixed because it does not have externalized xmp develop

	local inlineXmpVersionDocValue = WFCatVersionTestUtils.createVersionDocument( rxTest, wfCatalog, nil, optArguments )
	rxTest:waitFor( docStore:setDocValue( inlineXmpVersionDocValue ) )
	inlineXmpVersionDocValue = rxTest:getFirstValue( docStore:docValue( inlineXmpVersionDocValue._id ) )

	-- will not be fixed even though xmp develop link is invalid and file is present because file path is already written to _localOnly section

	optArguments = {
		ozDevelopSettingsAreInvalid = true,
	}

	local inLocalOnlyInvalidOnOzDocValue, inLocalOnlyInvalidOnOzLocalOnlySettings = WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog, nil, optArguments )
	rxTest:waitFor( docStore:setDocValue( inLocalOnlyInvalidOnOzDocValue ) )
	inLocalOnlyInvalidOnOzDocValue = rxTest:getFirstValue( docStore:docValue( inLocalOnlyInvalidOnOzDocValue._id ) )

	-- will be fixed because xmp develop link is invalid and _localOnly file information has different sha256

	local localOnlySha256MismatchDocValue, localOnlySha256MismatchLocalOnlySettings = WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog, nil, optArguments )

	local otherSha256 = KSIdGenerator.uuidInLowercaseHex() .. KSIdGenerator.uuidInLowercaseHex()
	KSTableUtils_setNested( localOnlySha256MismatchDocValue, otherSha256, '_localOnly', 'files', 'xmp_develop', expectedSha256Key )
	KSTableUtils_setNested( localOnlySha256MismatchDocValue, 'other/path', '_localOnly', 'files', 'xmp_develop', 'path' )

	local localOnlySha256MismatchExpectedXmpDevelopPath = maybeFixXmpDevelopFileLocationAndGetExpectedPath( wfCatalog, localOnlySha256MismatchLocalOnlySettings )

	rxTest:waitFor( docStore:setDocValue( localOnlySha256MismatchDocValue ) )
	localOnlySha256MismatchDocValue = rxTest:getFirstValue( docStore:docValue( localOnlySha256MismatchDocValue._id ) )

	-- version will not be fixed even though xmp develop link is missing and file is present because file path is already written to _localOnly section

	optArguments = {
		noDevelopSettingsLink = true,
	}

	local versionInLocalOnlyDocValue, versionInLocalOnlyLocalOnlySettings = WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog, nil, optArguments )
	rxTest:waitFor( docStore:setDocValue( versionInLocalOnlyDocValue ) )
	versionInLocalOnlyDocValue = rxTest:getFirstValue( docStore:docValue( versionInLocalOnlyDocValue._id ) )


	-- start the WFCatSimpleDocStoreUpdater

	local updater = WFCatSimpleDocStoreUpdater( docStore, wfCatalog:indexStore(), wfCatalog )
	updater:start()
	rxTest:finally( function()
		updater:close()
	end )


	-- check that invalid = true asset was fixed

	confirmMissingLocalXmpDevelopFixed( rxTest, docStore, invalidDocValue, invalidLocalOnlySettings, invalidExpectedXmpDevelopPath )

	-- check that missing link asset was fixed

	confirmMissingLocalXmpDevelopFixed( rxTest, docStore, missingLinkDocValue, missingLinkLocalOnlySettings, missingLinkExpectedXmpDevelopPath )

	-- check that missing link version was fixed

	confirmMissingLocalXmpDevelopFixed( rxTest, docStore, versionDocValue, versionLocalOnlySettings, versionExpectedXmpDevelopPath )

	-- check asset with invalid xmp develop and wrong sha256 in _localOnly.files.xmp_develop was fixed

	confirmMissingLocalXmpDevelopFixed( rxTest, docStore, localOnlySha256MismatchDocValue, localOnlySha256MismatchLocalOnlySettings, localOnlySha256MismatchExpectedXmpDevelopPath )

	-- check that assets with missing paths that should not have been updated at all were not updated

	for _, unchangedDoc in ipairs( { validNoErrorDocValue, validDifferentErrorDocValue, validWithExistsDocValue, inlineXmpDocValue, inlineXmpVersionDocValue } ) do

		rxTest:expectSingleValue( docStore:docValue( unchangedDoc._id )
			:map( function( docValue )
				return KSTableUtils_derefOpt( docValue, '_localOnly', 'files', 'xmp_develop', 'path' ) == nil and
					KSTableUtils_derefOpt( docValue, '_changeCounter' ) == KSTableUtils_derefOpt( unchangedDoc, '_changeCounter' )
			end ),
			true
		)

	end

	-- ensure documents that did not need to be fixed at all because file is in _localOnly were not touched

	local unchangedDocs = {
		[ inLocalOnlyInvalidOnOzDocValue ] = inLocalOnlyInvalidOnOzLocalOnlySettings,
		[ versionInLocalOnlyDocValue ] = versionInLocalOnlyLocalOnlySettings,
	}
	for unchangedDoc, localOnlySettings in pairs( unchangedDocs ) do
		rxTest:expectSingleValue( docStore:docValue( unchangedDoc._id )
			:map( function( docValue )
				return KSTableUtils_derefOpt( docValue, '_localOnly', 'files', 'xmp_develop', 'path' ) == localOnlySettings.xmpDevelopSettingsRelPath and
					KSTableUtils_derefOpt( docValue, '_localOnly', 'files', 'xmp_develop', 'fileSize' ) == localOnlySettings.xmpDevelopSettingsFileSize and
					KSTableUtils_derefOpt( docValue, '_localOnly', 'files', 'xmp_develop', expectedSha256Key ) == localOnlySettings.developSettingsSha256 and
					KSTableUtils_derefOpt( docValue, '_changeCounter' ) == KSTableUtils_derefOpt( unchangedDoc, '_changeCounter' )
			end ),
			true
		)
	end

	-- check that the correct number of overlays were applied

	rxTest:expectEqual(
		{ missingLocalOnlyXmpDevelop = 4, numOverlaysApplied = 4 },
		updater:DEBUG_getUpdatesApplied()
	)

end

--------------------------------------------------------------------------------

function WFCatSimpleDocStoreUpdaterTest.rxTestResolveMissingLocalOnlyXmpDevelopInChunksOf100( rxTest )

	rxTest:setTimeLimit( 10 )

	local wfCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest )
	local docStore = wfCatalog:docStore()

	local optArguments = {
		noLocalDevelopSettings = true,
	}

	local docsToRepair = {}

	for i = 1,110,1 do

		local docValue, localOnlySettings = WFCatAssetTestUtils.createAssetDocument( rxTest, wfCatalog, nil, optArguments )
		KSTableUtils_setNested( docValue, 'BinaryMissingError', '_localOnly', 'ozError', 'subtype' )

		local otherSha256 = KSIdGenerator.uuidInLowercaseHex() .. KSIdGenerator.uuidInLowercaseHex()
		KSTableUtils_setNested( docValue, otherSha256, '_serverProvidedMetadata', 'links', '/rels/xmp/develop', 'sha256' )

		maybeFixXmpDevelopFileLocationAndGetExpectedPath( wfCatalog, localOnlySettings )
		rxTest:waitFor( docStore:setDocValue( docValue ) )

		docsToRepair[ #docsToRepair + 1 ] = docValue

	end


	-- start the WFCatSimpleDocStoreUpdater

	local updater = WFCatSimpleDocStoreUpdater( docStore, wfCatalog:indexStore(), wfCatalog )
	updater:start()
	rxTest:finally( function()
		updater:close()
	end )


	-- check that each asset had path set

	for _, assetDocValue in ipairs( docsToRepair ) do

		local docObserver = rxTest:observe( docStore:ongoingDocValue( assetDocValue._id )
			:map( function( docValue )
				return KSTableUtils_derefOpt( docValue, '_localOnly', 'files', 'xmp_develop', 'path' ) ~= nil
			end ) )
		docObserver:expectDataWithinTime( 3, true )

	end

	-- check that the correct number of overlays were applied

	rxTest:expectEqual(
		{ missingLocalOnlyXmpDevelop = 110, numOverlaysApplied = 110 },
		updater:DEBUG_getUpdatesApplied()
	)

end

--------------------------------------------------------------------------------

return WFRxTestCase.wrapSuite( 'WFCatSimpleDocStoreUpdaterTest', WFCatSimpleDocStoreUpdaterTest )
