const _ = require("lodash");
const passport = require("passport");
const crypto = require("crypto");
const { Strategy: LocalStrategy } = require("passport-local");
const { Strategy: CustomStrategy } = require("passport-custom");

const models = require("./models");
const securityHelper = require("../helpers/security.helper");
const authService = require("../modules/auth/auth.service");
const userService = require("../modules/auth/user.service");

/**
 * Validación sobre firebase
 */
var firebase_admin = require("firebase-admin");
var serviceAccount = require("../firebase-key.json");
firebase_admin.initializeApp({
  credential: firebase_admin.credential.cert(serviceAccount),
  databaseURL: "https://app-lqdvi-v2.firebaseio.com",
});

passport.serializeUser((user, done) => {
  console.log("serializarUsuario");
  done(null, user.id);
});

passport.deserializeUser((id, done) => {
  console.log("desserializarUsuario");
  models.User.findById(id, (err, user) => {
    done(err, user);
  });
});

/**
 * Sign in using Email and Password.
 */
const localEmailOptions = {
  usernameField: "email",
  passwordField: "password",
};

passport.use(
  "local-email",
  new LocalStrategy(localEmailOptions, async (email, password, done) => {
    try {
      let user = await authService.extraMethods.findUser({ email });
      if (_.isNull(user)) {
        return done(null, false, { message: "User not found" });
      } else {
        var password_encoded = crypto.createHash("sha512").update(password).digest("hex");
        const isPasswordValid = await user.comparePassword(password_encoded);
        if (!isPasswordValid) {
          return done(null, false, { message: "Wrong Password" });
        } else {
          user = user.toJSON();
          delete user.password;
          return done(null, user, { message: "Logged in Successfully" });
        }
      }
    } catch (error) {
      return done(error);
    }
  })
);

/**
 * Register using phone.
 */
const localPhoneOptions = {
  usernameField: "phone",
  passwordField: "fbuid",
};

passport.use(
  "local-phone",
  new LocalStrategy(localPhoneOptions, async (phone, fbuid, done) => {
    try {
      console.log("PASSPORT - local-phone-w/o-google");
      firebase_admin
        .auth()
        .getUserByPhoneNumber(phone)
        .then(function (userRecord) {
          if (userRecord && userRecord.toJSON().uid == fbuid) {
            if (userRecord.toJSON().disabled) return done(null, false, { message: "User disabled in fb" });
            else
              return done(null, userRecord.toJSON(), {
                message: "Register user in FB",
              });
          } else {
            // Esto es para la versión de la APP 1.5.0 (sin Google Firebase)
            if (phone === fbuid) {
              const user = {
                phone,
                phoneNumber: phone,
                uid: fbuid,
                fbuid,
              };
              return done(null, user, { message: "Registered user" });
            } else {
              return done(null, false, { message: "User not validate in fb" });
            }
          }
        })
        .catch(function (error) {
          //Servicio firebase caido o no funciona pero devuelvo el usuario
          const user = {
            phone: phone,
            phoneNumber: phone,
            uid: fbuid,
            fbuid: fbuid,
          };
          return done(null, user, error);
        });
    } catch (error) {
      return done(error);
    }
  })
);

passport.use(
  "local-phone-firebase",
  new LocalStrategy(localPhoneOptions, async (phone, fbuid, done) => {
    try {
      console.log("PASSPORT - local-phone");
      firebase_admin
        .auth()
        .getUserByPhoneNumber(phone)
        .then(function (userRecord) {
          if (userRecord && userRecord.toJSON().uid == fbuid) {
            if (userRecord.toJSON().disabled) return done(null, false, { message: "User disabled in fb" });
            else
              return done(null, userRecord.toJSON(), {
                message: "Register user",
              });
          } else return done(null, false, { message: "User not validate in fb" });
        })
        .catch(function (error) {
          //Servicio firebase caido o no funciona pero devuelvo el usuario
          const user = {
            phone: phone,
            fbuid: fbuid,
          };
          return done(null, user, error);
        });
    } catch (error) {
      return done(null, false, error);
    }
  })
);

/**
 *
 */
passport.use(
  "api-key",
  new CustomStrategy(async (req, done) => {
    const token = req && req.headers && req.headers["x-access-key"] ? req.headers["x-access-key"] : null;

    if (!token) {
      console.error("Unauthorized. API KEY missing.");
      return done(null, false, { message: "Unauthorized. API KEY missing." });
    }

    const result = securityHelper.verify(token);
    if (result) {
      console.log("Valid API KEY");
      return done(null, {}, { message: "Valid API KEY" });
    } else {
      //console.log('Token no válido');
      console.error("Unauthorized. Invalid token.");
      return done(null, false, { message: "Unauthorized. Invalid API KEY." });
    }
  })
);

// JWT
passport.use(
  "jwt",
  new CustomStrategy(async (req, done) => {
    const token = req && req.headers && req.headers["x-access-token"] ? req.headers["x-access-token"] : null;
    const appVersion = req && req.headers && req.headers["accept-version"] ? req.headers["accept-version"] : null;
    console.log("appVersion: ", appVersion);

    if (!token) {
      console.error("Unauthorized. Token missing.");
      return done(null, false, { message: "Unauthorized. Token missing." });
    }

    const result = securityHelper.verify(token);
    //console.log('token result => ', result);

    if (result && result.id) {
      //recuperamos el usuario de la petición
      let user = await authService.extraMethods.findUser({ id: result.id });
      if (user) {
        user = user.toJSON();
        userService._updateLastLoginAndVersionUser(user.id, appVersion);
        user.app_version = appVersion;
        user.token = token;
        delete user.password;

        console.log("Logged in Successfully");
        console.log(user);
        return done(null, user, { message: "Logged in Successfully" });
      } else {
        console.error("Unauthorized. User not found.");
        return done(null, false, { message: "Unauthorized. User not found." });
      }
    } else {
      //console.log('Token no válido');
      console.error("Unauthorized. Invalid token.");
      return done(null, false, { message: "Unauthorized. Invalid token." });
    }
  })
);
