<script setup lang="ts">
import { ref, computed, watch, onMounted, onUnmounted } from "vue";
import { createEvent, updateEvent, deleteEvent, type EventEntry, type EventCreatePayload, type EventUpdatePayload } from "@/api/client";
import ProjectSelector from "@/components/ProjectSelector.vue";
import { useToastStore } from "@/stores/toast";

const props = defineProps<{
  // null = create mode; EventEntry = edit mode
  event: EventEntry | null;
  // pre-filled date string for create mode (YYYY-MM-DD or ISO)
  initialDate?: string;
}>();

const emit = defineEmits<{
  (e: "close"): void;
  (e: "created", event: EventEntry): void;
  (e: "updated", event: EventEntry): void;
  (e: "deleted", id: number): void;
}>();

const toast = useToastStore();

const isEditMode = computed(() => !!props.event);
const saving = ref(false);
const deleting = ref(false);
const deleteConfirm = ref(false);

// Form fields
const title = ref("");
const startDate = ref("");
const startTime = ref("");
const endDate = ref("");
const endTime = ref("");
const allDay = ref(false);
const description = ref("");
const location = ref("");
const color = ref("");
const projectId = ref<number | null>(null);

function dateFromIso(iso: string): string {
  const d = new Date(iso);
  if (isNaN(d.getTime())) return iso.slice(0, 10);
  const y = d.getFullYear();
  const m = String(d.getMonth() + 1).padStart(2, "0");
  const day = String(d.getDate()).padStart(2, "0");
  return `${y}-${m}-${day}`;
}

function timeFromIso(iso: string): string {
  if (!iso.includes("T")) return "09:00";
  const d = new Date(iso);
  if (isNaN(d.getTime())) return iso.slice(11, 16);
  return `${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}`;
}

function toIso(date: string, time: string): string {
  if (!time) return `${date}T00:00:00`;
  // Include local timezone offset so the server stores the correct UTC time
  const local = new Date(`${date}T${time}:00`);
  const off = -local.getTimezoneOffset();
  const sign = off >= 0 ? "+" : "-";
  const h = String(Math.floor(Math.abs(off) / 60)).padStart(2, "0");
  const min = String(Math.abs(off) % 60).padStart(2, "0");
  return `${date}T${time}:00${sign}${h}:${min}`;
}

function resetForm() {
  if (props.event) {
    title.value = props.event.title;
    allDay.value = props.event.all_day;
    startDate.value = dateFromIso(props.event.start_dt);
    startTime.value = props.event.all_day ? "" : timeFromIso(props.event.start_dt);
    endDate.value = props.event.end_dt ? dateFromIso(props.event.end_dt) : "";
    endTime.value = props.event.end_dt && !props.event.all_day ? timeFromIso(props.event.end_dt) : "";
    description.value = props.event.description || "";
    location.value = props.event.location || "";
    color.value = props.event.color || "";
    projectId.value = props.event.project_id;
  } else {
    title.value = "";
    allDay.value = false;
    const base = props.initialDate ? dateFromIso(props.initialDate) : new Date().toISOString().slice(0, 10);
    startDate.value = base;
    startTime.value = "09:00";
    endDate.value = base;
    endTime.value = "10:00";
    description.value = "";
    location.value = "";
    color.value = "";
    projectId.value = null;
  }
  deleteConfirm.value = false;
}

watch(() => props.event, resetForm, { immediate: true });
watch(() => props.initialDate, resetForm);

function handleKeydown(e: KeyboardEvent) {
  if (e.key === "Escape") emit("close");
}

onMounted(() => document.addEventListener("keydown", handleKeydown));
onUnmounted(() => document.removeEventListener("keydown", handleKeydown));

async function save() {
  if (!title.value.trim()) {
    toast.show("Title is required", "error");
    return;
  }
  if (!startDate.value) {
    toast.show("Start date is required", "error");
    return;
  }

  const start_dt = allDay.value ? `${startDate.value}T00:00:00` : toIso(startDate.value, startTime.value);
  const end_dt = endDate.value
    ? (allDay.value ? `${endDate.value}T00:00:00` : toIso(endDate.value, endTime.value))
    : undefined;

  saving.value = true;
  try {
    if (isEditMode.value && props.event) {
      const payload: EventUpdatePayload = {
        title: title.value.trim(),
        start_dt,
        end_dt,
        all_day: allDay.value,
        description: description.value,
        location: location.value,
        color: color.value,
        project_id: projectId.value ?? undefined,
      };
      const updated = await updateEvent(props.event.id, payload);
      toast.show("Event updated", "success");
      emit("updated", updated);
    } else {
      const payload: EventCreatePayload = {
        title: title.value.trim(),
        start_dt,
        end_dt,
        all_day: allDay.value,
        description: description.value,
        location: location.value,
        color: color.value,
        project_id: projectId.value ?? undefined,
      };
      const created = await createEvent(payload);
      toast.show("Event created", "success");
      emit("created", created);
    }
  } catch {
    toast.show("Failed to save event", "error");
  } finally {
    saving.value = false;
  }
}

async function doDelete() {
  if (!props.event) return;
  deleting.value = true;
  try {
    await deleteEvent(props.event.id);
    toast.show("Event deleted", "success");
    emit("deleted", props.event.id);
  } catch {
    toast.show("Failed to delete event", "error");
    deleting.value = false;
  }
}
</script>

<template>
  <Teleport to="body">
    <div class="slide-over-backdrop" @click.self="emit('close')">
      <div class="slide-over-panel" role="dialog" aria-modal="true">
        <div class="so-header">
          <h2 class="so-title">{{ isEditMode ? "Edit Event" : "New Event" }}</h2>
          <button class="so-close" @click="emit('close')" aria-label="Close">✕</button>
        </div>

        <form class="so-form" @submit.prevent="save">
          <!-- Title -->
          <div class="so-field">
            <label class="so-label">Title <span class="required">*</span></label>
            <input v-model="title" class="so-input" placeholder="Event title" autofocus />
          </div>

          <!-- All-day toggle -->
          <div class="so-field so-field-row">
            <label class="so-label so-label-inline">All day</label>
            <button
              type="button"
              :class="['toggle-btn', { active: allDay }]"
              @click="allDay = !allDay"
            >{{ allDay ? "Yes" : "No" }}</button>
          </div>

          <!-- Start -->
          <div class="so-field">
            <label class="so-label">Start</label>
            <div class="dt-row">
              <input v-model="startDate" type="date" class="so-input dt-date" />
              <input v-if="!allDay" v-model="startTime" type="time" class="so-input dt-time" />
            </div>
          </div>

          <!-- End -->
          <div class="so-field">
            <label class="so-label">End <span class="so-hint">(optional)</span></label>
            <div class="dt-row">
              <input v-model="endDate" type="date" class="so-input dt-date" />
              <input v-if="!allDay" v-model="endTime" type="time" class="so-input dt-time" />
            </div>
          </div>

          <!-- Location -->
          <div class="so-field">
            <label class="so-label">Location <span class="so-hint">(optional)</span></label>
            <input v-model="location" class="so-input" placeholder="Location" />
          </div>

          <!-- Description -->
          <div class="so-field">
            <label class="so-label">Description <span class="so-hint">(optional)</span></label>
            <textarea v-model="description" class="so-input so-textarea" placeholder="Description" rows="3" />
          </div>

          <!-- Color -->
          <div class="so-field so-field-row">
            <label class="so-label so-label-inline">Color</label>
            <div class="color-row">
              <input v-model="color" type="color" class="color-picker" title="Pick event color" />
              <input v-model="color" class="so-input color-hex" placeholder="#6366f1" />
              <button v-if="color" type="button" class="btn-clear-color" @click="color = ''">✕</button>
            </div>
          </div>

          <!-- Project -->
          <div class="so-field">
            <label class="so-label">Project <span class="so-hint">(optional)</span></label>
            <ProjectSelector v-model="projectId" />
          </div>

          <!-- Actions -->
          <div class="so-actions">
            <button type="submit" class="btn-primary" :disabled="saving">
              {{ saving ? "Saving…" : (isEditMode ? "Save" : "Create") }}
            </button>
            <button type="button" class="btn-secondary" @click="emit('close')">Cancel</button>
            <template v-if="isEditMode">
              <button
                v-if="!deleteConfirm"
                type="button"
                class="btn-danger-ghost"
                @click="deleteConfirm = true"
              >Delete</button>
              <template v-else>
                <span class="delete-confirm-label">Delete this event?</span>
                <button type="button" class="btn-danger" :disabled="deleting" @click="doDelete">
                  {{ deleting ? "Deleting…" : "Yes, delete" }}
                </button>
                <button type="button" class="btn-secondary" @click="deleteConfirm = false">No</button>
              </template>
            </template>
          </div>
        </form>
      </div>
    </div>
  </Teleport>
</template>

<style scoped>
.slide-over-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  z-index: 200;
  display: flex;
  justify-content: flex-end;
}

.slide-over-panel {
  background: var(--color-surface, #1a1b1e);
  border-left: 1px solid var(--color-border, #2a2b30);
  width: min(440px, 100vw);
  height: 100%;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  box-shadow: -4px 0 24px rgba(0, 0, 0, 0.4);
}

.so-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.25rem 1.5rem;
  border-bottom: 1px solid var(--color-border, #2a2b30);
  position: sticky;
  top: 0;
  background: var(--color-surface, #1a1b1e);
  z-index: 1;
}

.so-title {
  font-size: 1.05rem;
  font-weight: 600;
  margin: 0;
  color: var(--color-text, #e8e9f0);
}

.so-close {
  background: none;
  border: none;
  color: var(--color-text-muted, #888);
  cursor: pointer;
  font-size: 1.1rem;
  padding: 0.25rem 0.4rem;
  border-radius: 4px;
  line-height: 1;
}
.so-close:hover { background: var(--color-hover, rgba(255,255,255,0.06)); }

.so-form {
  padding: 1.25rem 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
  flex: 1;
}

.so-field { display: flex; flex-direction: column; gap: 0.35rem; }
.so-field-row { flex-direction: row; align-items: center; gap: 0.75rem; }

.so-label {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--color-text-muted, #888);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.so-label-inline { flex-shrink: 0; margin: 0; }
.so-hint { font-weight: 400; text-transform: none; letter-spacing: 0; opacity: 0.7; }

.required { color: #f87171; }

.so-input {
  background: var(--color-input-bg, #111113);
  border: 1px solid var(--color-border, #2a2b30);
  color: var(--color-text, #e8e9f0);
  border-radius: 6px;
  padding: 0.5rem 0.65rem;
  font-size: 0.9rem;
  width: 100%;
  box-sizing: border-box;
  transition: border-color 0.15s;
}
.so-input:focus { outline: none; border-color: var(--color-primary, #6366f1); }

.so-textarea { resize: vertical; min-height: 5rem; font-family: inherit; }

.dt-row { display: flex; gap: 0.5rem; }
.dt-date { flex: 1; }
.dt-time { width: 7.5rem; flex-shrink: 0; }

.toggle-btn {
  background: var(--color-input-bg, #111113);
  border: 1px solid var(--color-border, #2a2b30);
  color: var(--color-text-muted, #888);
  border-radius: 6px;
  padding: 0.3rem 0.9rem;
  font-size: 0.85rem;
  cursor: pointer;
  transition: all 0.15s;
}
.toggle-btn.active {
  background: var(--color-primary, #6366f1);
  border-color: var(--color-primary, #6366f1);
  color: #fff;
}

.color-row { display: flex; align-items: center; gap: 0.5rem; flex: 1; }
.color-picker { width: 2.4rem; height: 2.2rem; border: none; padding: 0; border-radius: 4px; cursor: pointer; flex-shrink: 0; }
.color-hex { flex: 1; }
.btn-clear-color {
  background: none;
  border: none;
  color: var(--color-text-muted, #888);
  cursor: pointer;
  padding: 0.2rem 0.3rem;
  font-size: 0.85rem;
}

.so-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  padding-top: 0.5rem;
  border-top: 1px solid var(--color-border, #2a2b30);
  margin-top: auto;
}

.btn-primary {
  background: linear-gradient(135deg, #6366f1, #4f46e5);
  color: #fff;
  border: none;
  border-radius: 8px;
  padding: 0.55rem 1.2rem;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  transition: opacity 0.15s;
}
.btn-primary:disabled { opacity: 0.5; cursor: not-allowed; }
.btn-primary:hover:not(:disabled) { opacity: 0.88; }

.btn-secondary {
  background: var(--color-input-bg, #111113);
  border: 1px solid var(--color-border, #2a2b30);
  color: var(--color-text-muted, #888);
  border-radius: 8px;
  padding: 0.55rem 1rem;
  font-size: 0.9rem;
  cursor: pointer;
}
.btn-secondary:hover { background: var(--color-hover, rgba(255,255,255,0.06)); }

.btn-danger-ghost {
  margin-left: auto;
  background: none;
  border: 1px solid #ef4444;
  color: #ef4444;
  border-radius: 8px;
  padding: 0.55rem 1rem;
  font-size: 0.9rem;
  cursor: pointer;
}
.btn-danger-ghost:hover { background: rgba(239, 68, 68, 0.1); }

.btn-danger {
  background: #ef4444;
  color: #fff;
  border: none;
  border-radius: 8px;
  padding: 0.55rem 1rem;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
}
.btn-danger:disabled { opacity: 0.5; cursor: not-allowed; }

.delete-confirm-label {
  font-size: 0.85rem;
  color: var(--color-text-muted, #888);
  align-self: center;
}
</style>
