package com.kbs.kbsintranett;

import android.Manifest;
import android.content.pm.PackageManager;
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.ProgressBar;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.navigation.Navigation;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.google.gson.JsonElement;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class HomeFragment extends Fragment implements HomeAdapter.OnHomeClickListener {

    private static final String TAG = "HomeFragment";
    private RecyclerView recyclerView;
    private HomeAdapter adapter;
    private ProgressBar mainProgressBar;
    private SwipeRefreshLayout swipeRefreshLayout;

    private List<CalendarEvent> currentEvents = new ArrayList<>();
    private List<WpPost> currentNews = new ArrayList<>();
    private List<TaskItem> currentTasks = new ArrayList<>();

    private int activeNetworkCalls = 0;

    private Handler timeoutHandler = new Handler(Looper.getMainLooper());
    private Runnable timeoutRunnable = this::forceStopLoading;

    private static final int CACHE_TTL_MINUTES = 60;

    private ActivityResultLauncher<String> requestPermissionLauncher;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestPermissionLauncher = registerForActivityResult(
                new ActivityResultContracts.RequestPermission(),
                isGranted -> refreshData(true)
        );
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_home, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        mainProgressBar = view.findViewById(R.id.main_loading_spinner);
        swipeRefreshLayout = view.findViewById(R.id.swipe_refresh_home);
        recyclerView = view.findViewById(R.id.main_recycler_view);

        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));

        swipeRefreshLayout.setOnRefreshListener(() -> refreshData(true));

        refreshData(false);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        timeoutHandler.removeCallbacks(timeoutRunnable);
    }

    private void refreshData(boolean forceNetwork) {
        if (activeNetworkCalls > 0) return;

        boolean useCacheCalendar = !forceNetwork && CacheManager.isCacheValid(getContext(), "calendar", CACHE_TTL_MINUTES);
        boolean useCacheNews = !forceNetwork && CacheManager.isCacheValid(getContext(), "news", CACHE_TTL_MINUTES);
        boolean useCacheTasks = !forceNetwork && CacheManager.isCacheValid(getContext(), "tasks", CACHE_TTL_MINUTES);

        // Hvis alt er i cache, last direkte
        if (useCacheCalendar && useCacheNews && useCacheTasks) {
            loadAllFromCache();
            return;
        }

        activeNetworkCalls = 3;
        if (mainProgressBar != null) mainProgressBar.setVisibility(View.VISIBLE);

        timeoutHandler.removeCallbacks(timeoutRunnable);
        timeoutHandler.postDelayed(timeoutRunnable, 10000);

        fetchCalendarData(useCacheCalendar);
        fetchNewsData(useCacheNews);
        fetchTaskData(useCacheTasks);
    }

    private void forceStopLoading() {
        if (activeNetworkCalls > 0) {
            activeNetworkCalls = 0;
            if (mainProgressBar != null) mainProgressBar.setVisibility(View.GONE);
            if (swipeRefreshLayout != null) swipeRefreshLayout.setRefreshing(false);
            buildAndDisplayList();
        }
    }

    private void loadAllFromCache() {
        if (mainProgressBar != null) mainProgressBar.setVisibility(View.VISIBLE);

        new Thread(() -> {
            List<CalendarEvent> deviceEvents = CalendarManager.getDeviceEvents(getContext(), true);
            new Handler(Looper.getMainLooper()).post(() -> {
                if (!isAdded()) return;

                List<CalendarEvent> cachedApi = CacheManager.getCachedCalendarEvents(getContext());
                for (CalendarEvent e : cachedApi) CalendarManager.formatEventForUI(e);
                currentEvents = CalendarManager.mergeAndSort(cachedApi, deviceEvents);

                currentNews = CacheManager.getCachedNewsPosts(getContext());
                formatNewsDates(currentNews);

                currentTasks = CacheManager.getTasks(getContext());

                // FIKS: Hvis cache er tom, prøv nettverk likevel for å unngå tom skjerm
                if (currentTasks.isEmpty() && !CacheManager.isCacheValid(getContext(), "tasks", CACHE_TTL_MINUTES)) {
                    fetchTaskData(false);
                }

                if (mainProgressBar != null) mainProgressBar.setVisibility(View.GONE);
                if (swipeRefreshLayout != null) swipeRefreshLayout.setRefreshing(false);

                buildAndDisplayList();
            });
        }).start();
    }

    private void fetchCalendarData(boolean useCache) {
        if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.READ_CALENDAR) != PackageManager.PERMISSION_GRANTED) {
            requestPermissionLauncher.launch(Manifest.permission.READ_CALENDAR);
            currentEvents.clear();
            checkLoadingComplete();
            return;
        }

        new Thread(() -> {
            try {
                if (getContext() == null) {
                    checkLoadingCompleteAsync();
                    return;
                }

                List<CalendarEvent> deviceEvents = CalendarManager.getDeviceEvents(getContext(), true);

                new Handler(Looper.getMainLooper()).post(() -> {
                    if (!isAdded()) return;

                    if (useCache) {
                        List<CalendarEvent> cached = CacheManager.getCachedCalendarEvents(getContext());
                        for (CalendarEvent e : cached) CalendarManager.formatEventForUI(e);
                        currentEvents = CalendarManager.mergeAndSort(cached, deviceEvents);
                        checkLoadingComplete();
                    } else {
                        RetrofitClient.getApiService().getCalendarEvents().enqueue(new Callback<List<CalendarEvent>>() {
                            @Override
                            public void onResponse(Call<List<CalendarEvent>> call, Response<List<CalendarEvent>> response) {
                                List<CalendarEvent> apiEvents = new ArrayList<>();
                                if (response.isSuccessful() && response.body() != null) {
                                    apiEvents = response.body();
                                    CacheManager.saveCalendarEvents(getContext(), apiEvents);
                                } else {
                                    apiEvents = CacheManager.getCachedCalendarEvents(getContext());
                                }
                                for (CalendarEvent e : apiEvents) CalendarManager.formatEventForUI(e);
                                currentEvents = CalendarManager.mergeAndSort(apiEvents, deviceEvents);
                                checkLoadingComplete();
                            }
                            @Override
                            public void onFailure(Call<List<CalendarEvent>> call, Throwable t) {
                                List<CalendarEvent> cached = CacheManager.getCachedCalendarEvents(getContext());
                                for (CalendarEvent e : cached) CalendarManager.formatEventForUI(e);
                                currentEvents = CalendarManager.mergeAndSort(cached, deviceEvents);
                                checkLoadingComplete();
                            }
                        });
                    }
                });
            } catch (Exception e) {
                checkLoadingCompleteAsync();
            }
        }).start();
    }

    private void fetchNewsData(boolean useCache) {
        if (useCache) {
            currentNews = CacheManager.getCachedNewsPosts(getContext());
            formatNewsDates(currentNews);
            checkLoadingComplete();
        } else {
            RetrofitClient.getApiService().getPosts().enqueue(new Callback<List<WpPost>>() {
                @Override
                public void onResponse(Call<List<WpPost>> call, Response<List<WpPost>> response) {
                    if (response.isSuccessful() && response.body() != null) {
                        currentNews = response.body();
                        CacheManager.saveNewsPosts(getContext(), currentNews);
                    } else {
                        currentNews = CacheManager.getCachedNewsPosts(getContext());
                    }
                    formatNewsDates(currentNews);
                    checkLoadingComplete();
                }
                @Override
                public void onFailure(Call<List<WpPost>> call, Throwable t) {
                    currentNews = CacheManager.getCachedNewsPosts(getContext());
                    formatNewsDates(currentNews);
                    checkLoadingComplete();
                }
            });
        }
    }

    private void fetchTaskData(boolean useCache) {
        // FIKS: Hvis cache er valgt, men listen er tom, hent fra nett!
        if (useCache) {
            currentTasks = CacheManager.getTasks(getContext());
            if (currentTasks.isEmpty()) {
                fetchTaskData(false); // Rekursivt kall men tvinger nettverk
                return;
            }
            checkLoadingComplete();
        } else {
            RetrofitClient.getApiService().getTasks().enqueue(new Callback<List<TaskItem>>() {
                @Override
                public void onResponse(Call<List<TaskItem>> call, Response<List<TaskItem>> response) {
                    if (response.isSuccessful() && response.body() != null) {
                        currentTasks = response.body();
                        CacheManager.saveTasks(getContext(), currentTasks);
                    } else {
                        currentTasks = CacheManager.getTasks(getContext());
                    }
                    checkLoadingComplete();
                }
                @Override
                public void onFailure(Call<List<TaskItem>> call, Throwable t) {
                    currentTasks = CacheManager.getTasks(getContext());
                    checkLoadingComplete();
                }
            });
        }
    }

    private void checkLoadingCompleteAsync() {
        new Handler(Looper.getMainLooper()).post(this::checkLoadingComplete);
    }

    private void formatNewsDates(List<WpPost> posts) {
        SimpleDateFormat rawFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.getDefault());
        SimpleDateFormat targetFormat = new SimpleDateFormat("dd. MMM yyyy", Locale.getDefault());
        for (WpPost post : posts) {
            try {
                Date date = rawFormat.parse(post.date);
                post.date = targetFormat.format(date);
            } catch (Exception ignored) {}
        }
    }

    private synchronized void checkLoadingComplete() {
        activeNetworkCalls--;
        if (activeNetworkCalls <= 0) {
            activeNetworkCalls = 0;
            timeoutHandler.removeCallbacks(timeoutRunnable);

            if (mainProgressBar != null) mainProgressBar.setVisibility(View.GONE);
            if (swipeRefreshLayout != null) swipeRefreshLayout.setRefreshing(false);

            buildAndDisplayList();
        }
    }

    private void buildAndDisplayList() {
        if (!isAdded()) return;

        List<Object> items = new ArrayList<>();
        String myEmail = UserManager.getInstance().getUserEmail();

        items.add(new HomeAdapter.SectionTitleItem("Kommende hendelser", HomeAdapter.SectionTitleItem.TYPE_CALENDAR));
        String today = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(new Date());
        int calCount = 0;
        for (CalendarEvent e : currentEvents) {
            if (e.getRawDate() != null && e.getRawDate().compareTo(today) >= 0) {
                items.add(e);
                calCount++;
            }
            if (calCount >= 3) break;
        }

        items.add(new HomeAdapter.SectionTitleItem("Mine oppgaver", HomeAdapter.SectionTitleItem.TYPE_TASKS));
        List<TaskItem> myActiveTasks = new ArrayList<>();
        if (currentTasks != null) {
            for (TaskItem t : currentTasks) {
                if (t.isUserParticipant(myEmail) && !t.getParticipantStatus(myEmail) && !t.isFullyCompleted()) {
                    myActiveTasks.add(t);
                }
            }
        }

        if (myActiveTasks.isEmpty()) {
            items.add(new HomeAdapter.EmptyTasksItem());
        } else {
            // NY SORTERING: Med frist først, så uten frist (alfabetisk)
            Collections.sort(myActiveTasks, (t1, t2) -> {
                boolean t1HasDate = t1.getDueDate() > 0;
                boolean t2HasDate = t2.getDueDate() > 0;

                if (t1HasDate && !t2HasDate) return -1; // t1 først
                if (!t1HasDate && t2HasDate) return 1;  // t2 først
                if (!t1HasDate && !t2HasDate) return t1.getTitle().compareToIgnoreCase(t2.getTitle()); // Alfabetisk

                return Long.compare(t1.getDueDate(), t2.getDueDate()); // Dato
            });

            for (int i = 0; i < Math.min(myActiveTasks.size(), 3); i++) {
                items.add(myActiveTasks.get(i));
            }
        }

        items.add(new HomeAdapter.SectionTitleItem("Siste nytt", HomeAdapter.SectionTitleItem.TYPE_NEWS));
        if (currentNews != null) {
            items.addAll(currentNews);
        }

        adapter = new HomeAdapter(items, this);
        recyclerView.setAdapter(adapter);
    }

    @Override public void onCreateEventClick() { Navigation.findNavController(getView()).navigate(R.id.navigation_create_event); }
    @Override public void onViewAllCalendarClick() { Navigation.findNavController(getView()).navigate(R.id.navigation_calendar_full); }
    @Override public void onViewAllNewsClick() { Navigation.findNavController(getView()).navigate(R.id.navigation_news_full); }
    @Override public void onViewAllTasksClick() { Navigation.findNavController(getView()).navigate(R.id.navigation_tasks); }

    @Override public void onCalendarItemClick(CalendarEvent event) {
        CalendarDetailsBottomSheet sheet = new CalendarDetailsBottomSheet(event);
        sheet.setOnEventChangeListener(() -> refreshData(true));
        sheet.show(getParentFragmentManager(), "CalendarDetails");
    }

    @Override public void onNewsItemClick(WpPost post) {
        Bundle bundle = new Bundle();
        bundle.putSerializable("post_data", post);
        Navigation.findNavController(getView()).navigate(R.id.navigation_news_detail, bundle);
    }

    @Override public void onTaskItemClick(TaskItem task) {
        TaskDetailsBottomSheet sheet = new TaskDetailsBottomSheet(task, new TaskDetailsBottomSheet.OnTaskChangeListener() {
            @Override public void onTaskChanged() { saveAndSyncTasks(); }
            @Override public void onTaskDeleted(TaskItem taskToDelete) {
                currentTasks.remove(taskToDelete);
                saveAndSyncTasks();
            }
            @Override public void onEditRequested(TaskItem taskToEdit) {
                AddTaskBottomSheet editDialog = new AddTaskBottomSheet();
                editDialog.setTaskToEdit(taskToEdit);
                editDialog.setOnTaskAddedListener(new AddTaskBottomSheet.OnTaskAddedListener() {
                    @Override public void onTaskAdded(TaskItem task) {}
                    @Override public void onTaskUpdated(TaskItem task) {
                        saveAndSyncTasks();
                    }
                });
                editDialog.show(getChildFragmentManager(), "EditTask");
            }
        });
        sheet.show(getChildFragmentManager(), "TaskDetails");
    }

    @Override public void onTaskStatusChanged(TaskItem task, boolean isDone) {
        String myEmail = UserManager.getInstance().getUserEmail();
        task.setParticipantStatus(myEmail, isDone);
        if (task.getCreatedByEmail().equalsIgnoreCase(myEmail) && isDone) {
            task.setFullyCompleted(true);
        }
        saveAndSyncTasks();
    }

    private void saveAndSyncTasks() {
        CacheManager.saveTasks(getContext(), currentTasks);
        buildAndDisplayList();
        RetrofitClient.getApiService().syncTasks(currentTasks).enqueue(new Callback<JsonElement>() {
            @Override public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {}
            @Override public void onFailure(Call<JsonElement> call, Throwable t) {}
        });
    }
}