package com.example.quiz;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.provider.Settings;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

import com.example.quiz.data.adapter.PointDeVenteAdapter;
import com.example.quiz.data.model.PagedModel;
import com.example.quiz.data.model.PointDeVente;
import com.example.quiz.data.model.Tpe;
import com.example.quiz.data.model.TpeResponse;
import com.example.quiz.databinding.FragmentServerConfigBinding;
import com.example.quiz.utils.LoaderDialog;
import com.example.quiz.utils.MessageDialog;
import com.example.quiz.utils.Result;
import com.example.quiz.utils.SharedPrefsHelper;
import com.example.quiz.viewModel.PointDeVenteViewModel;
import com.example.quiz.viewModel.TpeViewModel;
import com.google.android.material.appbar.MaterialToolbar;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Objects;

import dagger.hilt.android.AndroidEntryPoint;

/**
 * A simple {@link Fragment} subclass.
 * Use the {@link ServerConfig#newInstance} factory method to
 * create an instance of this fragment.
 */
@AndroidEntryPoint
public class ServerConfig extends Fragment {


    FragmentServerConfigBinding binding;
    private TpeViewModel viewModel;
    private SharedPrefsHelper sharedPrefsHelper;

    private boolean isUserTap = true;

    PointDeVenteAdapter pointDeVenteAdapter;

    TpeResponse existingTpe;

    PointDeVente pdv = null;

    private PointDeVenteViewModel pointDeVenteViewModel;

    LoaderDialog loader;

    public ServerConfig() {
        // Required empty public constructor
    }
    // TODO: Rename and change types and number of parameters
    public static ServerConfig newInstance() {
        ServerConfig fragment = new ServerConfig();
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        sharedPrefsHelper = SharedPrefsHelper.getInstance(getContext());
    }

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        binding = FragmentServerConfigBinding.inflate(inflater, container, false);
        viewModel = new ViewModelProvider(this).get(TpeViewModel.class);
        pointDeVenteViewModel = new ViewModelProvider(this).get(PointDeVenteViewModel.class);
        loader = new LoaderDialog(getContext());
        return binding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        AppCompatActivity activity = (AppCompatActivity) getActivity();
        if(activity != null){
            MaterialToolbar toolbar = activity.findViewById(R.id.toolbar);
            toolbar.setTitle("Configuration du terminal");
            toolbar.setBackgroundColor( getResources().getColor(R.color.primary_green));
        }
        if(sharedPrefsHelper.get("terminalId") != null){
            viewModel.getTpeById(sharedPrefsHelper.get("terminalId")).observe(getViewLifecycleOwner(), new Observer<Result<TpeResponse>>() {
                @Override
                public void onChanged(Result<TpeResponse> tpeResult) {
                    switch (tpeResult.status){
                        case LOADING:
                            loader.show("Chargement du TPE");
                            break;
                        case SUCCESS:
                            loader.dismiss();
                            existingTpe = tpeResult.data;
                            String numeroSerie = Settings.Secure.getString(getContext().getContentResolver(), Settings.Secure.ANDROID_ID);
                            if(existingTpe != null && existingTpe.getNumeroSerie().equals(numeroSerie)){
                                _checkPdv(existingTpe);
                                return;
                            }else{
                                MessageDialog.showError(getContext(), "Ce TPE n'est pas encore configuré");
                                _startAutocomplete();
                                break;
                            }
                        case ERROR:
                            loader.dismiss();
                            MessageDialog.showError(getContext(), "Erreur lors du chargement du TPE");
                            break;
                    }
                }
            });
        }
        _startAutocomplete();
        super.onViewCreated(view, savedInstanceState);
    }


    @SuppressLint("ClickableViewAccessibility")
    void _startAutocomplete(){
        pointDeVenteAdapter = new PointDeVenteAdapter();
        RecyclerView recyclerView = binding.pointRecyclerView;
        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
        binding.getRoot().setOnTouchListener((v, event) -> {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                // Vérifier si le clic est en dehors de l'autocomplete
                if (binding.autocompleteContainer.getVisibility() == View.VISIBLE && !binding.pointDeVente.isEnabled()) {
                    int[] location = new int[2];
                    binding.autocompleteContainer.getLocationOnScreen(location);
                    Rect rect = new Rect(
                            location[0],
                            location[1],
                            location[0] + binding.autocompleteContainer.getWidth(),
                            location[1] + binding.autocompleteContainer.getHeight()
                    );

                    int x = (int) event.getRawX();
                    int y = (int) event.getRawY();

                    if (!rect.contains(x, y)) {
                        binding.autocompleteContainer.setVisibility(View.GONE);
                    }
                }
            }
            return false;
        });
        binding.pointDeVente.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                if(!isUserTap) return;
                if(charSequence.toString().isEmpty() || !binding.pointDeVente.isEnabled()){
                    recyclerView.setVisibility(View.GONE);
                    binding.autocompleteContainer.setVisibility(View.GONE);
                    return;
                }
                pointDeVenteViewModel.setPointsDeVente(charSequence.toString()).observe(getViewLifecycleOwner(), new Observer<Result<PagedModel<PointDeVente>>>() {
                    @Override
                    public void onChanged(Result<PagedModel<PointDeVente>> pagedModelResult) {
                        switch (pagedModelResult.status){
                            case LOADING:
                                binding.autocompleteContainer.setVisibility(View.VISIBLE);
                                binding.loader.setVisibility(View.VISIBLE);
                                break;
                            case SUCCESS:
                                binding.autocompleteContainer.setVisibility(View.VISIBLE);
                                binding.loader.setVisibility(View.GONE);
                                List<PointDeVente> pointsDeVente = pagedModelResult.data.getContent();
                                recyclerView.setVisibility(View.VISIBLE);
                                pointDeVenteAdapter.setPoints(pointsDeVente);
                                recyclerView.setAdapter(pointDeVenteAdapter);
                                pointDeVenteAdapter.setOnItemClickListener((PointDeVente pointDeVente)->{
                                    pdv = pointDeVente;
                                    isUserTap = false;
                                    binding.pointDeVente.setText(pointDeVente.getNom());
                                    isUserTap = true;
                                    binding.autocompleteContainer.setVisibility(View.GONE);
                                    binding.loader.setVisibility(View.GONE);
                                });
                                break;
                            case ERROR:
                                binding.autocompleteContainer.setVisibility(View.GONE);
                                binding.loader.setVisibility(View.GONE);
                                MessageDialog.showError(getContext(), "Erreur lors du chargement des points de vente");
                                break;
                        }
                    }

                });
            }

            @Override
            public void afterTextChanged(Editable editable) {

            }
        });
    }

    void  _checkPdv(Tpe eTpe){
        binding.numeroSerie.setText(eTpe.getNumeroSerie());
        binding.brand.setText(eTpe.getTypeTerminal());
        binding.model.setText(eTpe.getModeleAppareil());
        binding.type.setText(eTpe.getTypeTerminal());
        pointDeVenteViewModel.getPointDeVenteById(String.valueOf(eTpe.getPointDeVenteId())).observe(getViewLifecycleOwner(), new Observer<Result<PointDeVente>>() {
            @Override
            public void onChanged(Result<PointDeVente> pointDeVenteResult) {
                switch (pointDeVenteResult.status){
                    case LOADING:
                        loader.show("Chargement du point de vente");
                        break;
                    case SUCCESS:
                        loader.dismiss();
                        binding.pointDeVente.setEnabled(false);
                        binding.pointDeVente.setText(pointDeVenteResult.data.getNom());
                        binding.validate.setClickable(false);
                        MessageDialog.showSuccess(getContext(), "Ce tpe est déjà configuré");
                        break;
                    case ERROR:
                        loader.dismiss();
                        MessageDialog.showError(getContext(), "Erreur lors du chargement du point de vente");
                        break;
                }
            }
        });
    }

    @Override
    public void onResume() {
        String serialNumber = Settings.Secure.getString(getContext().getContentResolver(), Settings.Secure.ANDROID_ID);
        binding.numeroSerie.setText(serialNumber);
        binding.brand.setText(Build.BRAND);
        binding.model.setText(Build.MODEL);
        binding.type.setText("POS");
        binding.validate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(pdv == null){
                    MessageDialog.showError(getContext(), "Veuillez sélectionner un point de vente");
                    return;
                }
                Tpe tpe = new Tpe();
                tpe.setNumeroSerie(serialNumber);
                tpe.setVersionOs(Build.VERSION.RELEASE);
                tpe.setVersionLogicielle(getAppVersion(getContext()));
                tpe.setPlateforme("PMU_BET");
                tpe.setSystemeExploitation("Android");
                tpe.setPointDeVenteId(pdv.getId());
                tpe.setAdresseIp(getLocalIpAddress());
                tpe.setModeleAppareil(Build.MODEL);
                tpe.setTypeTerminal("POS/"+Build.BRAND);
                tpe.setStatut("ACTIF");
                viewModel.createTpe(tpe).observe(getViewLifecycleOwner(), new Observer<Result<TpeResponse>>() {
                    @Override
                    public void onChanged(Result<TpeResponse> tpeResult) {
                        switch (tpeResult.status){
                            case LOADING:
                                loader.show("Création du TPE");
                                break;
                            case SUCCESS:
                                loader.dismiss();
                                MessageDialog.showSuccess(getContext(), "TPE configuré avec succès!");
                                sharedPrefsHelper.save("terminalId", String.valueOf(tpeResult.data.getId()));
                                sharedPrefsHelper.save("pointDeVenteId", String.valueOf(tpeResult.data.getPointDeVenteId()));
                                break;
                            case ERROR:
                                loader.dismiss();
                                MessageDialog.showError(getContext(), "Erreur lors de la configuration du TPE");
                                break;
                        }
                    }
                });
            }
        });

        binding.cancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (getActivity() != null) {
                    getActivity().getSupportFragmentManager().popBackStack();
                }
            }
        });
        super.onResume();
    }

    public String getLocalIpAddress() {
        try {
            for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
                NetworkInterface intf = en.nextElement();
                for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
                    InetAddress inetAddress = enumIpAddr.nextElement();
                    if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
                        return inetAddress.getHostAddress();
                    }
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return "0.0.0.0";
    }

    public static String getAppVersion(Context context) {
        try {
            return context.getPackageManager()
                    .getPackageInfo(context.getPackageName(), 0)
                    .versionName;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
            return "Version inconnue";
        }
    }


    public static String getMacAddress() {
        try {
            List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
            for (NetworkInterface nif : interfaces) {
                if (!nif.getName().equalsIgnoreCase("wlan0")) continue;

                byte[] macBytes = nif.getHardwareAddress();
                if (macBytes == null) return "N/A";

                StringBuilder res1 = new StringBuilder();
                for (byte b : macBytes) {
                    res1.append(String.format("%02X:", b));
                }

                if (res1.length() > 0) res1.deleteCharAt(res1.length() - 1);
                return res1.toString();
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return "N/A";
    }


}