package com.app.simplitend.chats;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;

import com.app.simplitend.R;
import com.app.simplitend.apputils.AppUtil;
import com.app.simplitend.apputils.Constants;
import com.app.simplitend.chats.mvvm.Author;
import com.app.simplitend.chats.mvvm.ChatViewModel;
import com.app.simplitend.chats.mvvm.Message;
import com.app.simplitend.chats.mvvm.Receiver;
import com.app.simplitend.chats.mvvm.RemoteMessage;
import com.app.simplitend.databinding.ChatFragmentBinding;
import com.bumptech.glide.Glide;
import com.onesignal.notifications.INotificationLifecycleListener;
import com.onesignal.notifications.INotificationWillDisplayEvent;
import com.stfalcon.chatkit.messages.MessagesListAdapter;
import com.stfalcon.chatkit.utils.DateFormatter;

import org.json.JSONObject;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

public class ChatFragment extends Fragment implements SocketHelper.Callback<Message>, ChatViewModel.ChatsCallBack, INotificationLifecycleListener {

    private static final String TAG = "SOCKET_CHAT_TAG";

    // view binding 
    protected ChatFragmentBinding binding;

    public static final String CHAT_ITEM_KEY = "chat_item_key";

    protected MessagesListAdapter<Message> messageAdapter;

    private final String nick_name, receiver_name;

    private final String author_image, receiver_image;

    private final String sender_id, receiver_id, channel_id, user_principal_id;

    public static final String SEND = "Send";

    private ChatViewModel chatViewModel;

    private boolean isLastPageLoaded;

    private int current_page_no;

    public ChatFragment(){
        // required
        this.sender_id = null;
        this.receiver_id = null;
        this.channel_id = null;
        this.nick_name = "NONE";
        this.receiver_name = "NONE";
        this.author_image = null;
        this.receiver_image = null;
        this.user_principal_id = null;
    }

    public ChatFragment(String sender_id,
                        String receiver_id,
                        String channel_id,
                        String user_principal_id,
                        String nick_name,
                        String receiver_name,
                        String sender_image,
                        String receiver_image) {
        this.sender_id = sender_id;
        this.receiver_id = receiver_id;
        this.channel_id = channel_id;
        this.nick_name = nick_name;
        this.receiver_name = receiver_name;
        this.author_image = sender_image;
        this.receiver_image = receiver_image;
        this.user_principal_id = user_principal_id;
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        binding = ChatFragmentBinding.inflate(inflater, container, false);

//        OneSignal.getNotifications().addForegroundLifecycleListener(this);

        chatViewModel = new ViewModelProvider(requireActivity()).get(ChatViewModel.class);

        initViews();

        clickEvents();

        current_page_no = 1;
        isLastPageLoaded = false;
        getChats();

        enableDenButton(false);

        if (sender_id != null && receiver_id != null && channel_id != null){
            SocketHelper socketHelper = SocketHelper.getInstance();
            socketHelper.establishConnection(new SocketHelper.SockCallBack() {
                @Override
                public void onSocketConnected() {
                    new Handler(Looper.getMainLooper()).post(() -> {
                        enableDenButton(true);
                    });
                }

                @Override
                public void onConnectionError(Exception e) {
                    Log.d(TAG, "onConnectionError: ");
                }

                @Override
                public void onDisconnected() {
                    Log.d(TAG, "onDisconnected: ");
                }
            });

            socketHelper.getMessage(this,
                    sender_id,
                    channel_id,
                    receiver_image,
                    author_image);
        }else{
            Toast.makeText(requireContext(), "Something went wrong", Toast.LENGTH_SHORT).show();
        }

        return binding.getRoot();
    }

    private void  getChats() {
        if (channel_id == null){
            binding.noChats.setVisibility(View.VISIBLE);
            binding.noChatMsg.setText(R.string.couldn_t_load_chats);
            return;
        }

        binding.progressBar.setVisibility(View.VISIBLE);

        String token;
        if (AppUtil.isPatientLoggedIn(requireContext())){
            token = AppUtil.getPatientToken(requireContext());
        }else {
            token = AppUtil.getCgToken(requireContext());
        }

        chatViewModel.getRemoteChatList("Bearer " + token,
                channel_id, current_page_no, this);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (channel_id != null){
            SocketHelper.getInstance().stopMessages(channel_id);
        }

//        OneSignal.getNotifications().removeForegroundLifecycleListener(this);
    }

    private void clickEvents() {
        binding.backBtn.setOnClickListener(v -> {
            if (getActivity() != null){
                getActivity().onBackPressed();
            }
        });

        binding.sendBtn.setOnClickListener(v -> {
            if (binding.messageEt.getText().toString().trim().isEmpty()){
                return;
            }

            if (sender_id == null || receiver_id == null || channel_id == null){
                Toast.makeText(requireContext(), "Something went wrong", Toast.LENGTH_SHORT).show();
                return;
            }

            if (SocketHelper.getInstance().isConnected()) {
                SocketHelper.getInstance().sendMessage(binding.messageEt.getText().toString().trim(),
                        sender_id, receiver_id, channel_id, user_principal_id);
                binding.messageEt.setText("");
                enableDenButton(false);
            } else {
                Toast.makeText(requireContext(), "Check internet connection", Toast.LENGTH_SHORT).show();
            }
        });

    }

    private void initViews() {

        try {
            try {
                int res = Integer.parseInt(receiver_image);
                binding.receiverImage.setImageResource(res);
            }catch (Exception e){
                if (receiver_image != null){
                    Glide.with(requireContext())
                            .load(receiver_image)
                            .placeholder(android.R.color.darker_gray)
                            .error(R.drawable.ic_contact)
                            .into(binding.receiverImage);
                }
            }
        }catch (Exception e){
            // do nothing
            binding.receiverImage.setImageResource(R.drawable.ic_contact);
        }

        binding.chatTitle.setText(receiver_name);

        MessagesListAdapter.HoldersConfig holdersConfig = new MessagesListAdapter.HoldersConfig();
        holdersConfig.setOutcoming(SenderViewHolder.class, R.layout.sender_msg_viewholder);
        holdersConfig.setIncoming(ReceiverViewHolder.class, R.layout.receiver_msg_viewholder);

        messageAdapter = new MessagesListAdapter<>("sender", holdersConfig, (imageView, url, payload) -> {
            if (url != null){
                Glide.with(imageView.getContext())
                        .load(url)
                        .fitCenter()
                        .placeholder(android.R.color.darker_gray)
                        .error(R.drawable.ic_user_outline)
                        .into(imageView);
            }else{
                Glide.with(imageView.getContext())
                        .load(R.drawable.ic_user_outline)
                        .fitCenter()
                        .placeholder(android.R.color.darker_gray)
                        .error(R.drawable.ic_user_outline)
                        .into(imageView);
            }
        });

        messageAdapter.setDateHeadersFormatter(date -> {
            if (DateFormatter.isToday(date)) {
                return "Today";
            } else if (DateFormatter.isYesterday(date)) {
                return "Yesterday";
            } else {
                return DateFormatter.format(date, DateFormatter.Template.STRING_DAY_MONTH_YEAR);
            }
        });

        binding.messageList.setAdapter(messageAdapter);

        messageAdapter.setLoadMoreListener((page, totalItemsCount) -> {
            if (!isLastPageLoaded){
                current_page_no++;
                getChats();
            }
        });
    }

    private void enableDenButton(boolean enable){
        binding.sendBtn.setEnabled(enable);

        if (enable){
            binding.sendProgress.setVisibility(View.GONE);
            binding.sendBtn.setText(SEND);
        }else{
            binding.sendProgress.setVisibility(View.VISIBLE);
            binding.sendBtn.setText(null);
        }
    }

    @Override
    public void onMessageReceived(Message message) {
        new Handler(Looper.getMainLooper()).post(() -> {
            if (messageAdapter == null) return;

            messageAdapter.addToStart(message, true);
            binding.noChats.setVisibility(View.GONE);
        });
    }

    @Override
    public void onMessageSentSuccessfully() {
        new Handler(Looper.getMainLooper()).post(() -> {
            enableDenButton(true);
        });
    }

    @Override
    public void onError(Exception e) {
        new Handler(Looper.getMainLooper()).post(() -> {
            enableDenButton(true);
            try {
                Toast.makeText(requireContext(), "Couldn't send message", Toast.LENGTH_SHORT).show();
            } catch (Exception ex) {
                // do nothing
            }
        });
    }

    @Override
    public void onChatsFetched(ArrayList<RemoteMessage> chatsList, int page_no) {
        // 2023-11-13 14:43:43 dateTime format
        // yyyy-MM-dd HH:mm:ss
        Log.d(TAG, "onChatsFetched: ");
        if (chatsList.size() < ChatViewModel.MESSAGES_PER_PAGE){
            this.isLastPageLoaded = true;
        }

        if (sender_id == null){
            return;
        }

        if (page_no == 1 && chatsList.isEmpty()){
            binding.noChats.setVisibility(View.VISIBLE);
        }else{
            binding.noChats.setVisibility(View.GONE);
        }

        ArrayList<Message> messages = new ArrayList<>();

        for (RemoteMessage remoteMessage: chatsList){

            Date message_date;
            try {
                SimpleDateFormat sdf =
                        new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
                sdf.setTimeZone(TimeZone.getTimeZone("UTC"));

                message_date = sdf.parse(remoteMessage.dateTime);
                if (message_date == null) throw new Exception();
            }catch (Exception e){
                message_date = Calendar.getInstance().getTime();
            }

            Message message;
            if (sender_id.equals(remoteMessage.senderID)){
                // Author message
                message = new Message(new Author(sender_id, author_image), remoteMessage.message, message_date);
            }else{
                // receiver message
                message = new Message(new Receiver(sender_id, receiver_image), remoteMessage.message, message_date);
            }

            messages.add(message);
        }

        binding.progressBar.setVisibility(View.GONE);
        messageAdapter.addToEnd(messages, false);
    }

    @Override
    public void onChatsFailed(Throwable t, String message) {
        current_page_no = Math.min(1, current_page_no-1);
        binding.progressBar.setVisibility(View.GONE);
        if (messageAdapter.getMessagesCount() == 0){
            binding.noChats.setVisibility(View.VISIBLE);
            binding.noChatMsg.setText(R.string.couldn_t_load_chats);
        }
    }

    @Override
    public void onWillDisplay(@NonNull INotificationWillDisplayEvent iNotificationWillDisplayEvent) {
        JSONObject extras = iNotificationWillDisplayEvent.getNotification().getAdditionalData();

        try {
            if (extras == null) return;
            if (Constants.CHATS_NOTIFICATIONS.equals(extras.getString("content_type"))){
                iNotificationWillDisplayEvent.preventDefault();
            }
        }catch (Exception e){
            // do nothing
        }
    }
}