package com.app.simplitend.patient_dashboard;

import static com.app.simplitend.caregiverdashboard.activities.EditProfileInfoActivity.IS_CAREGIVER;

import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.ListAdapter;
import androidx.recyclerview.widget.RecyclerView;

import com.app.simplitend.R;
import com.app.simplitend.apputils.AppUtil;
import com.app.simplitend.apputils.RetrofitHelper;
import com.app.simplitend.databinding.ActivityNotificationsBinding;
import com.app.simplitend.databinding.NotificationViewholderBinding;
import com.app.simplitend.welcome.welcomepatient.mvvm.models.CallResponse;

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

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.http.GET;
import retrofit2.http.Header;
import retrofit2.http.Url;

public class NotificationsActivity extends AppCompatActivity implements Callback<CallResponse<ArrayList<NotificationsActivity.Notification>>> {

    private ActivityNotificationsBinding binding;

    protected NotificationsApiService apiService;

    private static final String NOTIFICATION_BASE_URL = "api/get-notifications";

    private static final int PER_PAGE_COUNT = 10;

    private int page_no;

    protected String user_id;
    public static final String USER_ID = "user_id";

    protected String token;
    public static final String USER_TOKEN = "user_token";

    protected boolean isCaregiver;

    private NotificationsAdapter notificationsAdapter;
    private boolean isLoadingNotifications;
    private boolean lastPageHit;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityNotificationsBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        apiService = RetrofitHelper.getRetrofit().create(NotificationsApiService.class);

        user_id = getIntent().getStringExtra(USER_ID);
        token = getIntent().getStringExtra(USER_TOKEN);
        isCaregiver = getIntent().getBooleanExtra(IS_CAREGIVER, false);

        initViews();

        clickEvents();

        page_no = 1; // loading first page
        loadNotifications(false);

    }

    @Override
    protected void attachBaseContext(Context newBase) {
        final Configuration configuration = new Configuration(newBase.getResources().getConfiguration());
        configuration.fontScale = Math.min(configuration.fontScale, 1.1f);
        applyOverrideConfiguration(configuration);
        super.attachBaseContext(newBase);
    }

    private void clickEvents() {
        binding.backBtn.setOnClickListener(v -> onBackPressed());
    }

    private void initViews() {
        binding.notificationRv.setLayoutManager(new LinearLayoutManager(this));
        notificationsAdapter = new NotificationsAdapter();
        binding.notificationRv.setAdapter(notificationsAdapter);

        // pagination
        binding.notificationRv.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
                int visibleItemCount = layoutManager.getChildCount();
                int totalItemCount = layoutManager.getItemCount();
                int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition();

                if (!isLoadingNotifications && !lastPageHit) {
                    if ((visibleItemCount + firstVisibleItemPosition) >= (totalItemCount)
                            && firstVisibleItemPosition >= 0) {
                        page_no++; // loading next page
                        loadNotifications(true);
                    }
                }
            }
        });
    }

    private void loadNotifications(boolean show_bottom_progress) {
        if (user_id != null){

            if (show_bottom_progress){
                binding.pageProgress.setVisibility(View.VISIBLE);
            }else{
                binding.progress.setVisibility(View.VISIBLE);
            }
            isLoadingNotifications = true;

            if (isCaregiver){

                String url = NOTIFICATION_BASE_URL + "?caregiverId=" + user_id;
                url += "&per_page=" + PER_PAGE_COUNT + "&page=" + page_no;
                apiService.getNotifications(url,
                        "Bearer " + token).enqueue(this);
            }else{

                String url = NOTIFICATION_BASE_URL + "?patientId=" + user_id;
                url += "&per_page=" + PER_PAGE_COUNT + "&page=" + page_no;
                apiService.getNotifications(url,
                        "Bearer " + token).enqueue(this);
            }
        }else{
            binding.errorMsg.setText(R.string.couldn_t_load_notifications);
            binding.errorView.setVisibility(View.VISIBLE);
        }
    }

    @Override
    public void onResponse(Call<CallResponse<ArrayList<Notification>>> call, Response<CallResponse<ArrayList<Notification>>> response) {
        binding.progress.setVisibility(View.GONE);
        binding.pageProgress.setVisibility(View.GONE);

        if (response.body() != null){
            if (response.code() != 200){
                binding.errorMsg.setText(response.body().message);
                binding.errorView.setVisibility(View.VISIBLE);
                return;
            }

            if (response.body().result == null){
                binding.errorMsg.setText(R.string.couldn_t_load_notifications);
                binding.errorView.setVisibility(View.VISIBLE);
                return;
            }

            binding.errorView.setVisibility(View.GONE);
            binding.notificationRv.setVisibility(View.VISIBLE);

            isLoadingNotifications = false;
            lastPageHit = response.body().result.size() < 10; // no more data to load

            List<Notification> current_list = notificationsAdapter.getCurrentList();
            ArrayList<Notification> total_list = new ArrayList<>(current_list);
            total_list.addAll(response.body().result);

            if (total_list.isEmpty()){
                binding.errorMsg.setText(R.string.no_notifications);
                binding.errorView.setVisibility(View.VISIBLE);
            }else{
                notificationsAdapter.submitList(total_list);
            }

        }else{
            binding.errorMsg.setText(R.string.couldn_t_load_notifications);
            binding.errorView.setVisibility(View.VISIBLE);
        }
    }

    @Override
    public void onFailure(Call<CallResponse<ArrayList<Notification>>> call, Throwable t) {
        binding.progress.setVisibility(View.GONE);
        binding.pageProgress.setVisibility(View.GONE);
        binding.errorMsg.setText(R.string.couldn_t_load_notifications);
        binding.errorView.setVisibility(View.VISIBLE);
    }

    // util classes and interfaces

    public static class NotificationsAdapter extends ListAdapter<Notification, NotificationsAdapter.NotificationViewHolder> {

        private static final DiffUtil.ItemCallback<Notification> DIFF_CALLBACK = new DiffUtil.ItemCallback<Notification>() {
            @Override
            public boolean areItemsTheSame(@NonNull Notification oldItem, @NonNull Notification newItem) {
                return oldItem.id == newItem.id;
            }

            @Override
            public boolean areContentsTheSame(@NonNull Notification oldItem, @NonNull Notification newItem) {
                return oldItem.id == newItem.id;
            }
        };

        public NotificationsAdapter(){
            super(DIFF_CALLBACK);
        }

        @NonNull
        @Override
        public NotificationViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            NotificationViewholderBinding n_binding = NotificationViewholderBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
            return new NotificationViewHolder(n_binding);
        }

        @Override
        public void onBindViewHolder(@NonNull NotificationViewHolder holder, int position) {
            holder.setData(getItem(position));
        }

        public static class NotificationViewHolder extends RecyclerView.ViewHolder{
            public NotificationViewholderBinding binding;
            public NotificationViewHolder(@NonNull NotificationViewholderBinding binding){
                super(binding.getRoot());
                this.binding = binding;
            }

            public void setData(Notification notification){
                if (notification == null) return;

                binding.description.setText(notification.description);

                // 0-> medcine , 1-> activity , 2-> outofgeofence, 3-> reuqestedDirection , 4-> SOS , 5-> location , 6- radius add or update, 7 - subscription
                int imageRes = -1;

                switch (notification.type){
                    case "0":
                        imageRes = R.drawable.ic_med_noti;
                        break;
                    case "1":
                        imageRes = R.drawable.ic_activity_not;
                        break;
                    case  "2":
                    case "5":
                        imageRes = R.drawable.ic_geofence_noti;
                        break;
                    case "3":
                    case "6":
                        imageRes = R.drawable.ic_home_noti;
                        break;
                    case "4":
                        imageRes = R.drawable.ic_sos_noti;
                        break;
                    default:
                        imageRes = R.drawable.ic_subscription_noti;
                }

                if (imageRes != -1) {
                    binding.image.setImageResource(imageRes);
                    binding.imageCard.setCardBackgroundColor(itemView.getContext().getColor(R.color.color_accent));
                }

//                created at format 2023-11-03T11:13:22.000000Z
                if (notification.date_added != null){
                    String time;
                    try {
                        SimpleDateFormat fromSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
                        fromSdf.setTimeZone(TimeZone.getTimeZone("UTC"));
                        SimpleDateFormat toSdf = new SimpleDateFormat("dd MMM yyyy 'at' hh:mm a", Locale.getDefault());
                        toSdf.setTimeZone(TimeZone.getDefault());

                        Date date = fromSdf.parse(notification.date_added);
                        time = toSdf.format(date);
                    }catch (Exception e){
                        time = null;
                    }

                    if (time == null){
                        binding.timeView.setVisibility(View.GONE);
                    }else{
                        binding.timeView.setVisibility(View.VISIBLE);
                        binding.time.setText(time);
                    }
                }

            }
        }
    }

    public static class Notification{
        public int id;
        public String patient_xid;
        public String caregiver_xid;
        public String type;
        public String date_added;
        public String description;
        public String created_at;
        public String updated_at;
    }

    public interface NotificationsApiService{

        @GET
        Call<CallResponse<ArrayList<Notification>>> getNotifications(@Url String url,
                                                       @Header("Authorization") String token);
    }
}