import mongoose from 'mongoose';
import fs from 'fs';
import User from '../models/user';
import Project from '../models/project';
import Collection from '../models/collection';
import { moveObjectToUserInS3, copyObjectInS3 } from '../controllers/aws.controller';
import mail from '../utils/mail';
import { renderAccountConsolidation } from '../views/mail';


const mongoConnectionString = process.env.MONGO_URL;
const { ObjectId } = mongoose.Types;
// Connect to MongoDB
mongoose.Promise = global.Promise;
mongoose.connect(mongoConnectionString, { useNewUrlParser: true, useUnifiedTopology: true });
mongoose.set('useCreateIndex', true);
mongoose.connection.on('error', () => {
  console.error('MongoDB Connection Error. Please make sure that MongoDB is running.');
  process.exit(1);
});

/*
 * Requires the MongoDB Node.js Driver
 * https://mongodb.github.io/node-mongodb-native
 */

const agg = [
  {
    $project: {
      email: {
        $toLower: [
          '$email'
        ]
      }
    }
  }, {
    $group: {
      _id: '$email',
      total: {
        $sum: 1
      }
    }
  }, {
    $match: {
      total: {
        $gt: 1
      }
    }
  }, {
    $sort: {
      total: -1
    }
  }
];


// steps to make this work
// iterate through the results
// check if any files are on AWS
// if so, move them to the right user bucket
// then, update the user to currentUser
// then, after updating all of the projects
// also update the collections
// delete other users
// update user email so it is all lowercase
// then, send the email
// then, figure out how to iterate through all of the users.

// create list of duplicate users
// User.aggregate(agg).then((result) => {
//   return fs.writeFile('duplicates.json', JSON.stringify(result), () => {
//     console.log('File written.');
//     process.exit(0);
//   });
// });

let currentUser = null;
let duplicates = null;

fs.readFile('duplicates.json', async (err, file) => {
  const result = JSON.parse(file);
  for (let i = 3000; i < result.length; i += 1) {
    console.log('Index: ', i);
    const email = result[i]._id;
    console.log(email);
    await consolidateAccount(email); // eslint-disable-line
  }
  process.exit(0);
});

async function consolidateAccount(email) {
  return User.find({ email }).collation({ locale: 'en', strength: 2 })
    .sort({ createdAt: 1 }).exec()
    .then((result) => {
      [currentUser, ...duplicates] = result;
      console.log('Current User: ', currentUser._id, ' ', currentUser.email);
      duplicates = duplicates.map(dup => dup._id);
      console.log('Duplicates: ', duplicates);
      return Project.find({
        user: { $in: duplicates }
      }).exec();
    }).then((sketches) => {
      const saveSketchPromises = [];
      sketches.forEach((sketch) => {
        console.log('SketchId: ', sketch._id);
        console.log('UserId: ', sketch.user);
        const moveSketchFilesPromises = [];
        sketch.files.forEach((file) => {
        // if the file url contains sketch user
          if (file.url && file.url.includes(process.env.S3_BUCKET_URL_BASE) && !file.url.includes(currentUser._id)) {
            if (file.url.includes(sketch.user)) {
              const fileSavePromise = moveObjectToUserInS3(file.url, currentUser._id)
                .then((newUrl) => {
                  file.url = newUrl;
                }).catch((err) => {
                  console.log('Move Error:');
                  console.log(err);
                });
              moveSketchFilesPromises.push(fileSavePromise);
            } else {
              const fileSavePromise = copyObjectInS3(file.url, currentUser._id)
                .then((newUrl) => {
                  file.url = newUrl;
                }).catch((err) => {
                  console.log('Copy Error:');
                  console.log(err);
                });
              moveSketchFilesPromises.push(fileSavePromise);
            }
          }
        });
        const sketchSavePromise = Promise.all(moveSketchFilesPromises).then(() => {
          sketch.user = ObjectId(currentUser._id);
          return sketch.save();
        });
        saveSketchPromises.push(sketchSavePromise);
      });
      return Promise.all(saveSketchPromises);
    }).then(() => {
      console.log('Moved and updated all sketches.');
      return Collection.updateMany(
        { owner: { $in: duplicates } },
        { $set: { owner: ObjectId(currentUser.id) } }
      );
    }).then(() => {
      console.log('Moved and updated all collections.');
      return User.deleteMany({ _id: { $in: duplicates } });
    }).then(() => {
      console.log('Deleted other user accounts.');
      currentUser.email = currentUser.email.toLowerCase();
      return currentUser.save();
    }).then(() => {
      console.log('Migrated email to lowercase.');
      // const protocol = process.env.NODE_ENV === 'production' ? 'https' : 'http';
      const mailOptions = renderAccountConsolidation({
        body: {
          domain: 'https://editor.p5js.org',
          username: currentUser.username,
          email: currentUser.email
        },
        to: currentUser.email,
      });

      return new Promise((resolve, reject) => {
        mail.send(mailOptions, (mailErr, result) => {
          console.log('Sent email.');
          if (mailErr) {
            return reject(mailErr);
          }
          return resolve(result);
        });
      });
    }).catch((err) => {
      console.log(err);
      process.exit(1);
    });
}


// let duplicates = [
//   "5ce3d936e0f9df0022d8330c",
//   "5cff843f091745001e83c070",
//     "5d246f5db489e6001eaee6e9"
// ];
// let currentUser = null;
// User.deleteMany({ _id: { $in: duplicates } }).then(() => {
//   return User.findOne({ "email": "Silverstar09@hotmail.com" })
// }).then((result) => {
//   currentUser = result;
//   console.log('Deleted other user accounts.');
//   currentUser.email = currentUser.email.toLowerCase();
//   return currentUser.save();
// }).then(() => {
//   const mailOptions = renderAccountConsolidation({
//     body: {
//       domain: 'https://editor.p5js.org',
//       username: currentUser.username,
//       email: currentUser.email
//     },
//     to: currentUser.email,
//   });

//   return new Promise((resolve, reject) => {
//     mail.send(mailOptions, (mailErr, result) => {
//       console.log('Sent email.');
//       if (mailErr) {
//         return reject(mailErr);
//       }
//       return resolve(result);
//     });
//   });
// });


// import s3 from '@auth0/s3';

// const client = s3.createClient({
//   maxAsyncS3: 20,
//   s3RetryCount: 3,
//   s3RetryDelay: 1000,
//   multipartUploadThreshold: 20971520, // this is the default (20 MB)
//   multipartUploadSize: 15728640, // this is the default (15 MB)
//   s3Options: {
//     accessKeyId: `${process.env.AWS_ACCESS_KEY}`,
//     secretAccessKey: `${process.env.AWS_SECRET_KEY}`,
//     region: `${process.env.AWS_REGION}`
//   },
// });

// const headParams = {
//   Bucket: `${process.env.S3_BUCKET}`,
//   Key: "5c9de807f6bccf0017da7927/8b9d95ae-7ddd-452a-b398-672392c4ac43.png"
// };
// client.s3.headObject(headParams, (err, data) => {
//   console.log(err);
//   console.log(data);
// });