package com.dittomart.meatsbhavan.firebase;

import static com.dittomart.meatsbhavan.util.Constant.FCM_TOKEN;
import static com.google.firebase.FirebaseApp.initializeApp;

import android.content.Context;
import android.util.Log;

import com.dittomart.meatsbhavan.api.Api;
import com.dittomart.meatsbhavan.util.CallbackWithRetry;
import com.dittomart.meatsbhavan.util.Constant;
import com.dittomart.meatsbhavan.util.SharePref;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.google.firebase.messaging.FirebaseMessaging;
import com.google.gson.Gson;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.Iterator;
import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class CreateFirebase {

    private static String generatedToken;
    private boolean isFCMAvail;

    private static final String TAG = CreateFirebase.class.getSimpleName();
    private Api apiService;
    private Context context;

    public CreateFirebase(Api apiService, Context context) {
        this.apiService = apiService;
        this.context = context;
        ConnectFirebase();
        Log.d(TAG, "GENERATED_FCM_TOKEN: " + generatedToken);
    }


    private void ConnectFirebase() {
        apiService.getGoogleServices().enqueue(new Callback<Object>() {
            @Override
            public void onResponse(Call<Object> call, Response<Object> response) {
                if (response.code() == 200) {
                    String project_number = null, project_id = null, firebase_url = null, storage_bucket = null, appId = null, apiKey = null;

                    String json = new Gson().toJson(response.body());

                    try {
                        JSONObject jsonObject = new JSONObject(json.trim());


//                        Log.d(TAG, "JSONOBJECT: " + jsonObject);
                        Iterator<String> keys = jsonObject.keys();

                        while (keys.hasNext()) {
                            String key = keys.next();

                            if (key.equals("project_info")) {
                                JSONObject projectJson = jsonObject.getJSONObject(key);
                                project_number = projectJson.getString("project_number");

                                if (projectJson.has("firebase_url")) {
                                    firebase_url = projectJson.getString("firebase_url");
                                }

                                project_id = projectJson.getString("project_id");
                                storage_bucket = projectJson.getString("storage_bucket");
                            } else if (key.equals("client")) {
                                JSONArray jsonArray = jsonObject.getJSONArray(key);
                                JSONObject object = jsonArray.getJSONObject(0);
                                Iterator<String> objectKeys = object.keys();
                                while (objectKeys.hasNext()) {
                                    String objectKey = objectKeys.next();

                                    if (objectKey.equals("client_info")) {
                                        JSONObject obj = object.getJSONObject(objectKey);
                                        appId = obj.getString("mobilesdk_app_id");
                                    } else if (objectKey.equals("api_key")) {
                                        JSONArray jarray = object.getJSONArray(objectKey);
                                        JSONObject obj = jarray.getJSONObject(0);
                                        apiKey = obj.getString("current_key");
                                    }
                                }
                            }


                        }

                        Log.d(TAG, "Values: " + project_number + "\n" + firebase_url + "\n" + project_id + "\n" + storage_bucket + "\n" + appId + "\n" + apiKey);

                        initializeFirebaseApp(project_number, firebase_url, project_id, storage_bucket, appId, apiKey);

                    } catch (JSONException e) {
                        e.printStackTrace();
                    }

                }
            }

            @Override
            public void onFailure(Call<Object> call, Throwable t) {
                Log.e(TAG, "onFailure: ", t);
            }
        });

    }


    private void initializeFirebaseApp(String project_number, String firebase_url, String project_id, String storage_bucket, String appId, String apiKey) {
        FirebaseApp finestayApp;

        FirebaseOptions options;

        if (firebase_url != null) {
            options = new FirebaseOptions.Builder()
                    .setApiKey(apiKey)
                    .setProjectId(project_id)
                    .setDatabaseUrl(firebase_url)
                    .setApplicationId(appId)
                    .setGcmSenderId(project_number)
                    .setStorageBucket(storage_bucket)
                    .build();
        } else {
            options = new FirebaseOptions.Builder()
                    .setApiKey(apiKey)
                    .setProjectId(project_id)
                    .setApplicationId(appId)
                    .setGcmSenderId(project_number)
                    .setStorageBucket(storage_bucket)
                    .build();

        }


        boolean hasBeenInitialized = false;
        List<FirebaseApp> firebaseApps = FirebaseApp.getApps(context);
        for (FirebaseApp app : firebaseApps) {
            if (app.getName().equals(FirebaseApp.DEFAULT_APP_NAME)) {
                hasBeenInitialized = true;
                finestayApp = app;
            }
        }

        if (!hasBeenInitialized) {
            finestayApp = initializeApp(context, options);
        }


        isFCMAvail = SharePref.getBooleanFromPref(Constant.TOKEN_AVAILABLE);


        if (!isFCMAvail) {
            generateFCM();
        }


    }

    private void generateFCM() {
        Log.d(TAG, "generateFCM: ");
        FirebaseMessaging.getInstance().getToken()
                .addOnCompleteListener(task -> {
                    if (!task.isSuccessful()) {
                        Log.d(TAG, "Fetching FCM registration token failed", task.getException());
                        return;
                    }
                    // Get new FCM registration token
                    generatedToken = task.getResult();

                    //Send FCM to Api
                    sendFCMtoServerNoUser(generatedToken);
                    Log.d(TAG, "GENERATED_FCM_TOKEN: " + generatedToken);
                    //Stored in locally
                    SharePref.setDataPref(FCM_TOKEN, generatedToken);
                    SharePref.setBooleanPref(Constant.TOKEN_AVAILABLE, true);

                    FirebaseMessaging.getInstance().subscribeToTopic("updates")
                        .addOnCompleteListener(topicTask -> {
                            if (!topicTask.isSuccessful()) {
                                Log.d(TAG, "Subscription to topic failed", topicTask.getException());
                            } else {
                                Log.d(TAG, "Subscribed to topic: updates");
                            }
                        });
                });

    }

    //send generated fcm without logged in to server
    private void sendFCMtoServerNoUser(String generatedToken) {
        Call<String> pushToken = apiService.sendToken(generatedToken);


        pushToken.enqueue(new CallbackWithRetry<String>() {
            @Override
            public void onResponse(Call<String> call, Response<String> response) {
                if (!response.isSuccessful()) {
                    try {
                        throw new Exception("Server Error");
                    } catch (Exception e) {
                        super.onFailure(call, e);
                    }
                } else {
                    Log.d(TAG, "onResponse: " + response.code());
                }

            }

            @Override
            public void onFailure(Call<String> call, Throwable t) {
                super.onFailure(call, t);
            }
        });

    }
}
