package controllers;

import com.google.gson.JsonElement;
import models.AppUser;
import models.EmailAlreadySentException;
import models.EmailMessage;
import models.UnsupportedFeatureException;
import models.contacts.Person;
import models.projects.Deliverable;
import models.projects.Project;

import play.Logger;
import play.data.validation.Validation;
import play.db.jpa.JPA;
import play.libs.WS;
import play.mvc.Controller;
import play.mvc.Router;
import play.mvc.With;
import util.notifiers.Email;
import util.notifiers.MailAccounting;

import javax.script.ScriptException;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;
import java.util.*;


@With(Application.class)    //Change to application to go live
public class EmailController extends Controller {

    public static AppUser getByUserName() throws Throwable {
        return Application.connectedUser();
    }


//    private static Set<Person> getReceipients(Long[] persons) throws NoSuchMethodException, ParseException, UnsupportedEncodingException, IllegalAccessException, ScriptException, FileNotFoundException, InvocationTargetException {
//        return getReceipients(persons,null, null);
//    }

    /*
    * We don't need to check for subordinates, as service and category belong to the supervisor
    */
    private static Set<Person> getReceipients(Long[] persons) throws Throwable {

        AppUser user = getByUserName();
        List<Person> fromPersons = new ArrayList<>();

        if (persons != null && persons[0] != null) {
            fromPersons = Person.find("select p from Person p where p.id in :transactions").setParameter("transactions", Arrays.asList(persons)).fetch();
        }
        Set<Person> receipients = new HashSet<>();
        receipients.addAll(fromPersons);
        return receipients;
    }

//
//    public static void index(Long id) {
//        AppUser user = getByUserName();
//        checkMailRights(user);
//        //if(user.hasToPay()) { Application.accountManagement(); } /**  if hasn't paid redirect him */
//        List<EmailMessage> eMessages = EmailMessage.find(" appUser=? and dateSent is null", user).fetch();
//
//        renderArgs.put("pageHeader", "Σύνταξη email");
//        renderArgs.put("active", "email");
//        if (id != null) {
//            EmailMessage msg = EmailMessage.findById(id);
//            if (msg == null) {
//                notFound();
//            }
//            assert msg != null;
//            if (!msg.appUser.equals(user)) {
//                forbidden();
//            }
//            render(msg, eMessages);
//        }
//
//
//        render(eMessages);
//    }

//    private static void checkMailRights(AppUser user) {
//        if (!user.canSendEmail()) {
//            forbidden();
//        }
//    }

//    @PaidAction
//    public static void addMessage(String content, Long id, String title) throws IOException {
//        checkMessage(content, title);
//
//        EmailMessage msg = null;
//        if (id != null) {
//            msg = EmailMessage.findById(id);
//        }
//        if (msg == null) {
//            msg = new EmailMessage(content, title, getByUserName()).save();
//        } else {
//            msg.content = content; //sending//
//            msg.title = title;
//            msg.save();
//        }
//        Long msg_id = msg.id;
//        renderJSON(msg_id);
//    }

    private static void checkMessage(String content, String title) throws IOException {
        if (title == null || title.trim().isEmpty()) {
            response.out.write("Ο τίτλος δεν μπορεί να είναι κενός".getBytes());
            badRequest();
        }
        if (content == null || content.trim().isEmpty()) {
            response.out.write("Το μήνυμα δεν μπορεί να είναι κενό".getBytes());
            badRequest();
        }
    }

//    public static void sendSingleMessage(String content, Long id, String title, Long memberId) throws IOException, UnsupportedFeatureException, NoSuchMethodException, ScriptException, IllegalAccessException, ParseException, InvocationTargetException {
//        AppUser user = getByUserName();
//        checkMailRights(user);
//        checkMessage(content, title);
//        EmailMessage msg = new EmailMessage(content, title, getByUserName()).save();
//        JPA.em().flush();
//        JPA.em().getTransaction().commit();
//        Long[] receipients= new Long[1];
//        receipients[0]=memberId;
//        doSend(new Long[0],new Long[0],receipients,null,null,msg.id);
//    }

//    public static void sendGroupMessage(String content, String title, Long groupId) throws IOException, NoSuchMethodException, ParseException, UnsupportedFeatureException, IllegalAccessException, ScriptException, InvocationTargetException {
//        AppUser user = getByUserName();
//        notFoundIfNull(groupId);
//        MemberGroup memberGroup = MemberGroup.findById(groupId);
//        notFoundIfNull(memberGroup);
//        if (!memberGroup.appUser.equals(user)) {
//            forbidden();
//        }
//        checkMailRights(user);
//        checkMessage(content, title);
//        EmailMessage msg = new EmailMessage(content, title, getByUserName()).save();
//        Long[] memberIds = memberGroup.members.stream().map(m -> m.id).toArray(Long[]::new);
//
//        doSend(new Long[0],new Long[0],memberIds,null,null,msg.id);
//
//    }

//    public static void sendGroupMessageSuccess(Long groupId){
//        flash.put("singleSuccess","Επιτυχής αποστολή");
//
//        GroupController.show(groupId);
//    }


    public static void sendSingleMessageSuccess(Long memberId){
        flash.put("singleSuccess","Επιτυχής αποστολή");
        Map<String, Object> args = new HashMap<>();
        args.put("id", memberId);
        String url = Router.getFullUrl("Application.addMember", args);
        redirect(url + "#messaging");
//        Application.addMember(member.id);
    }

//    @PaidAction
//    public static void send(Long id) {
//        AppUser user = getByUserName();
//        if(user.hasToPay()) { Application.accountManagement(); } /**  if hasn't paid redirect him */
//        if (id == null) {
//            notFound();
//        }
//        EmailMessage msg = EmailMessage.findById(id);
//        if (msg == null) {
//            notFound();
//        }
//        assert msg != null;
//        if (!msg.appUser.equals(user)) {
//            forbidden();
//        }
//
//        renderArgs.put("pageHeader", "Επιλογή αποδεκτών");
//        renderArgs.put("active", "email");
//
//
//        List<MemberCategory> categories = MemberCategory.find("byAppUsr", user).fetch();
//        if (user.isSupervised()) {
//            categories.addAll(user.supervisor.categories);
//        }
//        List<MemberService> services = MemberService.find("byAppUsr", user).fetch();
//        if (user.isSupervised()) {
//            services.addAll(MemberService.find("byAppUsr", user.supervisor).fetch());
//        }
//        List<Member> members = Member.find("byAppUsr", user).fetch();
//        render(msg, categories, services, members);
//    }

//    public static void getReceipientNumber(Long[] categories, Long[] services, Long[] members, Long[] memberGroups, Long[] filters) throws NoSuchMethodException, ParseException, UnsupportedEncodingException, IllegalAccessException, ScriptException, FileNotFoundException, InvocationTargetException {
//        Integer memberCount = getReceipients(categories, services, members,memberGroups, filters).size();
//        renderJSON(memberCount);
//    }



    public static void accessToProject(Long userId, Long projectId, boolean hasAccess) throws Throwable {
        AppUser user = getByUserName();
        notFoundIfNull(user);
        notFoundIfNull(userId);
        AppUser puser = AppUser.findById(userId);
        Project project = Project.findById(projectId);

        notFoundIfNull(puser);
        Logger.info("accessToProject " +puser.userName);
        Email.welcomeToProject(puser,user,project,hasAccess);
        flash.success("Επιτυχής αποστολή πρόσκλησης");

    }

    public static void accessToDeliverable(Long userId, Long deliverableId, boolean hasAccess) throws Throwable {
        AppUser user = getByUserName();
        notFoundIfNull(user);
        notFoundIfNull(userId);
        AppUser puser = AppUser.findById(userId);
        Deliverable deliverable = Deliverable.findById(deliverableId);

        notFoundIfNull(puser);

        Email.addToDeliverable(puser,user,deliverable,hasAccess);
        flash.success("Επιτυχής αποστολή πρόσκλησης");

    }

    public static void sendInvite(Long personId) throws Throwable {
        AppUser user = getByUserName();
        Logger.info("1");
        notFoundIfNull(user);
        Logger.info("2");
        Person puser = Person.findById(personId);
        notFoundIfNull(puser);
        Logger.info("3");
        if(puser.contactInfo.email == null || puser.contactInfo.email.equals(""))
        {
            if (Validation.hasErrors()) {
                Logger.info(validation.errorsMap().toString());
                params.flash();
                Validation.keep();
                Contacts.filterContacts("associates");
            }
        }
        Email.inviteToRegister(puser,user);

        flash.success("Επιτυχής αποστολή πρόσκλησης");
        Contacts.filterContacts("associates");
    }
//
//    public static void doSend(Long[] categories, Long[] services, Long[] members,Long[] groups,Long[] filters, Long id) throws IOException, UnsupportedFeatureException, InvocationTargetException, NoSuchMethodException, ScriptException, ParseException, IllegalAccessException {
//        AppUser user = getByUserName();
//        if(user.hasToPay()) { Application.accountManagement(); } /**  if hasn't paid redirect him */
//        Set<Member> receipients = getReceipients(categories, services, members,groups,filters);
//        EmailMessage msg = EmailMessage.findById(id);
//        if (msg == null) {
//            notFound();
//        }
//        assert msg != null;
//        if (!msg.appUser.equals(user)) {
//            forbidden();
//        }
//        if (receipients.isEmpty()) {
//            response.out.write(play.i18n.Messages.get("emptyReceipientList").getBytes());
//            badRequest();
//        }
//        if (receipients.size() > user.remainingMessages) {
//            response.out.write(play.i18n.Messages.get("emailQuotaReached").getBytes());
//            badRequest();
//        }
//
//        msg.receipients.addAll(receipients);
//        if (!msg.receipients.stream().anyMatch(r -> r.contactInfo.email!=null&&!r.contactInfo.email.isEmpty()&&!r.contactInfo.emailBounced)) {
//            response.out.write("Κανένας από τους παραλήπτες δεν έχει έγκυρη δ/νση email.".getBytes());
//            badRequest();
//        }
//        WS.HttpResponse sendResponse;
//        try {
//            Logger.info(String.valueOf(msg.receipients));
//            sendResponse = msg.send();
//            if (!sendResponse.success()) {
//                response.out.write(sendResponse.getString().getBytes());
//                badRequest();
//            }
//            JsonElement json = sendResponse.getJson();
//            String messageId = json.getAsJsonObject().get("id").getAsString();
//            Logger.info("Message id = " + messageId);
//            msg.message_id = messageId;
//            msg.save();
//            user.remainingMessages=user.remainingMessages-msg.receipients.size();
//            user.save();
//        } catch (EmailAlreadySentException e) {
//            Logger.error("email already sent");
//            response.out.write(play.i18n.Messages.get("alreadySent").getBytes());
//            badRequest();
//        }
//        flash.put("successSent","Το μήνυμα απεστάλη σε "+receipients+ " παραλήπτες");
//    }


//    public static void sentEmails() {
//        AppUser user = getByUserName();
//        if(user.hasToPay()) { Application.accountManagement(); } /**  if hasn't paid redirect him */
//        List<EmailMessage> emailMessages = EmailMessage
//                .find("select m from EmailMessage m where m.appUser=:appUser and dateSent is not null order by dateSent desc")
//                .setParameter("appUser", user).fetch();
//        checkMailRights(user);
//        renderArgs.put("pageHeader", "Ιστορικο αποστολών");
//        renderArgs.put("active", "email");
//        render(emailMessages);
//    }

//    public static void showSent(Long id) {
//        EmailMessage emailMessage = getEmailMessage(id);
//        List<SentStatus> events = SentStatus.find("byEmailMessage", emailMessage).fetch();
//
//        renderArgs.put("pageHeader", "Ιστορικο αποστολών");
//        renderArgs.put("active", "email");
//        render(emailMessage, events);
//    }
//
//    @PaidAction
//    public static void previewMessage(Long id) {
//        EmailMessage emailMessage = getEmailMessage(id);
//        render(emailMessage);
//    }
//
//    @PaidAction
//    public static void deleteDraft(Long id) {
//        getEmailMessage(id).delete();
//        renderText("Deleted");
//    }

    private static EmailMessage getEmailMessage(Long id) throws Throwable {
        if (id == null) {
            notFound();
        }
        AppUser user = getByUserName();
        EmailMessage emailMessage = EmailMessage.findById(id);
        if (emailMessage == null || !emailMessage.appUser.equals(user)) {
            notFound();
        }
        assert emailMessage != null;
        return emailMessage;
    }

//    public static void settings() {
//        AppUser user = getByUserName();
//        if(user.hasToPay()) { Application.accountManagement(); } /**  if hasn't paid redirect him */
//        user.setupDomain();
//
//        Integer count = new MailAccounting(user).sentEmails();
//
//        renderArgs.put("pageHeader", "Ρυθμίσεις μηνυμάτων");
//        renderArgs.put("active", "email");
//        renderArgs.put("user", user);
//        renderArgs.put("countMonth", count);
//        render();
//    }

//    public static void changeSettings(String email) {
//
//        AppUser user = getByUserName();
//        if (user.demo()) {
//            return;
//        }
//        if(user.hasToPay()) { Application.accountManagement(); } /**  if hasn't paid redirect him */
//        if (!email.equals(user.appUserParams.contactInfo.replyToAddress)) {
//            user.appUserParams.contactInfo.replyToAddressVerified = false;
//            user.appUserParams.contactInfo.replyToAddress = email;
//            user.appUserParams.contactInfo.verificationSent = true;
//
//            user.verifyReplyTo();
//            user.save();
//        }
//        Application.settings();
//    }

}
