package com.kbs.kbsintranett;

import android.app.AlertDialog;
import android.app.DatePickerDialog;
import android.app.TimePickerDialog;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.Spinner;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.navigation.Navigation;
import com.google.android.material.chip.Chip;
import com.google.android.material.chip.ChipGroup;
import com.google.gson.JsonElement;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class CreateEventFragment extends Fragment {
    private EditText etTitle, etDesc, etLocation;
    private Spinner spinnerCalendar, spinnerRecurrence;
    private ChipGroup chipGroupReminders;
    private Switch switchAllDay;
    private TextView txtPreview;
    private Button btnStartDate, btnStartTime, btnEndDate, btnEndTime, btnSave;

    private Calendar startCal = Calendar.getInstance();
    private Calendar endCal = Calendar.getInstance();

    private String selectedRRule = null;
    private boolean isCustomRecurrence = false;

    // EDIT MODE
    private CalendarEvent eventToEdit = null;

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

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

        etTitle = view.findViewById(R.id.et_title);
        etDesc = view.findViewById(R.id.et_desc);
        etLocation = view.findViewById(R.id.et_location);
        switchAllDay = view.findViewById(R.id.switch_all_day);

        spinnerCalendar = view.findViewById(R.id.spinner_calendar);
        spinnerRecurrence = view.findViewById(R.id.spinner_recurrence);
        chipGroupReminders = view.findViewById(R.id.chip_group_reminders);

        txtPreview = view.findViewById(R.id.txt_time_preview);

        btnStartDate = view.findViewById(R.id.btn_start_date);
        btnStartTime = view.findViewById(R.id.btn_start_time);
        btnEndDate = view.findViewById(R.id.btn_end_date);
        btnEndTime = view.findViewById(R.id.btn_end_time);

        btnSave = view.findViewById(R.id.btn_save_event);

        // Initialiser tid (neste hele time)
        startCal.add(Calendar.HOUR_OF_DAY, 1);
        startCal.set(Calendar.MINUTE, 0);
        endCal.setTime(startCal.getTime());
        endCal.add(Calendar.HOUR_OF_DAY, 1);

        setupCalendarSpinner();
        setupReminderChips();

        // SJEKK OM VI ER I REDIGERINGS-MODUS
        if (getArguments() != null && getArguments().containsKey("edit_event")) {
            eventToEdit = (CalendarEvent) getArguments().getSerializable("edit_event");
            prefillForm(eventToEdit);
            btnSave.setText("Oppdater Hendelse");
        }

        updateRecurrenceSpinner();
        updateUI();

        // Listeners
        switchAllDay.setOnCheckedChangeListener((btn, isChecked) -> updateUI());

        btnStartDate.setOnClickListener(v -> pickDate(startCal, true));
        btnEndDate.setOnClickListener(v -> pickDate(endCal, false));

        btnStartTime.setOnClickListener(v -> pickTime(startCal));
        btnEndTime.setOnClickListener(v -> pickTime(endCal));

        btnSave.setOnClickListener(v -> submitEvent());

        spinnerRecurrence.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                // Unngå å overskrive ved innlasting hvis vi allerede har satt en verdi
                if (eventToEdit != null && position == 0 && selectedRRule != null) return;

                String selected = parent.getItemAtPosition(position).toString();
                if (selected.equals("Egendefinert...")) {
                    showCustomRecurrenceDialog();
                } else if (selected.startsWith("Ikke gjenta")) {
                    selectedRRule = null;
                } else {
                    generateStandardRRule(position);
                }
            }
            @Override public void onNothingSelected(AdapterView<?> parent) {}
        });
    }

    private void prefillForm(CalendarEvent event) {
        etTitle.setText(event.getTitle());

        // Rens beskrivelsen for #varsel tag
        String cleanDesc = event.getDescription().replaceAll("#varsel:[\\d,]+", "").trim();
        etDesc.setText(cleanDesc);
        etLocation.setText(event.getLocation());

        // Dato-parsing
        try {
            SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.getDefault());
            SimpleDateFormat simpleFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());

            String start = event.getRawDate();
            if (start != null) {
                if (start.length() == 10) {
                    // Heldags
                    switchAllDay.setChecked(true);
                    Date d = simpleFormat.parse(start);
                    startCal.setTime(d);

                    if (event.getRawEndDate() != null) {
                        Date e = simpleFormat.parse(event.getRawEndDate());
                        Calendar c = Calendar.getInstance();
                        c.setTime(e);
                        c.add(Calendar.DAY_OF_MONTH, -1);
                        endCal.setTime(c.getTime());
                    } else {
                        endCal.setTime(d);
                    }
                } else if (start.contains("T")) {
                    // Vanlig tid (kutt tidssone)
                    if (start.length() > 19) start = start.substring(0, 19);
                    startCal.setTime(isoFormat.parse(start));

                    String end = event.getRawEndDate();
                    if (end != null && end.contains("T")) {
                        if (end.length() > 19) end = end.substring(0, 19);
                        endCal.setTime(isoFormat.parse(end));
                    } else {
                        endCal.setTime(startCal.getTime());
                        endCal.add(Calendar.HOUR_OF_DAY, 1);
                    }
                }
            }

            // Varsler
            List<Integer> existingReminders = event.getReminders();
            if (!existingReminders.isEmpty()) {
                // Fjern alle sjekkmerker først (15 min er default checked)
                for (int i = 0; i < chipGroupReminders.getChildCount(); i++) {
                    ((Chip) chipGroupReminders.getChildAt(i)).setChecked(false);
                }
                for (int min : existingReminders) {
                    checkChipByMinutes(min);
                }
            }

        } catch (Exception e) {
            Log.e("KBS_EDIT", "Feil ved prefill", e);
        }
    }

    private void checkChipByMinutes(int minutes) {
        for (int i = 0; i < chipGroupReminders.getChildCount(); i++) {
            Chip chip = (Chip) chipGroupReminders.getChildAt(i);
            if ((int)chip.getTag() == minutes) {
                chip.setChecked(true);
            }
        }
    }

    private void setupCalendarSpinner() {
        // HENT DYNAMISK LISTE FRA USERMANAGER
        List<String> calendars = UserManager.getInstance().getWriteableCalendars();

        if (calendars.isEmpty()) calendars.add("Felles");

        spinnerCalendar.setAdapter(new ArrayAdapter<>(getContext(), android.R.layout.simple_spinner_dropdown_item, calendars));
    }

    private void setupReminderChips() {
        addChip("Ved start", 0);
        addChip("5 min", 5);
        addChip("10 min", 10);
        addChip("15 min", 15);
        addChip("30 min", 30);
        addChip("1 time", 60);
        addChip("2 timer", 120);
        addChip("1 dag", 1440);
        addChip("2 dager", 2880);
        addChip("1 uke", 10080);

        if (eventToEdit == null) checkChipByMinutes(15);
    }

    private void addChip(String text, int minutes) {
        Chip chip = new Chip(getContext());
        chip.setText(text);
        chip.setTag(minutes);
        chip.setCheckable(true);
        chip.setClickable(true);
        chipGroupReminders.addView(chip);
    }

    private List<Integer> getSelectedReminders() {
        List<Integer> selected = new ArrayList<>();
        for (int i = 0; i < chipGroupReminders.getChildCount(); i++) {
            Chip chip = (Chip) chipGroupReminders.getChildAt(i);
            if (chip.isChecked()) {
                selected.add((Integer) chip.getTag());
            }
        }
        return selected;
    }

    private void updateRecurrenceSpinner() {
        String dayName = new SimpleDateFormat("EEEE", new Locale("no")).format(startCal.getTime());
        int dayOfMonth = startCal.get(Calendar.DAY_OF_MONTH);
        String monthName = new SimpleDateFormat("MMMM", new Locale("no")).format(startCal.getTime());

        int weekNo = (startCal.get(Calendar.DAY_OF_MONTH) - 1) / 7 + 1;
        String nthDayString = "månedlig den " + weekNo + ". " + dayName + "en";

        List<String> options = new ArrayList<>();
        options.add("Ikke gjenta");
        options.add("Daglig");
        options.add("Ukentlig på " + dayName);
        options.add("Månedlig den " + dayOfMonth + ".");
        options.add(capitalize(nthDayString));
        options.add("Årlig den " + dayOfMonth + ". " + monthName);
        options.add("Hver ukedag (man-fre)");
        options.add("Egendefinert...");

        ArrayAdapter<String> adapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_spinner_dropdown_item, options);
        spinnerRecurrence.setAdapter(adapter);
    }

    private void generateStandardRRule(int position) {
        switch (position) {
            case 1: selectedRRule = "RRULE:FREQ=DAILY"; break;
            case 2: selectedRRule = "RRULE:FREQ=WEEKLY"; break;
            case 3: selectedRRule = "RRULE:FREQ=MONTHLY"; break;
            case 4:
                int weekNo = (startCal.get(Calendar.DAY_OF_MONTH) - 1) / 7 + 1;
                String dayCode = getDayCode(startCal.get(Calendar.DAY_OF_WEEK));
                selectedRRule = "RRULE:FREQ=MONTHLY;BYDAY=" + weekNo + dayCode;
                break;
            case 5: selectedRRule = "RRULE:FREQ=YEARLY"; break;
            case 6: selectedRRule = "RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR"; break;
            default: selectedRRule = null;
        }
    }

    private void showCustomRecurrenceDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
        View view = LayoutInflater.from(getContext()).inflate(R.layout.dialog_custom_recurrence, null);

        EditText etInterval = view.findViewById(R.id.et_interval);
        Spinner spinnerFreq = view.findViewById(R.id.spinner_freq);
        View layoutWeekdays = view.findViewById(R.id.layout_weekdays);

        ToggleButton[] toggles = {
                view.findViewById(R.id.tg_mon), view.findViewById(R.id.tg_tue),
                view.findViewById(R.id.tg_wed), view.findViewById(R.id.tg_thu),
                view.findViewById(R.id.tg_fri), view.findViewById(R.id.tg_sat),
                view.findViewById(R.id.tg_sun)
        };
        String[] labels = {"M", "T", "O", "T", "F", "L", "S"};
        for(int i=0; i<7; i++) { toggles[i].setText(labels[i]); toggles[i].setTextOn(labels[i]); toggles[i].setTextOff(labels[i]); }

        RadioGroup rgEnd = view.findViewById(R.id.rg_end);
        Button btnEndDatePicker = view.findViewById(R.id.btn_end_date_picker);
        EditText etCount = view.findViewById(R.id.et_count);
        Calendar customEndCal = Calendar.getInstance();
        customEndCal.add(Calendar.MONTH, 1);

        SimpleDateFormat sdf = new SimpleDateFormat("d. MMM yyyy", Locale.getDefault());
        btnEndDatePicker.setText(sdf.format(customEndCal.getTime()));

        btnEndDatePicker.setOnClickListener(v -> {
            rgEnd.check(R.id.rb_date);
            new DatePickerDialog(getContext(), (p, y, m, d) -> {
                customEndCal.set(y, m, d);
                btnEndDatePicker.setText(sdf.format(customEndCal.getTime()));
            }, customEndCal.get(Calendar.YEAR), customEndCal.get(Calendar.MONTH), customEndCal.get(Calendar.DAY_OF_MONTH)).show();
        });

        spinnerFreq.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                layoutWeekdays.setVisibility(position == 1 ? View.VISIBLE : View.GONE);
            }
            @Override public void onNothingSelected(AdapterView<?> parent) {}
        });

        builder.setView(view);
        AlertDialog dialog = builder.create();

        view.findViewById(R.id.btn_cancel).setOnClickListener(v -> {
            dialog.dismiss();
            spinnerRecurrence.setSelection(0);
        });

        view.findViewById(R.id.btn_done).setOnClickListener(v -> {
            StringBuilder rrule = new StringBuilder("RRULE:");
            int freqPos = spinnerFreq.getSelectedItemPosition();
            String freq = "";
            switch (freqPos) {
                case 0: freq = "DAILY"; break;
                case 1: freq = "WEEKLY"; break;
                case 2: freq = "MONTHLY"; break;
                case 3: freq = "YEARLY"; break;
            }
            rrule.append("FREQ=").append(freq);

            String interval = etInterval.getText().toString();
            if (!interval.isEmpty() && !interval.equals("1")) {
                rrule.append(";INTERVAL=").append(interval);
            }

            if (freq.equals("WEEKLY")) {
                List<String> days = new ArrayList<>();
                String[] codes = {"MO", "TU", "WE", "TH", "FR", "SA", "SU"};
                for (int i=0; i<7; i++) {
                    if (toggles[i].isChecked()) days.add(codes[i]);
                }
                if (!days.isEmpty()) {
                    rrule.append(";BYDAY=").append(String.join(",", days));
                }
            }

            int checkedId = rgEnd.getCheckedRadioButtonId();
            if (checkedId == R.id.rb_date) {
                customEndCal.set(Calendar.HOUR_OF_DAY, 23);
                customEndCal.set(Calendar.MINUTE, 59);
                customEndCal.setTimeZone(java.util.TimeZone.getTimeZone("UTC"));
                SimpleDateFormat utc = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'", Locale.US);
                utc.setTimeZone(java.util.TimeZone.getTimeZone("UTC"));
                rrule.append(";UNTIL=").append(utc.format(customEndCal.getTime()));
            } else if (checkedId == R.id.rb_count) {
                rrule.append(";COUNT=").append(etCount.getText().toString());
            }

            selectedRRule = rrule.toString();
            isCustomRecurrence = true;
            dialog.dismiss();
        });

        dialog.show();
    }

    private void pickDate(Calendar cal, boolean isStart) {
        new DatePickerDialog(getContext(), (view, y, m, d) -> {
            cal.set(y, m, d);
            if (isStart) {
                if (endCal.before(startCal)) {
                    endCal.setTime(startCal.getTime());
                    if (!switchAllDay.isChecked()) endCal.add(Calendar.HOUR_OF_DAY, 1);
                }
                updateRecurrenceSpinner();
                if (!isCustomRecurrence) spinnerRecurrence.setSelection(0);
            }
            updateUI();
        }, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH)).show();
    }

    private void pickTime(Calendar cal) {
        new TimePickerDialog(getContext(), (view, h, m) -> {
            cal.set(Calendar.HOUR_OF_DAY, h);
            cal.set(Calendar.MINUTE, m);
            if (cal == startCal && endCal.before(startCal)) {
                endCal.setTime(startCal.getTime());
                endCal.add(Calendar.HOUR_OF_DAY, 1);
            }
            updateUI();
        }, cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), true).show();
    }

    private void updateUI() {
        boolean isAllDay = switchAllDay.isChecked();

        btnStartTime.setVisibility(isAllDay ? View.GONE : View.VISIBLE);
        btnEndTime.setVisibility(isAllDay ? View.GONE : View.VISIBLE);

        SimpleDateFormat dateFmt = new SimpleDateFormat("dd.MM.yyyy", Locale.getDefault());
        SimpleDateFormat timeFmt = new SimpleDateFormat("HH:mm", Locale.getDefault());

        btnStartDate.setText(dateFmt.format(startCal.getTime()));
        btnEndDate.setText(dateFmt.format(endCal.getTime()));
        btnStartTime.setText(timeFmt.format(startCal.getTime()));
        btnEndTime.setText(timeFmt.format(endCal.getTime()));

        String preview = dateFmt.format(startCal.getTime());
        if (!isAllDay) preview += " " + timeFmt.format(startCal.getTime());
        preview += " - ";

        if (isSameDay(startCal, endCal)) {
            if (isAllDay) preview += " (Samme dag)";
            else preview += timeFmt.format(endCal.getTime());
        } else {
            preview += dateFmt.format(endCal.getTime());
            if (!isAllDay) preview += " " + timeFmt.format(endCal.getTime());
        }
        txtPreview.setText(preview);
    }

    private boolean isSameDay(Calendar c1, Calendar c2) {
        return c1.get(Calendar.YEAR) == c2.get(Calendar.YEAR) &&
                c1.get(Calendar.DAY_OF_YEAR) == c2.get(Calendar.DAY_OF_YEAR);
    }

    private String capitalize(String s) {
        if (s == null || s.isEmpty()) return s;
        return s.substring(0, 1).toUpperCase() + s.substring(1);
    }

    private String getDayCode(int calendarDay) {
        switch (calendarDay) {
            case Calendar.MONDAY: return "MO";
            case Calendar.TUESDAY: return "TU";
            case Calendar.WEDNESDAY: return "WE";
            case Calendar.THURSDAY: return "TH";
            case Calendar.FRIDAY: return "FR";
            case Calendar.SATURDAY: return "SA";
            case Calendar.SUNDAY: return "SU";
            default: return "MO";
        }
    }

    // NY: Henter navnet på kalenderen direkte fra Spinneren
    private String getCalendarSlug() {
        if (spinnerCalendar.getSelectedItem() != null) {
            return spinnerCalendar.getSelectedItem().toString();
        }
        return "Felles";
    }

    private void submitEvent() {
        String title = etTitle.getText().toString().trim();
        if (title.isEmpty()) {
            etTitle.setError("Mangler tittel");
            return;
        }

        boolean isAllDay = switchAllDay.isChecked();
        String format = isAllDay ? "yyyy-MM-dd" : "yyyy-MM-dd'T'HH:mm";
        SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.getDefault());

        CreateEventRequest req = new CreateEventRequest(
                title,
                etDesc.getText().toString(),
                etLocation.getText().toString(),
                sdf.format(startCal.getTime()),
                sdf.format(endCal.getTime()),
                getCalendarSlug(),
                getSelectedReminders(),
                isAllDay,
                selectedRRule
        );

        if (eventToEdit != null) {
            req.id = eventToEdit.getId();
        }

        Toast.makeText(getContext(), eventToEdit != null ? "Oppdaterer..." : "Oppretter...", Toast.LENGTH_SHORT).show();

        Call<JsonElement> call;
        if (eventToEdit != null) {
            call = RetrofitClient.getApiService().updateCalendarEvent(req);
        } else {
            call = RetrofitClient.getApiService().createCalendarEvent(req);
        }

        call.enqueue(new Callback<JsonElement>() {
            @Override
            public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {
                if (response.isSuccessful()) {
                    Toast.makeText(getContext(), eventToEdit != null ? "Hendelse oppdatert!" : "Hendelse opprettet!", Toast.LENGTH_LONG).show();
                    Navigation.findNavController(getView()).navigateUp();
                } else {
                    String errorMsg = "Ukjent feil";
                    try {
                        if (response.errorBody() != null) {
                            errorMsg = response.errorBody().string();
                        }
                    } catch (Exception e) {}

                    Log.e("KBS_ERROR", "Server svarte med feil: " + errorMsg);
                    Toast.makeText(getContext(), "Feil (" + response.code() + "): Sjekk Logcat", Toast.LENGTH_LONG).show();
                }
            }

            @Override
            public void onFailure(Call<JsonElement> call, Throwable t) {
                Log.e("KBS_ERROR", "Nettverksfeil", t);
                Toast.makeText(getContext(), "Nettverksfeil: " + t.getMessage(), Toast.LENGTH_SHORT).show();
            }
        });
    }
}