var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
import { EntityPermissionType, Metadata, FieldValueCollection, RunView } from '@memberjunction/core';
import { NormalizeUUID } from '@memberjunction/global';
import { Arg, Ctx, DeleteOptionsInput, Field, FieldResolver, InputType, Int, Mutation, ObjectType, PubSub, PubSubEngine, Query, Resolver, Root, } from '@memberjunction/server';
import { createDownloadUrl, createUploadUrl, deleteObject, moveObject, copyObject, listObjects, copyObjectBetweenProviders, searchAcrossAccounts, initializeDriverWithAccountCredentials, } from '@memberjunction/storage';
import { CreateMJFileInput, MJFileResolver as FileResolverBase, MJFile_, UpdateMJFileInput } from '../generated/generated.js';
import { FieldMapper } from '@memberjunction/graphql-dataprovider';
import { GetReadOnlyProvider } from '../util.js';
let CreateUploadURLInput = class CreateUploadURLInput {
};
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], CreateUploadURLInput.prototype, "FileID", void 0);
CreateUploadURLInput = __decorate([
    InputType()
], CreateUploadURLInput);
export { CreateUploadURLInput };
let CreateFilePayload = class CreateFilePayload {
};
__decorate([
    Field(() => MJFile_),
    __metadata("design:type", MJFile_)
], CreateFilePayload.prototype, "File", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], CreateFilePayload.prototype, "UploadUrl", void 0);
__decorate([
    Field(() => Boolean),
    __metadata("design:type", Boolean)
], CreateFilePayload.prototype, "NameExists", void 0);
CreateFilePayload = __decorate([
    ObjectType()
], CreateFilePayload);
export { CreateFilePayload };
let FileExt = class FileExt extends MJFile_ {
};
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], FileExt.prototype, "DownloadUrl", void 0);
FileExt = __decorate([
    ObjectType()
], FileExt);
export { FileExt };
let StorageObjectMetadata = class StorageObjectMetadata {
};
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], StorageObjectMetadata.prototype, "name", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], StorageObjectMetadata.prototype, "path", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], StorageObjectMetadata.prototype, "fullPath", void 0);
__decorate([
    Field(() => Int),
    __metadata("design:type", Number)
], StorageObjectMetadata.prototype, "size", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], StorageObjectMetadata.prototype, "contentType", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], StorageObjectMetadata.prototype, "lastModified", void 0);
__decorate([
    Field(() => Boolean),
    __metadata("design:type", Boolean)
], StorageObjectMetadata.prototype, "isDirectory", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], StorageObjectMetadata.prototype, "etag", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], StorageObjectMetadata.prototype, "cacheControl", void 0);
StorageObjectMetadata = __decorate([
    ObjectType()
], StorageObjectMetadata);
export { StorageObjectMetadata };
let StorageListResult = class StorageListResult {
};
__decorate([
    Field(() => [StorageObjectMetadata]),
    __metadata("design:type", Array)
], StorageListResult.prototype, "objects", void 0);
__decorate([
    Field(() => [String]),
    __metadata("design:type", Array)
], StorageListResult.prototype, "prefixes", void 0);
StorageListResult = __decorate([
    ObjectType()
], StorageListResult);
export { StorageListResult };
let ListStorageObjectsInput = class ListStorageObjectsInput {
};
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], ListStorageObjectsInput.prototype, "AccountID", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], ListStorageObjectsInput.prototype, "Prefix", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], ListStorageObjectsInput.prototype, "Delimiter", void 0);
ListStorageObjectsInput = __decorate([
    InputType()
], ListStorageObjectsInput);
export { ListStorageObjectsInput };
let CreatePreAuthDownloadUrlInput = class CreatePreAuthDownloadUrlInput {
};
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], CreatePreAuthDownloadUrlInput.prototype, "AccountID", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], CreatePreAuthDownloadUrlInput.prototype, "ObjectName", void 0);
CreatePreAuthDownloadUrlInput = __decorate([
    InputType()
], CreatePreAuthDownloadUrlInput);
export { CreatePreAuthDownloadUrlInput };
let CreatePreAuthUploadUrlInput = class CreatePreAuthUploadUrlInput {
};
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], CreatePreAuthUploadUrlInput.prototype, "AccountID", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], CreatePreAuthUploadUrlInput.prototype, "ObjectName", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], CreatePreAuthUploadUrlInput.prototype, "ContentType", void 0);
CreatePreAuthUploadUrlInput = __decorate([
    InputType()
], CreatePreAuthUploadUrlInput);
export { CreatePreAuthUploadUrlInput };
let CreatePreAuthUploadUrlPayload = class CreatePreAuthUploadUrlPayload {
};
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], CreatePreAuthUploadUrlPayload.prototype, "UploadUrl", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], CreatePreAuthUploadUrlPayload.prototype, "ProviderKey", void 0);
CreatePreAuthUploadUrlPayload = __decorate([
    ObjectType()
], CreatePreAuthUploadUrlPayload);
export { CreatePreAuthUploadUrlPayload };
let DeleteStorageObjectInput = class DeleteStorageObjectInput {
};
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], DeleteStorageObjectInput.prototype, "AccountID", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], DeleteStorageObjectInput.prototype, "ObjectName", void 0);
DeleteStorageObjectInput = __decorate([
    InputType()
], DeleteStorageObjectInput);
export { DeleteStorageObjectInput };
let MoveStorageObjectInput = class MoveStorageObjectInput {
};
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], MoveStorageObjectInput.prototype, "AccountID", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], MoveStorageObjectInput.prototype, "OldName", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], MoveStorageObjectInput.prototype, "NewName", void 0);
MoveStorageObjectInput = __decorate([
    InputType()
], MoveStorageObjectInput);
export { MoveStorageObjectInput };
let CopyStorageObjectInput = class CopyStorageObjectInput {
};
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], CopyStorageObjectInput.prototype, "AccountID", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], CopyStorageObjectInput.prototype, "SourceName", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], CopyStorageObjectInput.prototype, "DestinationName", void 0);
CopyStorageObjectInput = __decorate([
    InputType()
], CopyStorageObjectInput);
export { CopyStorageObjectInput };
let CreateDirectoryInput = class CreateDirectoryInput {
};
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], CreateDirectoryInput.prototype, "AccountID", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], CreateDirectoryInput.prototype, "Path", void 0);
CreateDirectoryInput = __decorate([
    InputType()
], CreateDirectoryInput);
export { CreateDirectoryInput };
let CopyObjectBetweenAccountsInput = class CopyObjectBetweenAccountsInput {
};
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], CopyObjectBetweenAccountsInput.prototype, "SourceAccountID", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], CopyObjectBetweenAccountsInput.prototype, "DestinationAccountID", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], CopyObjectBetweenAccountsInput.prototype, "SourcePath", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], CopyObjectBetweenAccountsInput.prototype, "DestinationPath", void 0);
CopyObjectBetweenAccountsInput = __decorate([
    InputType()
], CopyObjectBetweenAccountsInput);
export { CopyObjectBetweenAccountsInput };
let CopyObjectBetweenAccountsPayload = class CopyObjectBetweenAccountsPayload {
};
__decorate([
    Field(() => Boolean),
    __metadata("design:type", Boolean)
], CopyObjectBetweenAccountsPayload.prototype, "success", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], CopyObjectBetweenAccountsPayload.prototype, "message", void 0);
__decorate([
    Field(() => Int, { nullable: true }),
    __metadata("design:type", Number)
], CopyObjectBetweenAccountsPayload.prototype, "bytesTransferred", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], CopyObjectBetweenAccountsPayload.prototype, "sourceAccount", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], CopyObjectBetweenAccountsPayload.prototype, "destinationAccount", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], CopyObjectBetweenAccountsPayload.prototype, "sourcePath", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], CopyObjectBetweenAccountsPayload.prototype, "destinationPath", void 0);
CopyObjectBetweenAccountsPayload = __decorate([
    ObjectType()
], CopyObjectBetweenAccountsPayload);
export { CopyObjectBetweenAccountsPayload };
let SearchAcrossAccountsInput = class SearchAcrossAccountsInput {
};
__decorate([
    Field(() => [String]),
    __metadata("design:type", Array)
], SearchAcrossAccountsInput.prototype, "AccountIDs", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], SearchAcrossAccountsInput.prototype, "Query", void 0);
__decorate([
    Field(() => Int, { nullable: true }),
    __metadata("design:type", Number)
], SearchAcrossAccountsInput.prototype, "MaxResultsPerAccount", void 0);
__decorate([
    Field(() => [String], { nullable: true }),
    __metadata("design:type", Array)
], SearchAcrossAccountsInput.prototype, "FileTypes", void 0);
__decorate([
    Field(() => Boolean, { nullable: true }),
    __metadata("design:type", Boolean)
], SearchAcrossAccountsInput.prototype, "SearchContent", void 0);
SearchAcrossAccountsInput = __decorate([
    InputType()
], SearchAcrossAccountsInput);
export { SearchAcrossAccountsInput };
let FileSearchResultPayload = class FileSearchResultPayload {
};
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], FileSearchResultPayload.prototype, "path", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], FileSearchResultPayload.prototype, "name", void 0);
__decorate([
    Field(() => Int),
    __metadata("design:type", Number)
], FileSearchResultPayload.prototype, "size", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], FileSearchResultPayload.prototype, "contentType", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], FileSearchResultPayload.prototype, "lastModified", void 0);
__decorate([
    Field(() => Number, { nullable: true }),
    __metadata("design:type", Number)
], FileSearchResultPayload.prototype, "relevance", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], FileSearchResultPayload.prototype, "excerpt", void 0);
__decorate([
    Field(() => Boolean, { nullable: true }),
    __metadata("design:type", Boolean)
], FileSearchResultPayload.prototype, "matchInFilename", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], FileSearchResultPayload.prototype, "objectId", void 0);
FileSearchResultPayload = __decorate([
    ObjectType()
], FileSearchResultPayload);
export { FileSearchResultPayload };
let AccountSearchResultPayload = class AccountSearchResultPayload {
};
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], AccountSearchResultPayload.prototype, "accountID", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], AccountSearchResultPayload.prototype, "accountName", void 0);
__decorate([
    Field(() => Boolean),
    __metadata("design:type", Boolean)
], AccountSearchResultPayload.prototype, "success", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], AccountSearchResultPayload.prototype, "errorMessage", void 0);
__decorate([
    Field(() => [FileSearchResultPayload]),
    __metadata("design:type", Array)
], AccountSearchResultPayload.prototype, "results", void 0);
__decorate([
    Field(() => Int, { nullable: true }),
    __metadata("design:type", Number)
], AccountSearchResultPayload.prototype, "totalMatches", void 0);
__decorate([
    Field(() => Boolean),
    __metadata("design:type", Boolean)
], AccountSearchResultPayload.prototype, "hasMore", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], AccountSearchResultPayload.prototype, "nextPageToken", void 0);
AccountSearchResultPayload = __decorate([
    ObjectType()
], AccountSearchResultPayload);
export { AccountSearchResultPayload };
let SearchAcrossAccountsPayload = class SearchAcrossAccountsPayload {
};
__decorate([
    Field(() => [AccountSearchResultPayload]),
    __metadata("design:type", Array)
], SearchAcrossAccountsPayload.prototype, "accountResults", void 0);
__decorate([
    Field(() => Int),
    __metadata("design:type", Number)
], SearchAcrossAccountsPayload.prototype, "totalResultsReturned", void 0);
__decorate([
    Field(() => Int),
    __metadata("design:type", Number)
], SearchAcrossAccountsPayload.prototype, "successfulAccounts", void 0);
__decorate([
    Field(() => Int),
    __metadata("design:type", Number)
], SearchAcrossAccountsPayload.prototype, "failedAccounts", void 0);
SearchAcrossAccountsPayload = __decorate([
    ObjectType()
], SearchAcrossAccountsPayload);
export { SearchAcrossAccountsPayload };
let FileResolver = class FileResolver extends FileResolverBase {
    /**
     * Builds UserContextOptions for storage operations that may require OAuth authentication.
     * This passes the current user's ID and context to allow the storage utilities to
     * load user-specific OAuth tokens for providers like Google Drive.
     */
    buildUserContext(context) {
        const user = this.GetUserFromPayload(context.userPayload);
        return {
            userID: user.ID,
            contextUser: user,
        };
    }
    /**
     * Builds ExtendedUserContextOptions that includes the account entity for enterprise model.
     * This is required for OAuth providers using the Credential Engine to decrypt credentials.
     */
    buildExtendedUserContext(context, accountEntity) {
        const user = this.GetUserFromPayload(context.userPayload);
        return {
            userID: user.ID,
            contextUser: user,
            accountEntity,
        };
    }
    /**
     * Loads a FileStorageAccount and its associated FileStorageProvider.
     * This is the standard way to get provider information in the enterprise model.
     * @param accountId The ID of the FileStorageAccount
     * @param context The AppContext containing provider info
     * @returns Object containing both the account and provider entities
     */
    async loadAccountAndProvider(accountId, context) {
        const md = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
        const user = this.GetUserFromPayload(context.userPayload);
        // Load the account entity
        const account = await md.GetEntityObject('MJ: File Storage Accounts', user);
        const loaded = await account.Load(accountId);
        if (!loaded) {
            throw new Error(`Storage account with ID ${accountId} not found`);
        }
        // Load the provider entity from the account's ProviderID
        const provider = await md.GetEntityObject('MJ: File Storage Providers', user);
        await provider.Load(account.ProviderID);
        return { account, provider };
    }
    async CreateFile(input, context, pubSub) {
        // Check to see if there's already an object with that name
        const provider = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
        const user = this.GetUserFromPayload(context.userPayload);
        const fileEntity = await provider.GetEntityObject('MJ: Files', user);
        const providerEntity = await provider.GetEntityObject('MJ: File Storage Providers', user);
        fileEntity.CheckPermissions(EntityPermissionType.Create, true);
        const [sameName] = await this.findBy(provider, 'MJ: Files', { Name: input.Name, ProviderID: input.ProviderID }, context.userPayload.userRecord);
        const NameExists = Boolean(sameName);
        const success = fileEntity.NewRecord(FieldValueCollection.FromObject({ ...input, Status: 'Pending' }));
        // If there's a problem creating the file record, the base resolver will return null
        if (!success) {
            return null;
        }
        // Create the upload URL and get the record updates (provider key, content type, etc)
        const userContext = this.buildUserContext(context);
        const { updatedInput, UploadUrl } = await createUploadUrl(providerEntity, fileEntity, userContext);
        // Save the file record with the updated input
        const mapper = new FieldMapper();
        fileEntity.SetMany(mapper.ReverseMapFields({ ...updatedInput }), true, true);
        await fileEntity.Save();
        const File = mapper.MapFields({ ...fileEntity.GetAll() });
        return { File, UploadUrl, NameExists };
    }
    async DownloadUrl(file, context) {
        const md = new Metadata();
        const user = this.GetUserFromPayload(context.userPayload);
        const fileEntity = await md.GetEntityObject('MJ: Files', user);
        fileEntity.CheckPermissions(EntityPermissionType.Read, true);
        const providerEntity = await md.GetEntityObject('MJ: File Storage Providers', user);
        await providerEntity.Load(file.ProviderID);
        const userContext = this.buildUserContext(context);
        const url = await createDownloadUrl(providerEntity, file.ProviderKey ?? file.Name, userContext);
        return url;
    }
    async UpdateFile(input, context, pubSub) {
        // if the name is changing, rename the target object as well
        const md = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
        const user = this.GetUserFromPayload(context.userPayload);
        const fileEntity = await md.GetEntityObject('MJ: Files', user);
        fileEntity.CheckPermissions(EntityPermissionType.Update, true);
        await fileEntity.Load(input.ID);
        if (fileEntity.Name !== input.Name) {
            const providerEntity = await md.GetEntityObject('MJ: File Storage Providers', user);
            await providerEntity.Load(fileEntity.ProviderID);
            const userContext = this.buildUserContext(context);
            const success = await moveObject(providerEntity, fileEntity.Name, input.Name, userContext);
            if (!success) {
                throw new Error('Error updating object name');
            }
        }
        const updatedFile = await super.UpdateMJFile(input, context, pubSub);
        return updatedFile;
    }
    async DeleteFile(ID, options, context, pubSub) {
        const md = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
        const userInfo = this.GetUserFromPayload(context.userPayload);
        const fileEntity = await md.GetEntityObject('MJ: Files', userInfo);
        await fileEntity.Load(ID);
        if (!fileEntity) {
            return null;
        }
        fileEntity.CheckPermissions(EntityPermissionType.Delete, true);
        // Only delete the object from the provider if it's actually been uploaded
        if (fileEntity.Status === 'Uploaded') {
            const providerEntity = await md.GetEntityObject('MJ: File Storage Providers', userInfo);
            await providerEntity.Load(fileEntity.ProviderID);
            const userContext = this.buildUserContext(context);
            await deleteObject(providerEntity, fileEntity.ProviderKey ?? fileEntity.Name, userContext);
        }
        return super.DeleteMJFile(ID, options, context, pubSub);
    }
    async ListStorageObjects(input, context) {
        console.log('[FileResolver] ListStorageObjects called with:', {
            AccountID: input.AccountID,
            Prefix: input.Prefix,
            Delimiter: input.Delimiter,
        });
        const md = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
        const user = this.GetUserFromPayload(context.userPayload);
        // Load the account and its provider
        const { account, provider: providerEntity } = await this.loadAccountAndProvider(input.AccountID, context);
        console.log('[FileResolver] Provider loaded:', {
            Name: providerEntity.Name,
            ServerDriverKey: providerEntity.ServerDriverKey,
            HasConfiguration: !!providerEntity.Get('Configuration'),
        });
        // Check permissions - user must have read access to Files entity
        const fileEntity = await md.GetEntityObject('MJ: Files', user);
        fileEntity.CheckPermissions(EntityPermissionType.Read, true);
        // Call the storage provider to list objects with extended user context (includes account for credential lookup)
        const userContext = this.buildExtendedUserContext(context, account);
        const result = await listObjects(providerEntity, input.Prefix, input.Delimiter || '/', userContext);
        console.log('[FileResolver] listObjects result:', {
            objectsCount: result.objects.length,
            prefixesCount: result.prefixes.length,
            objects: result.objects.map((o) => ({ name: o.name, isDirectory: o.isDirectory })),
            prefixes: result.prefixes,
        });
        // Convert Date objects to ISO strings for GraphQL
        const objects = result.objects.map((obj) => ({
            ...obj,
            lastModified: obj.lastModified.toISOString(),
        }));
        return {
            objects,
            prefixes: result.prefixes,
        };
    }
    async CreatePreAuthDownloadUrl(input, context) {
        const md = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
        const user = this.GetUserFromPayload(context.userPayload);
        // Load the account and its provider
        const { account, provider: providerEntity } = await this.loadAccountAndProvider(input.AccountID, context);
        // Check permissions
        const fileEntity = await md.GetEntityObject('MJ: Files', user);
        fileEntity.CheckPermissions(EntityPermissionType.Read, true);
        // Create download URL with extended user context (includes account for credential lookup)
        const userContext = this.buildExtendedUserContext(context, account);
        const downloadUrl = await createDownloadUrl(providerEntity, input.ObjectName, userContext);
        return downloadUrl;
    }
    async CreatePreAuthUploadUrl(input, context) {
        const md = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
        const user = this.GetUserFromPayload(context.userPayload);
        // Load the account and its provider
        const { account, provider: providerEntity } = await this.loadAccountAndProvider(input.AccountID, context);
        // Check permissions
        const fileEntity = await md.GetEntityObject('MJ: Files', user);
        fileEntity.CheckPermissions(EntityPermissionType.Create, true);
        // Create upload URL with extended user context (includes account for credential lookup)
        const userContext = this.buildExtendedUserContext(context, account);
        const { UploadUrl, updatedInput } = await createUploadUrl(providerEntity, {
            ID: '', // Not needed for direct upload
            Name: input.ObjectName,
            ProviderID: providerEntity.ID,
            ContentType: input.ContentType,
        }, userContext);
        // Extract ProviderKey if it exists (spread into updatedInput by createUploadUrl)
        const providerKey = updatedInput.ProviderKey;
        return {
            UploadUrl,
            ProviderKey: providerKey,
        };
    }
    async DeleteStorageObject(input, context) {
        console.log('[FileResolver] DeleteStorageObject called:', input);
        const md = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
        const user = this.GetUserFromPayload(context.userPayload);
        // Load the account and its provider
        const { account, provider: providerEntity } = await this.loadAccountAndProvider(input.AccountID, context);
        console.log('[FileResolver] Provider loaded:', {
            providerID: providerEntity.ID,
            providerName: providerEntity.Name,
            serverDriverKey: providerEntity.ServerDriverKey,
        });
        // Check permissions
        const fileEntity = await md.GetEntityObject('MJ: Files', user);
        fileEntity.CheckPermissions(EntityPermissionType.Delete, true);
        console.log('[FileResolver] Permissions checked, calling deleteObject...');
        // Delete the object with extended user context (includes account for credential lookup)
        const userContext = this.buildExtendedUserContext(context, account);
        const success = await deleteObject(providerEntity, input.ObjectName, userContext);
        console.log('[FileResolver] deleteObject returned:', success);
        return success;
    }
    async MoveStorageObject(input, context) {
        const md = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
        const user = this.GetUserFromPayload(context.userPayload);
        // Load the account and its provider
        const { account, provider: providerEntity } = await this.loadAccountAndProvider(input.AccountID, context);
        // Check permissions
        const fileEntity = await md.GetEntityObject('MJ: Files', user);
        fileEntity.CheckPermissions(EntityPermissionType.Update, true);
        // Move the object with extended user context (includes account for credential lookup)
        const userContext = this.buildExtendedUserContext(context, account);
        const success = await moveObject(providerEntity, input.OldName, input.NewName, userContext);
        return success;
    }
    async CopyStorageObject(input, context) {
        const md = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
        const user = this.GetUserFromPayload(context.userPayload);
        // Load the account and its provider
        const { account, provider: providerEntity } = await this.loadAccountAndProvider(input.AccountID, context);
        // Check permissions - copying requires both read (source) and create (destination)
        const fileEntity = await md.GetEntityObject('MJ: Files', user);
        fileEntity.CheckPermissions(EntityPermissionType.Read, true);
        fileEntity.CheckPermissions(EntityPermissionType.Create, true);
        // Copy the object with extended user context (includes account for credential lookup)
        const userContext = this.buildExtendedUserContext(context, account);
        const success = await copyObject(providerEntity, input.SourceName, input.DestinationName, userContext);
        return success;
    }
    async CreateDirectory(input, context) {
        const md = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
        const user = this.GetUserFromPayload(context.userPayload);
        // Load the account and its provider
        const { account: accountEntity, provider: providerEntity } = await this.loadAccountAndProvider(input.AccountID, context);
        // Check permissions
        const fileEntity = await md.GetEntityObject('MJ: Files', user);
        fileEntity.CheckPermissions(EntityPermissionType.Create, true);
        // Initialize driver with account-based credentials from Credential Engine
        const driver = await initializeDriverWithAccountCredentials({
            accountEntity,
            providerEntity,
            contextUser: user,
        });
        const success = await driver.CreateDirectory(input.Path);
        return success;
    }
    async CopyObjectBetweenAccounts(input, context) {
        console.log('[FileResolver] CopyObjectBetweenAccounts called:', {
            sourceAccountID: input.SourceAccountID,
            destinationAccountID: input.DestinationAccountID,
            sourcePath: input.SourcePath,
            destinationPath: input.DestinationPath,
        });
        const md = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
        const user = this.GetUserFromPayload(context.userPayload);
        // Check permissions - copying requires both read (source) and create (destination)
        const fileEntity = await md.GetEntityObject('MJ: Files', user);
        fileEntity.CheckPermissions(EntityPermissionType.Read, true);
        fileEntity.CheckPermissions(EntityPermissionType.Create, true);
        // Load the source account and its provider
        const { account: sourceAccount, provider: sourceProviderEntity } = await this.loadAccountAndProvider(input.SourceAccountID, context);
        // Load the destination account and its provider
        const { account: destAccount, provider: destProviderEntity } = await this.loadAccountAndProvider(input.DestinationAccountID, context);
        // Perform the cross-provider copy with extended user context (includes account for credential lookup)
        const sourceUserContext = this.buildExtendedUserContext(context, sourceAccount);
        const destUserContext = this.buildExtendedUserContext(context, destAccount);
        const result = await copyObjectBetweenProviders(sourceProviderEntity, destProviderEntity, input.SourcePath, input.DestinationPath, {
            sourceUserContext,
            destinationUserContext: destUserContext,
        });
        console.log('[FileResolver] CopyObjectBetweenAccounts result:', result);
        return {
            success: result.success,
            message: result.message,
            bytesTransferred: result.bytesTransferred,
            sourceAccount: sourceAccount.Name,
            destinationAccount: destAccount.Name,
            sourcePath: result.sourcePath,
            destinationPath: result.destinationPath,
        };
    }
    async SearchAcrossAccounts(input, context) {
        console.log('[FileResolver] SearchAcrossAccounts called:', {
            accountIDs: input.AccountIDs,
            query: input.Query,
            maxResultsPerAccount: input.MaxResultsPerAccount,
            fileTypes: input.FileTypes,
            searchContent: input.SearchContent,
        });
        const md = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
        const user = this.GetUserFromPayload(context.userPayload);
        // Check permissions - searching requires read access
        const fileEntity = await md.GetEntityObject('MJ: Files', user);
        fileEntity.CheckPermissions(EntityPermissionType.Read, true);
        // Load all requested account entities in a single query
        const rv = new RunView();
        const quotedIDs = input.AccountIDs.map((id) => `'${id}'`).join(', ');
        const accountResult = await rv.RunView({
            EntityName: 'MJ: File Storage Accounts',
            ExtraFilter: `ID IN (${quotedIDs})`,
            ResultType: 'entity_object',
        }, user);
        if (!accountResult.Success) {
            throw new Error(`Failed to load storage accounts: ${accountResult.ErrorMessage}`);
        }
        const accountEntities = accountResult.Results;
        if (accountEntities.length === 0) {
            throw new Error('No valid storage accounts found for the provided IDs');
        }
        // Log any accounts that weren't found
        if (accountEntities.length < input.AccountIDs.length) {
            const foundIDs = new Set(accountEntities.map((a) => NormalizeUUID(a.ID)));
            const missingIDs = input.AccountIDs.filter((id) => !foundIDs.has(NormalizeUUID(id)));
            console.warn(`[FileResolver] Accounts not found: ${missingIDs.join(', ')}`);
        }
        // Load providers for all accounts
        const providerIDs = [...new Set(accountEntities.map((a) => a.ProviderID))];
        const quotedProviderIDs = providerIDs.map((id) => `'${id}'`).join(', ');
        const providerResult = await rv.RunView({
            EntityName: 'MJ: File Storage Providers',
            ExtraFilter: `ID IN (${quotedProviderIDs})`,
            ResultType: 'entity_object',
        }, user);
        if (!providerResult.Success) {
            throw new Error(`Failed to load storage providers: ${providerResult.ErrorMessage}`);
        }
        const providerMap = new Map();
        for (const provider of providerResult.Results) {
            providerMap.set(provider.ID, provider);
        }
        // Build account/provider pairs for the search
        const accountInputs = [];
        for (const account of accountEntities) {
            const provider = providerMap.get(account.ProviderID);
            if (provider) {
                accountInputs.push({ accountEntity: account, providerEntity: provider });
            }
        }
        // Execute the search across all accounts with account-based credentials
        const result = await searchAcrossAccounts(accountInputs, input.Query, {
            maxResultsPerAccount: input.MaxResultsPerAccount,
            fileTypes: input.FileTypes,
            searchContent: input.SearchContent,
            contextUser: user,
        });
        console.log('[FileResolver] SearchAcrossAccounts result:', {
            totalResultsReturned: result.totalResultsReturned,
            successfulAccounts: result.successfulAccounts,
            failedAccounts: result.failedAccounts,
        });
        // Convert results to GraphQL payload format
        const accountResults = result.accountResults.map((ar) => ({
            accountID: ar.accountID,
            accountName: ar.accountName,
            success: ar.success,
            errorMessage: ar.errorMessage,
            results: ar.results.map((r) => ({
                path: r.path,
                name: r.name,
                size: r.size,
                contentType: r.contentType,
                lastModified: r.lastModified.toISOString(),
                relevance: r.relevance,
                excerpt: r.excerpt,
                matchInFilename: r.matchInFilename,
                objectId: r.objectId,
            })),
            totalMatches: ar.totalMatches,
            hasMore: ar.hasMore,
            nextPageToken: ar.nextPageToken,
        }));
        return {
            accountResults,
            totalResultsReturned: result.totalResultsReturned,
            successfulAccounts: result.successfulAccounts,
            failedAccounts: result.failedAccounts,
        };
    }
};
__decorate([
    Mutation(() => CreateFilePayload),
    __param(0, Arg('input', () => CreateMJFileInput)),
    __param(1, Ctx()),
    __param(2, PubSub()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [CreateMJFileInput, Object, PubSubEngine]),
    __metadata("design:returntype", Promise)
], FileResolver.prototype, "CreateFile", null);
__decorate([
    FieldResolver(() => String),
    __param(0, Root()),
    __param(1, Ctx()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [MJFile_, Object]),
    __metadata("design:returntype", Promise)
], FileResolver.prototype, "DownloadUrl", null);
__decorate([
    Mutation(() => MJFile_),
    __param(0, Arg('input', () => UpdateMJFileInput)),
    __param(1, Ctx()),
    __param(2, PubSub()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [UpdateMJFileInput, Object, PubSubEngine]),
    __metadata("design:returntype", Promise)
], FileResolver.prototype, "UpdateFile", null);
__decorate([
    Mutation(() => MJFile_),
    __param(0, Arg('ID', () => String)),
    __param(1, Arg('options___', () => DeleteOptionsInput)),
    __param(2, Ctx()),
    __param(3, PubSub()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, DeleteOptionsInput, Object, PubSubEngine]),
    __metadata("design:returntype", Promise)
], FileResolver.prototype, "DeleteFile", null);
__decorate([
    Query(() => StorageListResult),
    __param(0, Arg('input', () => ListStorageObjectsInput)),
    __param(1, Ctx()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [ListStorageObjectsInput, Object]),
    __metadata("design:returntype", Promise)
], FileResolver.prototype, "ListStorageObjects", null);
__decorate([
    Query(() => String),
    __param(0, Arg('input', () => CreatePreAuthDownloadUrlInput)),
    __param(1, Ctx()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [CreatePreAuthDownloadUrlInput, Object]),
    __metadata("design:returntype", Promise)
], FileResolver.prototype, "CreatePreAuthDownloadUrl", null);
__decorate([
    Mutation(() => CreatePreAuthUploadUrlPayload),
    __param(0, Arg('input', () => CreatePreAuthUploadUrlInput)),
    __param(1, Ctx()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [CreatePreAuthUploadUrlInput, Object]),
    __metadata("design:returntype", Promise)
], FileResolver.prototype, "CreatePreAuthUploadUrl", null);
__decorate([
    Mutation(() => Boolean),
    __param(0, Arg('input', () => DeleteStorageObjectInput)),
    __param(1, Ctx()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [DeleteStorageObjectInput, Object]),
    __metadata("design:returntype", Promise)
], FileResolver.prototype, "DeleteStorageObject", null);
__decorate([
    Mutation(() => Boolean),
    __param(0, Arg('input', () => MoveStorageObjectInput)),
    __param(1, Ctx()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [MoveStorageObjectInput, Object]),
    __metadata("design:returntype", Promise)
], FileResolver.prototype, "MoveStorageObject", null);
__decorate([
    Mutation(() => Boolean),
    __param(0, Arg('input', () => CopyStorageObjectInput)),
    __param(1, Ctx()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [CopyStorageObjectInput, Object]),
    __metadata("design:returntype", Promise)
], FileResolver.prototype, "CopyStorageObject", null);
__decorate([
    Mutation(() => Boolean),
    __param(0, Arg('input', () => CreateDirectoryInput)),
    __param(1, Ctx()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [CreateDirectoryInput, Object]),
    __metadata("design:returntype", Promise)
], FileResolver.prototype, "CreateDirectory", null);
__decorate([
    Mutation(() => CopyObjectBetweenAccountsPayload),
    __param(0, Arg('input', () => CopyObjectBetweenAccountsInput)),
    __param(1, Ctx()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [CopyObjectBetweenAccountsInput, Object]),
    __metadata("design:returntype", Promise)
], FileResolver.prototype, "CopyObjectBetweenAccounts", null);
__decorate([
    Query(() => SearchAcrossAccountsPayload),
    __param(0, Arg('input', () => SearchAcrossAccountsInput)),
    __param(1, Ctx()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [SearchAcrossAccountsInput, Object]),
    __metadata("design:returntype", Promise)
], FileResolver.prototype, "SearchAcrossAccounts", null);
FileResolver = __decorate([
    Resolver(MJFile_)
], FileResolver);
export { FileResolver };
//# sourceMappingURL=FileResolver.js.map