package controllers;

import com.google.gson.JsonParser;

import models.AppUser;
import models.ContactInfo;
import models.EmailMessage;
import models.SentStatus;

import models.userAccess.UserNotFoundException;
import net.sf.oval.constraint.Email;
import org.joda.time.DateTime;
import play.Logger;
import play.Play;
import play.data.validation.Required;
import play.data.validation.Validation;
import play.libs.WS;
import play.mvc.Controller;
import play.mvc.Http;

import util.notifiers.MailgunMailer;

import java.util.HashMap;
import java.util.Map;



public class Unsecure extends Controller {

    private static final String CAPTCHA_SECRET = "6LfAIwYTAAAAAAzs_X6W1DdDxqbs3FCJfkvky2wu";


    public static void index() {
        login();
    }

    public static void login() {
        if (checkLogin()) {
            AppUser user = AppUser.find("byUsername", Security.connected()).first();
            if(user.roleInfo.roleName.equals("viewer"))
                Projects.filterProjects(null);
            else
                Application.index();
        }else{
            renderTemplate("app/views/Secure/login.html");

        }
    }

    public static boolean checkLogin(){
        String connected = Security.connected();
        if (connected == null || connected.isEmpty()) {
            return false;
        }
        String trimmedUser = connected.toUpperCase().trim();
        AppUser user = AppUser.find("select au from AppUser au where UPPER(au.userName)=:username").setParameter("username", trimmedUser).first();
        if (user != null) {
            return true;
        }
        return false;
    }


    public static void terms() {
        render();
    }


    public static void beginDemo() {
        render();
    }


    @SuppressWarnings("unused")
    public static void createNew(
            @Required(message = "Το πεδίο είναι υποχρεωτικό") @Email(message = "Η ηλ. διεύθυνση δεν είναι έγκυρη") String email,
            @Required(message = "Το πεδίο είναι υποχρεωτικό") String password,
            @Required(message = "Το πεδίο είναι υποχρεωτικό") String firstName,
            @Required(message = "Το πεδίο είναι υποχρεωτικό") String lastName,
            @Required(message = "Το πεδίο είναι υποχρεωτικό") String confirmPassword) {


        Http.Header forwarded_for_header = request.headers.get("x-forwarded-for");

        String remoteAddress = request.remoteAddress;
        if (forwarded_for_header != null) //if there are x-forwarded-for headers, use them instead
        {
            remoteAddress = forwarded_for_header.toString();
        }

        String captcha = params.allSimple().get("g-recaptcha-response");
        Map<String, Object> captchaParams = new HashMap<>();
        captchaParams.put("secret", CAPTCHA_SECRET);
        captchaParams.put("response", captcha);
        captchaParams.put("remoteip", remoteAddress);


        if (Play.mode.isProd()) {
            WS.HttpResponse captchaPOST = WS.url("https://www.google.com/recaptcha/api/siteverify").params(captchaParams).post();
            if (!captchaPOST.success() || !captchaPOST.getString().contains("true")) {
                flashError("captchaError", "Δεν επιβεβαιώθηκε το captcha");
                response.status = 400;
                register();
            }
        }

        validation.required(email);
        validation.required(password);
        validation.required(firstName);
        validation.required(lastName);
        validation.required(confirmPassword);


        if (Validation.hasErrors()) {
            flashError("regValidationError", "Υπάρχει σφάλμα στην φόρμα");
            response.status = 400;
            register();
        }

        if (!password.equals(confirmPassword)) {
            Validation.addError("confirmPassword", "Οι δύο κωδικοί δεν είναι ίδιοι");

            params.flash();
            flash.put("confPassword", "Οι κωδικοί δεν είναι ίδιοι");
            flash.put("error", "Οι κωδικοί δεν είναι ίδιοι");
            flash.put("regValidationError", true);
            response.status = 400;
            register();
        }
        if (email.equals("") || password.equals("") || firstName.equals("") || lastName.equals("") || confirmPassword.equals("")) {
            flashErrors("regEmailError", "Κενός κωδικός", "regError", "empty ship");
        }

        if (!util.Utils.validate(email)) {
            params.flash();
            flash.put("regEmailError", "Η διεύθυνση ηλεκτρονικού ταχυδρομείου που εισάγατε δεν είναι έγκυρη");
            flash.put("error", "Η διεύθυνση ηλεκτρονικού ταχυδρομείου που εισάγατε δεν είναι έγκυρη");
            flash.put("regValidationError", true);
            response.status = 400;
            register();
        }

        if (!util.Utils.validateUnique(email)) {
            params.flash();
            flash.put("regEmailError", "Υπάρχει ήδη λογαριασμός με αυτό το email");
            flash.put("error", "Υπάρχει ήδη λογαριασμός με αυτό το email");
            flash.put("regValidationError", true);
            response.status = 400;
            register();
        }


        AppUser appUser = new AppUser(email, password, firstName, lastName, DateTime.now());

        appUser.save();

        try {
            MailgunMailer.notifyMe(firstName + " " + lastName + " <" + email + "> ", "New user registered for Syndromi.gr");
        } catch (Exception e) {
            Logger.error(e.getMessage(), e);
        }

        Unsecure.successfullRegistration();
    }

    private static void flashError(String flashErrorKey, String error) {
        Validation.keep();
        params.flash();
        flash.put(flashErrorKey, true);
        flash.put("error", error);
    }

    private static void flashErrors(String regEmailError, String value, String regError, String value2) {
        params.flash();
        flash.put(regEmailError, value);
        flash.put(regError, value2);
        flash.put("regValidationError", true);
        response.status = 400;
        register();
    }

    public static void successfullRegistration() {
        render();
    }

    public static void remindPasswordUser(String username) {
        AppUser user = AppUser.find("byEmail", username).first();
        Boolean isOk=user!=null;
        Logger.info("remindPasswordUser ----- " +username);
        if (!isOk) {
            try {
                Logger.info("DID NOT FIND AN APPUSER !!!!!!!!!!!!!!!!!!!!!!!!!!!11");
                AppUser forEmail = AppUser.findOrCreateFromPerson(username);

                forEmail.sendPasswordResetRequest();
                isOk = true;
            } catch (UserNotFoundException e) {
                isOk = false;
            }
        }else{
            Logger.info("FOUND AN APPUSER --------------------------");
            user.sendPasswordResetRequest();
        }

        renderTemplate("Unsecure/remindPassword.html", isOk);
    }

    public static void remindPassword(String username) {
        Boolean isOk;
        AppUser appUser = AppUser.find("byUserName", username).first();
        isOk = (appUser != null);
        if (isOk) {
            appUser.sendPasswordResetRequest();
        }

        render(isOk);
    }

    public static void resetThePassword(String resetToken) {
        if (resetToken == null || resetToken.length() < 10) {
            Logger.info("reset token null");
            renderTemplate("/app/views/errors/badToken.html");
        }
        AppUser user = AppUser.find("byResetToken", resetToken).first();
        //MemberUser memberUser = MemberUser.find("byResetToken", resetToken).first();
        if (user == null ) {
            renderTemplate("/app/views/errors/badToken.html");
        } else {
            render(user, resetToken);
        }
    }

    public static void verifyEmail(String resetToken) {
        if (resetToken == null || resetToken.length() < 10) {
            renderTemplate("/app/views/errors/badTokenEmail.html");
        }
        AppUser user = AppUser.find("select u from AppUser u where u.appUserParams.contactInfo.verificationToken = ?", resetToken).first();
        if (user == null) {
            Logger.info("user not found with reset token");
            renderTemplate("/app/views/errors/badTokenEmail.html");
        } else {
            user.contactInfo.replyToAddressVerified = true;
           // user.save();
            renderTemplate("/app/views/Unsecure/emailVerified.html");
        }
    }

    public static void doResetPassword(String newPassword, String resetToken) throws Throwable {
        if (resetToken == null || resetToken.length() < 10) renderTemplate("/app/views/Unsecure/badToken.html");
        AppUser user = AppUser.find("byResetToken", resetToken).first();
        //MemberUser memberUser = MemberUser.find("byResetToken", resetToken).first();
        if (user == null) {
            renderTemplate("/app/views/errors/badToken.html");
        }
        if (user != null) {
            user.changePassword(newPassword);
            user.resetToken = null;
            user.save();
            flash.put("passReset", "passReset");
            Secure.login();
        }

    }


    public static void register() {

        if (Security.connected() != null) {
            Application.index();
        }
        render();
    }


    public static void logoutAndRegister() throws Throwable {

        session.clear();
        response.removeCookie("rememberme");

        flash.success("secure.logout");
        register();
    }

    public static void webhook() {
        //TODO: hashing things
        String messageId = request.params.get("Message-Id");
        String recipient = request.params.get("recipient");
        String event = request.params.get("event");
        String custom_variables = request.params.get("my-custom-data");
        Long id = new JsonParser().parse(custom_variables).getAsJsonObject().get("id").getAsLong();

        Logger.info(request.params.toString());
        EmailMessage emailMessage = EmailMessage.find("byMessage_id", messageId).first();
        if (emailMessage == null) {
            emailMessage = EmailMessage.findById(id);
            if (emailMessage == null) {
                Logger.error("Unknown message with this id: " + messageId);
                renderText("Thank you");
            }
        }
        assert emailMessage != null;
      //  Member member =
//                Member.find("from Member m where m in :recipientsIDs and m.contactInfo.email=:email")
//                        .setParameter("recipientsIDs", emailMessage.receipients)
//                        .setParameter("email", recipient)
//                        .first();
//        if (member != null) {
//            new SentStatus(member, emailMessage, event).save();
//        }
        renderText("Thank you");
    }




    public static void authenticateJSON(@Required String username, String password) throws Throwable {
        // Check tokens
//        Boolean allowed;
//        try {
//            // This is the deprecated method name
//            allowed = (Boolean) invoke("authentify", username, password);
//        } catch (UnsupportedOperationException e) {
//            // This is the official method name
//            allowed = (Boolean) invoke("authenticate", username, password);
//        }
//
//        if (Validation.hasErrors() || !allowed) {
//            response.status = 400;
//            renderJSONp("{username:" + username + "}");
//        }
//        // Mark user as connected
//        session.put("username", username);
//        AppUser connectedUser = AppUser.connect(username, password);
//        if (connectedUser == null) {
//            unauthorized();
//        }
//
//        assert connectedUser != null;
//        String token = connectedUser.createToken();

        // Remember if needed
        //renderJSONp("{'authToken':'" + token + "'}");
    }

    public static String renderJSONp(@Required String str) {
        if (request.params._contains("callback")) {
            response.contentType = "application/javascript";
            renderText(request.params.get("callback") + "(" + str + ")");
        } else {
            Controller.renderJSON(str);
        }
        return null;
    }




}