import { Meteor } from 'meteor/meteor';
import { ReactiveCache } from '/imports/reactiveCache';
import { Attachments, fileStoreStrategyFactory } from '/models/attachments';
import { moveToStorage } from '/models/lib/fileStoreStrategy';
import { STORAGE_NAME_FILESYSTEM, STORAGE_NAME_GRIDFS, STORAGE_NAME_S3 } from '/models/lib/fileStoreStrategy';
import AttachmentStorageSettings from '/models/attachmentStorageSettings';
import fs from 'fs';
import path from 'path';
import { ObjectID } from 'bson';

// Attachment API methods
if (Meteor.isServer) {
  Meteor.methods({
    // Upload attachment via API
    'api.attachment.upload'(boardId, swimlaneId, listId, cardId, fileData, fileName, fileType, storageBackend) {
      if (!this.userId) {
        throw new Meteor.Error('not-authorized', 'Must be logged in');
      }

      // Validate parameters
      if (!boardId || !swimlaneId || !listId || !cardId || !fileData || !fileName) {
        throw new Meteor.Error('invalid-parameters', 'Missing required parameters');
      }

      // Check if user has permission to modify the card
      const card = ReactiveCache.getCard(cardId);
      if (!card) {
        throw new Meteor.Error('card-not-found', 'Card not found');
      }

      const board = ReactiveCache.getBoard(boardId);
      if (!board) {
        throw new Meteor.Error('board-not-found', 'Board not found');
      }

      // Check permissions
      if (!board.isBoardMember(this.userId)) {
        throw new Meteor.Error('not-authorized', 'You do not have permission to modify this card');
      }

      // Check if board allows attachments
      if (!board.allowsAttachments) {
        throw new Meteor.Error('attachments-not-allowed', 'Attachments are not allowed on this board');
      }

      // Get default storage backend if not specified
      let targetStorage = storageBackend;
      if (!targetStorage) {
        try {
          const settings = AttachmentStorageSettings.findOne({});
          targetStorage = settings ? settings.getDefaultStorage() : STORAGE_NAME_FILESYSTEM;
        } catch (error) {
          targetStorage = STORAGE_NAME_FILESYSTEM;
        }
      }

      // Validate storage backend
      if (![STORAGE_NAME_FILESYSTEM, STORAGE_NAME_GRIDFS, STORAGE_NAME_S3].includes(targetStorage)) {
        throw new Meteor.Error('invalid-storage', 'Invalid storage backend');
      }

      try {
        // Create file object from base64 data
        const fileBuffer = Buffer.from(fileData, 'base64');
        const file = new File([fileBuffer], fileName, { type: fileType || 'application/octet-stream' });

        // Create attachment metadata
        const fileId = new ObjectID().toString();
        const meta = {
          boardId: boardId,
          swimlaneId: swimlaneId,
          listId: listId,
          cardId: cardId,
          fileId: fileId,
          source: 'api',
          storageBackend: targetStorage
        };

        // Create attachment
        const uploader = Attachments.insert({
          file: file,
          meta: meta,
          isBase64: false,
          transport: 'http'
        });

        if (uploader) {
          // Move to target storage if not filesystem
          if (targetStorage !== STORAGE_NAME_FILESYSTEM) {
            Meteor.defer(() => {
              try {
                moveToStorage(uploader, targetStorage, fileStoreStrategyFactory);
              } catch (error) {
                console.error('Error moving attachment to target storage:', error);
              }
            });
          }

          return {
            success: true,
            attachmentId: uploader._id,
            fileName: fileName,
            fileSize: fileBuffer.length,
            storageBackend: targetStorage,
            message: 'Attachment uploaded successfully'
          };
        } else {
          throw new Meteor.Error('upload-failed', 'Failed to upload attachment');
        }
      } catch (error) {
        console.error('API attachment upload error:', error);
        throw new Meteor.Error('upload-error', error.message);
      }
    },

    // Download attachment via API
    'api.attachment.download'(attachmentId) {
      if (!this.userId) {
        throw new Meteor.Error('not-authorized', 'Must be logged in');
      }

      // Get attachment
      const attachment = ReactiveCache.getAttachment(attachmentId);
      if (!attachment) {
        throw new Meteor.Error('attachment-not-found', 'Attachment not found');
      }

      // Check permissions
      const board = ReactiveCache.getBoard(attachment.meta.boardId);
      if (!board || !board.isBoardMember(this.userId)) {
        throw new Meteor.Error('not-authorized', 'You do not have permission to access this attachment');
      }

      try {
        // Get file strategy
        const strategy = fileStoreStrategyFactory.getFileStrategy(attachment, 'original');
        const readStream = strategy.getReadStream();

        if (!readStream) {
          throw new Meteor.Error('file-not-found', 'File not found in storage');
        }

        // Read file data
        const chunks = [];
        return new Promise((resolve, reject) => {
          readStream.on('data', (chunk) => {
            chunks.push(chunk);
          });

          readStream.on('end', () => {
            const fileBuffer = Buffer.concat(chunks);
            const base64Data = fileBuffer.toString('base64');
            
            resolve({
              success: true,
              attachmentId: attachmentId,
              fileName: attachment.name,
              fileSize: attachment.size,
              fileType: attachment.type,
              base64Data: base64Data,
              storageBackend: strategy.getStorageName()
            });
          });

          readStream.on('error', (error) => {
            reject(new Meteor.Error('download-error', error.message));
          });
        });
      } catch (error) {
        console.error('API attachment download error:', error);
        throw new Meteor.Error('download-error', error.message);
      }
    },

    // List attachments for board, swimlane, list, or card
    'api.attachment.list'(boardId, swimlaneId, listId, cardId) {
      if (!this.userId) {
        throw new Meteor.Error('not-authorized', 'Must be logged in');
      }

      // Check permissions
      const board = ReactiveCache.getBoard(boardId);
      if (!board || !board.isBoardMember(this.userId)) {
        throw new Meteor.Error('not-authorized', 'You do not have permission to access this board');
      }

      try {
        let query = { 'meta.boardId': boardId };

        if (swimlaneId) {
          query['meta.swimlaneId'] = swimlaneId;
        }

        if (listId) {
          query['meta.listId'] = listId;
        }

        if (cardId) {
          query['meta.cardId'] = cardId;
        }

        const attachments = ReactiveCache.getAttachments(query);
        
        const attachmentList = attachments.map(attachment => {
          const strategy = fileStoreStrategyFactory.getFileStrategy(attachment, 'original');
          return {
            attachmentId: attachment._id,
            fileName: attachment.name,
            fileSize: attachment.size,
            fileType: attachment.type,
            storageBackend: strategy.getStorageName(),
            boardId: attachment.meta.boardId,
            swimlaneId: attachment.meta.swimlaneId,
            listId: attachment.meta.listId,
            cardId: attachment.meta.cardId,
            createdAt: attachment.uploadedAt,
            isImage: attachment.isImage
          };
        });

        return {
          success: true,
          attachments: attachmentList,
          count: attachmentList.length
        };
      } catch (error) {
        console.error('API attachment list error:', error);
        throw new Meteor.Error('list-error', error.message);
      }
    },

    // Copy attachment to another card
    'api.attachment.copy'(attachmentId, targetBoardId, targetSwimlaneId, targetListId, targetCardId) {
      if (!this.userId) {
        throw new Meteor.Error('not-authorized', 'Must be logged in');
      }

      // Get source attachment
      const sourceAttachment = ReactiveCache.getAttachment(attachmentId);
      if (!sourceAttachment) {
        throw new Meteor.Error('attachment-not-found', 'Source attachment not found');
      }

      // Check source permissions
      const sourceBoard = ReactiveCache.getBoard(sourceAttachment.meta.boardId);
      if (!sourceBoard || !sourceBoard.isBoardMember(this.userId)) {
        throw new Meteor.Error('not-authorized', 'You do not have permission to access the source attachment');
      }

      // Check target permissions
      const targetBoard = ReactiveCache.getBoard(targetBoardId);
      if (!targetBoard || !targetBoard.isBoardMember(this.userId)) {
        throw new Meteor.Error('not-authorized', 'You do not have permission to modify the target card');
      }

      // Check if target board allows attachments
      if (!targetBoard.allowsAttachments) {
        throw new Meteor.Error('attachments-not-allowed', 'Attachments are not allowed on the target board');
      }

      try {
        // Get source file strategy
        const sourceStrategy = fileStoreStrategyFactory.getFileStrategy(sourceAttachment, 'original');
        const readStream = sourceStrategy.getReadStream();

        if (!readStream) {
          throw new Meteor.Error('file-not-found', 'Source file not found in storage');
        }

        // Read source file data
        const chunks = [];
        return new Promise((resolve, reject) => {
          readStream.on('data', (chunk) => {
            chunks.push(chunk);
          });

          readStream.on('end', () => {
            try {
              const fileBuffer = Buffer.concat(chunks);
              const file = new File([fileBuffer], sourceAttachment.name, { type: sourceAttachment.type });

              // Create new attachment metadata
              const fileId = new ObjectID().toString();
              const meta = {
                boardId: targetBoardId,
                swimlaneId: targetSwimlaneId,
                listId: targetListId,
                cardId: targetCardId,
                fileId: fileId,
                source: 'api-copy',
                copyFrom: attachmentId,
                copyStorage: sourceStrategy.getStorageName()
              };

              // Create new attachment
              const uploader = Attachments.insert({
                file: file,
                meta: meta,
                isBase64: false,
                transport: 'http'
              });

              if (uploader) {
                resolve({
                  success: true,
                  sourceAttachmentId: attachmentId,
                  newAttachmentId: uploader._id,
                  fileName: sourceAttachment.name,
                  fileSize: sourceAttachment.size,
                  message: 'Attachment copied successfully'
                });
              } else {
                reject(new Meteor.Error('copy-failed', 'Failed to copy attachment'));
              }
            } catch (error) {
              reject(new Meteor.Error('copy-error', error.message));
            }
          });

          readStream.on('error', (error) => {
            reject(new Meteor.Error('copy-error', error.message));
          });
        });
      } catch (error) {
        console.error('API attachment copy error:', error);
        throw new Meteor.Error('copy-error', error.message);
      }
    },

    // Move attachment to another card
    'api.attachment.move'(attachmentId, targetBoardId, targetSwimlaneId, targetListId, targetCardId) {
      if (!this.userId) {
        throw new Meteor.Error('not-authorized', 'Must be logged in');
      }

      // Get source attachment
      const sourceAttachment = ReactiveCache.getAttachment(attachmentId);
      if (!sourceAttachment) {
        throw new Meteor.Error('attachment-not-found', 'Source attachment not found');
      }

      // Check source permissions
      const sourceBoard = ReactiveCache.getBoard(sourceAttachment.meta.boardId);
      if (!sourceBoard || !sourceBoard.isBoardMember(this.userId)) {
        throw new Meteor.Error('not-authorized', 'You do not have permission to access the source attachment');
      }

      // Check target permissions
      const targetBoard = ReactiveCache.getBoard(targetBoardId);
      if (!targetBoard || !targetBoard.isBoardMember(this.userId)) {
        throw new Meteor.Error('not-authorized', 'You do not have permission to modify the target card');
      }

      // Check if target board allows attachments
      if (!targetBoard.allowsAttachments) {
        throw new Meteor.Error('attachments-not-allowed', 'Attachments are not allowed on the target board');
      }

      try {
        // Update attachment metadata
        Attachments.update(attachmentId, {
          $set: {
            'meta.boardId': targetBoardId,
            'meta.swimlaneId': targetSwimlaneId,
            'meta.listId': targetListId,
            'meta.cardId': targetCardId,
            'meta.source': 'api-move',
            'meta.movedAt': new Date()
          }
        });

        return {
          success: true,
          attachmentId: attachmentId,
          fileName: sourceAttachment.name,
          fileSize: sourceAttachment.size,
          sourceBoardId: sourceAttachment.meta.boardId,
          targetBoardId: targetBoardId,
          message: 'Attachment moved successfully'
        };
      } catch (error) {
        console.error('API attachment move error:', error);
        throw new Meteor.Error('move-error', error.message);
      }
    },

    // Delete attachment via API
    'api.attachment.delete'(attachmentId) {
      if (!this.userId) {
        throw new Meteor.Error('not-authorized', 'Must be logged in');
      }

      // Get attachment
      const attachment = ReactiveCache.getAttachment(attachmentId);
      if (!attachment) {
        throw new Meteor.Error('attachment-not-found', 'Attachment not found');
      }

      // Check permissions
      const board = ReactiveCache.getBoard(attachment.meta.boardId);
      if (!board || !board.isBoardMember(this.userId)) {
        throw new Meteor.Error('not-authorized', 'You do not have permission to delete this attachment');
      }

      try {
        // Delete attachment
        Attachments.remove(attachmentId);

        return {
          success: true,
          attachmentId: attachmentId,
          fileName: attachment.name,
          message: 'Attachment deleted successfully'
        };
      } catch (error) {
        console.error('API attachment delete error:', error);
        throw new Meteor.Error('delete-error', error.message);
      }
    },

    // Get attachment info via API
    'api.attachment.info'(attachmentId) {
      if (!this.userId) {
        throw new Meteor.Error('not-authorized', 'Must be logged in');
      }

      // Get attachment
      const attachment = ReactiveCache.getAttachment(attachmentId);
      if (!attachment) {
        throw new Meteor.Error('attachment-not-found', 'Attachment not found');
      }

      // Check permissions
      const board = ReactiveCache.getBoard(attachment.meta.boardId);
      if (!board || !board.isBoardMember(this.userId)) {
        throw new Meteor.Error('not-authorized', 'You do not have permission to access this attachment');
      }

      try {
        const strategy = fileStoreStrategyFactory.getFileStrategy(attachment, 'original');
        
        return {
          success: true,
          attachmentId: attachment._id,
          fileName: attachment.name,
          fileSize: attachment.size,
          fileType: attachment.type,
          storageBackend: strategy.getStorageName(),
          boardId: attachment.meta.boardId,
          swimlaneId: attachment.meta.swimlaneId,
          listId: attachment.meta.listId,
          cardId: attachment.meta.cardId,
          createdAt: attachment.uploadedAt,
          isImage: attachment.isImage,
          versions: Object.keys(attachment.versions).map(versionName => ({
            versionName: versionName,
            storage: attachment.versions[versionName].storage,
            size: attachment.versions[versionName].size,
            type: attachment.versions[versionName].type
          }))
        };
      } catch (error) {
        console.error('API attachment info error:', error);
        throw new Meteor.Error('info-error', error.message);
      }
    }
  });
}
