package com.kbs.kbsintranett;

import android.content.Context;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.provider.CalendarContract;
import androidx.core.content.ContextCompat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.TimeZone;

public class CalendarManager {
    private static List<String> getKbsCalendarIds(Context context) {
        List<String> ids = new ArrayList<>();
        if (ContextCompat.checkSelfPermission(context, android.Manifest.permission.READ_CALENDAR) != PackageManager.PERMISSION_GRANTED) {
            return ids;
        }
        String[] projection = new String[] {
                CalendarContract.Calendars._ID,
                CalendarContract.Calendars.ACCOUNT_NAME
        };
        String selection = CalendarContract.Calendars.ACCOUNT_NAME + " LIKE ?";
        String[] selectionArgs = new String[] {"%@kbs.no"};

        try (Cursor cursor = context.getContentResolver().query(
                CalendarContract.Calendars.CONTENT_URI,
                projection,
                selection,
                selectionArgs,
                null
        )) {
            if (cursor != null) {
                while (cursor.moveToNext()) {
                    ids.add(cursor.getString(0));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ids;
    }

    /**
     * Henter hendelser fra enheten.
     * @param context App Context
     * @param isPreview Hvis true: Henter kun kommende måned (Raskt). Hvis false: Henter -1 til +6 mnd (Tregere).
     * @return Liste med events
     */
    public static List<CalendarEvent> getDeviceEvents(Context context, boolean isPreview) {
        List<CalendarEvent> deviceEvents = new ArrayList<>();
        if (ContextCompat.checkSelfPermission(context, android.Manifest.permission.READ_CALENDAR)
                != PackageManager.PERMISSION_GRANTED) {
            return deviceEvents;
        }

        List<String> kbsCalendarIds = getKbsCalendarIds(context);
        if (kbsCalendarIds.isEmpty()) {
            return deviceEvents;
        }

        long now = System.currentTimeMillis();
        long startMillis;
        long endMillis;

        if (isPreview) {
            // FORSIDEN: Optimalisert for hastighet.
            // Henter fra NÅ og 30 dager frem i tid.
            startMillis = now;
            endMillis = now + (30L * 24 * 60 * 60 * 1000);
        } else {
            // FULL VISNING: Bredere tidsvindu.
            // 1 mnd tilbake til 6 mnd frem.
            startMillis = now - (30L * 24 * 60 * 60 * 1000);
            endMillis = now + (180L * 24 * 60 * 60 * 1000);
        }

        String[] projection = new String[]{
                CalendarContract.Events.TITLE,
                CalendarContract.Events.DTSTART,
                CalendarContract.Events.DTEND,
                CalendarContract.Events.DESCRIPTION,
                CalendarContract.Events.EVENT_LOCATION,
                CalendarContract.Events.ALL_DAY
        };

        StringBuilder selection = new StringBuilder("(");
        List<String> selectionArgsList = new ArrayList<>();

        for (int i = 0; i < kbsCalendarIds.size(); i++) {
            selection.append(CalendarContract.Events.CALENDAR_ID).append(" = ?");
            selectionArgsList.add(kbsCalendarIds.get(i));
            if (i < kbsCalendarIds.size() - 1) {
                selection.append(" OR ");
            }
        }
        selection.append(") AND ");
        selection.append(CalendarContract.Events.DTSTART).append(" >= ? AND ");
        selection.append(CalendarContract.Events.DTSTART).append(" <= ?");

        selectionArgsList.add(String.valueOf(startMillis));
        selectionArgsList.add(String.valueOf(endMillis));

        String[] selectionArgs = selectionArgsList.toArray(new String[0]);

        try (Cursor cursor = context.getContentResolver().query(
                CalendarContract.Events.CONTENT_URI,
                projection,
                selection.toString(),
                selectionArgs,
                CalendarContract.Events.DTSTART + " ASC"
        )) {
            if (cursor != null) {
                SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.getDefault());
                while (cursor.moveToNext()) {
                    String title = cursor.getString(0);
                    long dtStart = cursor.getLong(1);
                    long dtEnd = cursor.getLong(2);
                    String desc = cursor.getString(3);
                    String loc = cursor.getString(4);
                    int allDay = cursor.getInt(5);

                    String rawStart;
                    String rawEnd;

                    if (allDay == 1) {
                        SimpleDateFormat shortFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
                        rawStart = shortFormat.format(new Date(dtStart));
                        rawEnd = shortFormat.format(new Date(dtEnd));
                    } else {
                        rawStart = isoFormat.format(new Date(dtStart));
                        rawEnd = isoFormat.format(new Date(dtEnd));
                    }

                    CalendarEvent event = new CalendarEvent(title, rawStart, rawEnd, desc, loc);
                    event.setReminderMinutes(0);

                    event.setCalendarColor("#888888");
                    event.setCalendarName("Min Kalender (Lokal)");

                    formatEventForUI(event);
                    deviceEvents.add(event);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return deviceEvents;
    }

    public static void formatEventForUI(CalendarEvent event) {
        if (event.getRawDate() == null) return;

        SimpleDateFormat outputDay = new SimpleDateFormat("dd", Locale.getDefault());
        SimpleDateFormat outputMonth = new SimpleDateFormat("MMM", new Locale("no", "NO"));
        SimpleDateFormat outputTime = new SimpleDateFormat("HH:mm", Locale.getDefault());

        outputMonth.setTimeZone(TimeZone.getTimeZone("Europe/Oslo"));
        outputTime.setTimeZone(TimeZone.getTimeZone("Europe/Oslo"));

        try {
            Date date = null;
            Date endDate = null;
            boolean isAllDay = false;

            String raw = event.getRawDate();

            if (raw.length() == 10 && !raw.contains("T") && !raw.contains(" ")) {
                SimpleDateFormat shortFmt = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
                date = shortFmt.parse(raw);
                isAllDay = true;
                if (event.getRawEndDate() != null && event.getRawEndDate().length() == 10) {
                    endDate = shortFmt.parse(event.getRawEndDate());
                }
            }
            else if (raw.contains("T")) {
                SimpleDateFormat isoFmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.getDefault());
                isoFmt.setTimeZone(TimeZone.getTimeZone("Europe/Oslo"));
                date = isoFmt.parse(raw);
                if (event.getRawEndDate() != null && event.getRawEndDate().contains("T")) {
                    endDate = isoFmt.parse(event.getRawEndDate());
                }
            }
            else {
                SimpleDateFormat sqlFmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
                sqlFmt.setTimeZone(TimeZone.getTimeZone("Europe/Oslo"));
                date = sqlFmt.parse(raw);
                if (event.getRawEndDate() != null) {
                    endDate = sqlFmt.parse(event.getRawEndDate());
                }
            }

            if (date != null) {
                event.setDay(outputDay.format(date));
                event.setMonth(outputMonth.format(date).toUpperCase());

                if (isAllDay) {
                    event.setTime("Hele dagen");
                } else {
                    String timeStr = outputTime.format(date);
                    if (endDate != null) {
                        timeStr += " - " + outputTime.format(endDate);
                    }
                    event.setTime("Kl. " + timeStr);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            event.setDay("??");
            event.setMonth("???");
            event.setTime("Feil dato");
        }
    }

    public static List<CalendarEvent> mergeAndSort(List<CalendarEvent> apiEvents, List<CalendarEvent> deviceEvents) {
        List<CalendarEvent> all = new ArrayList<>();
        Set<String> uniqueKeys = new HashSet<>();

        // 1. Legg til alle API-events først (Prioritert)
        for (CalendarEvent apiEvent : apiEvents) {
            all.add(apiEvent);
            uniqueKeys.add(generateKey(apiEvent));
        }

        // 2. Legg til Device-events KUN hvis nøkkelen ikke finnes
        for (CalendarEvent deviceEvent : deviceEvents) {
            String key = generateKey(deviceEvent);
            if (!uniqueKeys.contains(key)) {
                all.add(deviceEvent);
            }
        }

        // 3. Sorter alt kronologisk
        Collections.sort(all, (e1, e2) -> {
            String d1 = e1.getRawDate() != null ? e1.getRawDate() : "";
            String d2 = e2.getRawDate() != null ? e2.getRawDate() : "";
            return d1.compareTo(d2);
        });

        return all;
    }

    private static String generateKey(CalendarEvent event) {
        String title = event.getTitle() != null ? event.getTitle().toLowerCase().trim() : "";
        String datePart = "";

        if (event.getRawDate() != null) {
            String digits = event.getRawDate().replaceAll("[^0-9]", "");
            if (digits.length() >= 12) {
                datePart = digits.substring(0, 12);
            } else if (digits.length() >= 8) {
                datePart = digits.substring(0, 8);
            } else {
                datePart = digits;
            }
        }
        return title + "_" + datePart;
    }
}