<script lang="ts">
  import { onMount } from 'svelte';
  import { goto } from '$app/navigation';
  import { page } from '$app/state';
  import { api } from '$lib/api';
  import { addToast } from '$lib/stores/toast';
  import Button from '$lib/components/ui/Button.svelte';
  import Card from '$lib/components/ui/Card.svelte';
  import Skeleton from '$lib/components/ui/Skeleton.svelte';
  import TextInput from '$lib/components/ui/TextInput.svelte';
  import Textarea from '$lib/components/ui/Textarea.svelte';
  import {
    ArrowLeft,
    Check,
    X as XIcon,
    Pause,
    RotateCcw,
    Save,
  } from 'lucide-svelte';
  import {
    type EventItem,
    type EventKind,
    KIND_LABEL,
    STATUS_LABEL,
    STATUS_COLOR,
    KIND_COLOR,
    getEvent,
    patchEvent,
    completeEvent,
    cancelEvent,
    deferEvent,
    reactivateEvent,
    formatDateTimeKst,
    relativeTimeKo,
  } from '$lib/utils/events';

  const eventId = $derived(parseInt(page.params.id ?? '0', 10));

  let item = $state<EventItem | null>(null);
  let history = $state<HistoryEntry[]>([]);
  let loading = $state(true);
  let saving = $state(false);

  // edit fields (PATCH 허용만)
  let editTitle = $state('');
  let editDescription = $state('');
  let editDueAt = $state('');
  let editStartAt = $state('');
  let editEndAt = $state('');
  let editAllDay = $state(false);
  let editPriority = $state<number | ''>('');
  let editProjectTag = $state('');

  interface HistoryEntry {
    id: number;
    event_id: number;
    changed_at: string;
    changed_by: string;
    change_kind: string;
    before: Record<string, unknown> | null;
    after: Record<string, unknown>;
  }

  const CHANGE_KIND_LABEL: Record<string, string> = {
    create: '생성',
    reschedule: '시간 변경',
    defer: '연기',
    reactivate: '재활성',
    complete: '완료',
    cancel: '취소',
  };

  onMount(() => {
    if (!eventId) {
      addToast('error', '유효하지 않은 ID');
      goto('/events');
      return;
    }
    void load();
  });

  async function load() {
    loading = true;
    try {
      const [ev, hist] = await Promise.all([
        getEvent(eventId),
        api<{ items: HistoryEntry[] }>(`/events/${eventId}/history`),
      ]);
      item = ev;
      history = hist.items;
      // edit fields seed
      editTitle = ev.title;
      editDescription = ev.description ?? '';
      editDueAt = isoToLocalInput(ev.due_at);
      editStartAt = isoToLocalInput(ev.start_at);
      editEndAt = isoToLocalInput(ev.end_at);
      editAllDay = ev.all_day;
      editPriority = ev.priority ?? '';
      editProjectTag = ev.project_tag ?? '';
    } catch (err) {
      const detail = (err as { detail?: string })?.detail ?? '로드 실패';
      addToast('error', detail);
      if ((err as { status?: number })?.status === 404) goto('/events');
    } finally {
      loading = false;
    }
  }

  function isoToLocalInput(iso: string | null): string {
    if (!iso) return '';
    const d = new Date(iso);
    if (isNaN(d.getTime())) return '';
    // YYYY-MM-DDTHH:MM (KST 변환은 브라우저 default)
    const off = d.getTimezoneOffset();
    const local = new Date(d.getTime() - off * 60_000);
    return local.toISOString().slice(0, 16);
  }

  function localInputToIso(s: string): string | null {
    if (!s) return null;
    const d = new Date(s);
    if (isNaN(d.getTime())) return null;
    return d.toISOString();
  }

  async function save() {
    if (!item || saving) return;
    saving = true;
    try {
      const patch: Record<string, unknown> = {};
      if (editTitle !== item.title) patch.title = editTitle;
      if ((editDescription || null) !== (item.description ?? null))
        patch.description = editDescription || null;
      const newDue = localInputToIso(editDueAt);
      if (newDue !== item.due_at) patch.due_at = newDue;
      const newStart = localInputToIso(editStartAt);
      if (newStart !== item.start_at) patch.start_at = newStart;
      const newEnd = localInputToIso(editEndAt);
      if (newEnd !== item.end_at) patch.end_at = newEnd;
      if (editAllDay !== item.all_day) patch.all_day = editAllDay;
      const newPriority = editPriority === '' ? null : Number(editPriority);
      if (newPriority !== item.priority) patch.priority = newPriority;
      if ((editProjectTag || null) !== (item.project_tag ?? null))
        patch.project_tag = editProjectTag || null;

      if (Object.keys(patch).length === 0) {
        addToast('info', '변경 사항 없음');
        return;
      }
      const updated = await patchEvent(item.id, patch);
      item = updated;
      addToast('success', '저장됨');
      // history 가 새 reschedule row 가질 수 있어 reload
      await reloadHistory();
    } catch (err) {
      const detail = (err as { detail?: string })?.detail ?? '저장 실패';
      addToast('error', detail);
    } finally {
      saving = false;
    }
  }

  async function reloadHistory() {
    if (!item) return;
    try {
      const hist = await api<{ items: HistoryEntry[] }>(`/events/${item.id}/history`);
      history = hist.items;
    } catch (err) {
      // silent
    }
  }

  async function lifecycle(action: 'complete' | 'cancel' | 'defer' | 'reactivate') {
    if (!item) return;
    try {
      let updated: EventItem;
      if (action === 'complete') updated = await completeEvent(item.id);
      else if (action === 'cancel') {
        if (!confirm(`"${item.title}" 취소할까요?`)) return;
        updated = await cancelEvent(item.id);
      } else if (action === 'defer') {
        const dt = new Date(Date.now() + 86400_000);
        const input = prompt('연기할 시각 (YYYY-MM-DDTHH:MM, KST)', isoToLocalInput(dt.toISOString()));
        if (!input) return;
        updated = await deferEvent(item.id, new Date(input).toISOString());
      } else {
        updated = await reactivateEvent(item.id);
      }
      item = updated;
      addToast('success', '처리됨');
      await reloadHistory();
    } catch (err) {
      const detail = (err as { detail?: string })?.detail ?? '실패';
      addToast('error', detail);
    }
  }

  function actorLabel(actor: string): string {
    return { manual: '나', eid: '이드', email_ingest: '메일', system: '시스템' }[actor] ?? actor;
  }
</script>

<svelte:head>
  <title>{item?.title ?? 'events'} · hyungi PKM</title>
</svelte:head>

<div class="mx-auto max-w-3xl space-y-6 px-4 py-6">
  <div class="flex items-center gap-2">
    <Button variant="ghost" size="sm" icon={ArrowLeft} href="/events" />
    <h1 class="text-xl font-semibold">events 상세</h1>
  </div>

  {#if loading}
    <Skeleton class="h-64 rounded-lg" />
  {:else if item}
    <Card class="space-y-4 p-4 {KIND_COLOR[item.kind]}">
      <div class="flex flex-wrap items-center gap-2 text-xs text-slate-500">
        <span>{KIND_LABEL[item.kind]}</span>
        <span class="rounded px-1.5 py-0.5 text-[10px] {STATUS_COLOR[item.status]}">
          {STATUS_LABEL[item.status]}
        </span>
        <span class="text-slate-400">id #{item.id}</span>
        <span class="text-slate-400">source: {item.source}</span>
      </div>

      <div class="space-y-3">
        <label class="block">
          <span class="block text-xs text-slate-500">제목</span>
          <TextInput bind:value={editTitle} />
        </label>

        <label class="block">
          <span class="block text-xs text-slate-500">설명 (markdown)</span>
          <Textarea bind:value={editDescription} rows={4} />
        </label>

        {#if item.kind === 'task'}
          <label class="block">
            <span class="block text-xs text-slate-500">마감 (due_at)</span>
            <input type="datetime-local" bind:value={editDueAt} class="rounded-md border border-slate-200 px-2 py-1 text-sm" />
          </label>
        {/if}

        {#if item.kind === 'calendar_event' || item.kind === 'task'}
          <div class="flex flex-wrap gap-3">
            <label class="block">
              <span class="block text-xs text-slate-500">시작 (start_at)</span>
              <input type="datetime-local" bind:value={editStartAt} class="rounded-md border border-slate-200 px-2 py-1 text-sm" />
            </label>
            <label class="block">
              <span class="block text-xs text-slate-500">종료 (end_at)</span>
              <input type="datetime-local" bind:value={editEndAt} class="rounded-md border border-slate-200 px-2 py-1 text-sm" />
            </label>
          </div>
          <label class="inline-flex items-center gap-2 text-sm">
            <input type="checkbox" bind:checked={editAllDay} />
            <span>all-day</span>
          </label>
        {/if}

        <div class="flex flex-wrap gap-3">
          <label class="block">
            <span class="block text-xs text-slate-500">우선순위 (1–4)</span>
            <input type="number" min="1" max="4" bind:value={editPriority} class="w-20 rounded-md border border-slate-200 px-2 py-1 text-sm" />
          </label>
          <label class="block">
            <span class="block text-xs text-slate-500">프로젝트 태그</span>
            <TextInput bind:value={editProjectTag} placeholder="(없음)" />
          </label>
        </div>
      </div>

      <div class="flex flex-wrap items-center justify-between gap-2 pt-2">
        <div class="flex flex-wrap items-center gap-2">
          {#if item.status !== 'done' && item.status !== 'cancelled' && item.kind !== 'activity_log'}
            <Button variant="primary" size="sm" icon={Check} onclick={() => lifecycle('complete')}>완료</Button>
            <Button variant="secondary" size="sm" icon={Pause} onclick={() => lifecycle('defer')}>연기</Button>
            <Button variant="ghost" size="sm" icon={XIcon} onclick={() => lifecycle('cancel')}>취소</Button>
          {:else if (item.status === 'done' || item.status === 'cancelled') && item.kind !== 'activity_log'}
            <Button variant="secondary" size="sm" icon={RotateCcw} onclick={() => lifecycle('reactivate')}>재활성</Button>
          {/if}
        </div>
        <Button variant="primary" size="sm" icon={Save} loading={saving} onclick={save}>저장</Button>
      </div>
    </Card>

    <section class="space-y-2">
      <h2 class="text-sm font-semibold text-slate-700">변경 이력</h2>
      {#if history.length === 0}
        <p class="text-sm text-slate-500">이력 없음</p>
      {:else}
        <ol class="space-y-1.5 border-l border-slate-200 pl-4">
          {#each history as h (h.id)}
            <li class="relative">
              <span class="absolute -left-[21px] top-1.5 h-2 w-2 rounded-full bg-slate-300"></span>
              <div class="text-xs text-slate-500">
                {formatDateTimeKst(h.changed_at)} · {actorLabel(h.changed_by)}
              </div>
              <div class="text-sm">
                {CHANGE_KIND_LABEL[h.change_kind] ?? h.change_kind}
              </div>
            </li>
          {/each}
        </ol>
      {/if}
    </section>
  {/if}
</div>
