const UnitOfWork = require('../../database/UnitOfWork');
const UserDocumentRepository = require('../../repositories/documents/UserDocumentRepository');
const { s3 } = require('../../utils/exoscaleUploader');
const { GetObjectCommand } = require('@aws-sdk/client-s3');
const { getSignedUrl } = require('@aws-sdk/s3-request-presigner');
const { logger } = require('../../middleware/logger');

class UserDocumentController {
  static async getAllDocumentsForUser(req, res) {
    const userId = req.params.id;
    logger.info(`[UserDocumentController] Fetching all documents for userId: ${userId}`);
    const unitOfWork = new UnitOfWork();
    await unitOfWork.start();
    try {
      const repo = new UserDocumentRepository(unitOfWork);

      // Use repository methods for queries
      const documents = await repo.getDocumentsForUser(userId);
      logger.info(`[UserDocumentController] Found ${documents.length} user_documents for userId: ${userId}`);

      const idDocs = await repo.getIdDocumentsForUser(userId);
      logger.info(`[UserDocumentController] Found ${idDocs.length} user_id_documents for userId: ${userId}`);

      await unitOfWork.commit();

      // Generate signed URLs for each document in user_documents
      const signedDocuments = await Promise.all(
        documents.map(async doc => {
          let signedUrl = null;
          if (doc.object_storage_id) {
            try {
              const command = new GetObjectCommand({
                Bucket: process.env.EXOSCALE_BUCKET,
                Key: doc.object_storage_id
              });
              signedUrl = await getSignedUrl(s3, command, { expiresIn: 900 });
              logger.info(`[UserDocumentController] Generated signedUrl for object_storage_id: ${doc.object_storage_id}`);
            } catch (err) {
              logger.error(`[UserDocumentController] Failed to generate signedUrl for object_storage_id: ${doc.object_storage_id}`, { error: err });
            }
          } else {
            logger.warn(`[UserDocumentController] No object_storage_id for document id: ${doc.id}`);
          }
          return { ...doc, signedUrl };
        })
      );

      // Generate signed URLs for front and back of each ID document in user_id_documents
      const idDocFiles = await Promise.all(
        idDocs.flatMap(doc => [
          (async () => {
            let signedUrl = null;
            if (doc.front_object_storage_id) {
              try {
                const command = new GetObjectCommand({
                  Bucket: process.env.EXOSCALE_BUCKET,
                  Key: doc.front_object_storage_id
                });
                signedUrl = await getSignedUrl(s3, command, { expiresIn: 900 });
                logger.info(`[UserDocumentController] Generated signedUrl for front_object_storage_id: ${doc.front_object_storage_id}`);
              } catch (err) {
                logger.error(`[UserDocumentController] Failed to generate signedUrl for front_object_storage_id: ${doc.front_object_storage_id}`, { error: err });
              }
            }
            return {
              user_id_document_id: doc.id,
              user_id: doc.user_id,
              document_type: doc.document_type,
              side: 'front',
              object_storage_id: doc.front_object_storage_id,
              signedUrl,
              id_type: doc.id_type,
              id_number: doc.id_number,
              expiry_date: doc.expiry_date,
              original_filename: doc.original_filename_front
            };
          })(),
          (async () => {
            let signedUrl = null;
            if (doc.back_object_storage_id) {
              try {
                const command = new GetObjectCommand({
                  Bucket: process.env.EXOSCALE_BUCKET,
                  Key: doc.back_object_storage_id
                });
                signedUrl = await getSignedUrl(s3, command, { expiresIn: 900 });
                logger.info(`[UserDocumentController] Generated signedUrl for back_object_storage_id: ${doc.back_object_storage_id}`);
              } catch (err) {
                logger.error(`[UserDocumentController] Failed to generate signedUrl for back_object_storage_id: ${doc.back_object_storage_id}`, { error: err });
              }
            }
            return {
              user_id_document_id: doc.id,
              user_id: doc.user_id,
              document_type: doc.document_type,
              side: 'back',
              object_storage_id: doc.back_object_storage_id,
              signedUrl,
              id_type: doc.id_type,
              id_number: doc.id_number,
              expiry_date: doc.expiry_date,
              original_filename: doc.original_filename_back
            };
          })()
        ])
      );

      // Merge user_documents and idDocFiles for a complete list
      const allDocuments = [...signedDocuments, ...idDocFiles];

      logger.info(`[UserDocumentController] Returning ${allDocuments.length} documents with signed URLs for userId: ${userId}`);
      res.json({ success: true, documents: allDocuments, idDocuments: idDocs });
    } catch (error) {
      logger.error('[UserDocumentController] Error in getAllDocumentsForUser', { error });
      await unitOfWork.rollback(error);
      res.status(500).json({ success: false, message: error.message });
    }
  }
}

module.exports = UserDocumentController;
