/**
 * EventDetailPopover — read-only event detail overlay (Phase 2).
 *
 * Phase 3 note: This component is built for reuse as the edit surface.
 * Reserve the footer action area (marked below) — Phase 3 adds edit/delete here (D-08).
 *
 * Rendering modes:
 *   1. Driven by Zustand openEventId + TanStack Query cache (primary mode)
 *   2. Passed calendarEvent prop by Schedule-X customComponents.eventModal
 *
 * Responsive:
 *   - Phone (≤767px): bottom sheet (slides from bottom)
 *   - Tablet/desktop (≥768px): anchored popover (max-width 360px)
 *
 * Security: T-02e-01 — all event fields rendered as plain-text JSX children.
 * NEVER inject raw HTML for any event field. All fields are plain-text JSX children.
 *
 * Accessibility:
 *   - Focus trap while open
 *   - Escape closes and returns focus to triggering element
 *   - Close button: aria-label="Close", min 44px touch target
 *   - aria-modal="true", role="dialog"
 */

import { useEffect, useRef } from 'react';
import { useQueryClient } from '@tanstack/react-query';
import { MapPin, Edit2, Trash2 } from 'lucide-react';
import { useCalendarStore } from '../store/calendarStore.js';
import type { CalendarOccurrence } from '../api/client.js';

// ── Types ──────────────────────────────────────────────────────────────────

/** Shape of props passed by Schedule-X customComponents.eventModal */
interface ScheduleXEventModalProps {
  calendarEvent?: {
    id?: string | number;
    title?: string;
    start?: unknown;
    end?: unknown;
    calendarId?: string;
    location?: string;
    description?: string;
    _familySync?: { uid: string; color: string; isShared: boolean };
  };
}

// ── Helpers ────────────────────────────────────────────────────────────────

/**
 * Format a start/end pair for display.
 * Handles both timed (IANA-annotated ISO e.g. '2026-06-18T08:00:00-04:00[America/Toronto]')
 * and all-day ('YYYY-MM-DD') strings.
 *
 * The IANA bracket suffix '[Zone]' is stripped before passing to new Date() because
 * the built-in Date constructor cannot parse it and returns Invalid Date (BUG 3).
 */
function formatDateTime(start: string, end: string, allDay: boolean): string {
  if (allDay) {
    // YYYY-MM-DD — format as a date without time
    try {
      const d = new Date(start + 'T00:00:00');
      return d.toLocaleDateString(undefined, {
        weekday: 'short',
        year: 'numeric',
        month: 'long',
        day: 'numeric',
      });
    } catch {
      return start;
    }
  }
  // Timed — parse offset-aware ISO string.
  // Strip trailing IANA bracket e.g. '[America/Toronto]' before passing to new Date():
  // new Date() cannot parse the bracket notation and returns Invalid Date.
  try {
    const cleanStart = start.replace(/\[[^\]]*\]$/, '');
    const cleanEnd = end.replace(/\[[^\]]*\]$/, '');
    const startDate = new Date(cleanStart);
    const endDate = new Date(cleanEnd);
    const dateStr = startDate.toLocaleDateString(undefined, {
      weekday: 'short',
      month: 'long',
      day: 'numeric',
    });
    const startTime = startDate.toLocaleTimeString(undefined, {
      hour: 'numeric',
      minute: '2-digit',
    });
    const endTime = endDate.toLocaleTimeString(undefined, {
      hour: 'numeric',
      minute: '2-digit',
    });
    return `${dateStr}, ${startTime} – ${endTime}`;
  } catch {
    return start;
  }
}

// ── Component ──────────────────────────────────────────────────────────────

/**
 * EventDetailPopover renders when openEventId is non-null (Zustand) or when
 * Schedule-X passes a calendarEvent prop (customComponents.eventModal mode).
 *
 * In Schedule-X modal mode the component receives props from the library.
 * In standalone mode it resolves the event from TanStack Query cache.
 */
export function EventDetailPopover(props: ScheduleXEventModalProps = {}) {
  const { openEventId, setOpenEventId } = useCalendarStore();
  const setEventForm = useCalendarStore((s) => s.setEventForm);
  const setDeleteDialog = useCalendarStore((s) => s.setDeleteDialog);
  const queryClient = useQueryClient();
  const dialogRef = useRef<HTMLDivElement>(null);

  // Resolve the event to display:
  // 1. If Schedule-X passed a calendarEvent prop, use it to get the id
  // 2. Otherwise use Zustand openEventId
  const activeId: string | null = (() => {
    if (props.calendarEvent?.id != null) {
      return String(props.calendarEvent.id);
    }
    return openEventId;
  })();

  // Lookup the occurrence in TanStack Query cache.
  // We search all 'events' query entries for a matching id.
  const occurrence: CalendarOccurrence | null = (() => {
    if (!activeId) return null;
    // queryClient.getQueriesData returns [{queryKey, data}] entries
    const allEntries = queryClient.getQueriesData<{ occurrences: CalendarOccurrence[] }>({
      queryKey: ['events'],
    });
    for (const [, data] of allEntries) {
      if (!data?.occurrences) continue;
      const found = data.occurrences.find((o) => o.id === activeId);
      if (found) return found;
    }
    return null;
  })();

  // Close handler
  const handleClose = () => setOpenEventId(null);

  // Escape key listener — add to document so it works even when focus is trapped
  useEffect(() => {
    if (!activeId) return;
    const onKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'Escape') {
        handleClose();
      }
    };
    document.addEventListener('keydown', onKeyDown);
    return () => document.removeEventListener('keydown', onKeyDown);
  }, [activeId]); // eslint-disable-line react-hooks/exhaustive-deps

  // Focus trap — when popover opens, focus the dialog
  useEffect(() => {
    if (activeId && dialogRef.current) {
      dialogRef.current.focus();
    }
  }, [activeId]);

  // Nothing to show
  if (!activeId || !occurrence) return null;

  // Responsive: detect phone breakpoint
  const isPhone = typeof window !== 'undefined' && window.matchMedia('(max-width: 767px)').matches;

  const dialogStyle: React.CSSProperties = isPhone
    ? {
        // Phone: bottom sheet
        position: 'fixed',
        bottom: 0,
        left: 0,
        right: 0,
        background: 'var(--color-surface-raised)',
        borderRadius: 'var(--space-3) var(--space-3) 0 0',
        boxShadow: '0 -4px 24px rgba(0,0,0,0.12)',
        padding: 'var(--space-6)',
        maxHeight: '80dvh',
        overflowY: 'auto',
        zIndex: 200,
        fontFamily: 'var(--font-family-base)',
      }
    : {
        // Tablet/desktop: centered popover (max-width 360px)
        position: 'fixed',
        top: '50%',
        left: '50%',
        transform: 'translate(-50%, -50%)',
        background: 'var(--color-surface-raised)',
        borderRadius: 'var(--space-2)',
        boxShadow: '0 8px 32px rgba(0,0,0,0.16)',
        padding: 'var(--space-6)',
        width: '100%',
        maxWidth: '360px',
        maxHeight: '80dvh',
        overflowY: 'auto',
        zIndex: 200,
        fontFamily: 'var(--font-family-base)',
      };

  return (
    <>
      {/* Backdrop */}
      <div
        data-testid="popover-backdrop"
        onClick={handleClose}
        style={{
          position: 'fixed',
          inset: 0,
          background: 'var(--color-overlay)',
          zIndex: 199,
        }}
      />

      {/* Dialog */}
      <div
        ref={dialogRef}
        role="dialog"
        aria-modal="true"
        aria-label={occurrence.title}
        tabIndex={-1}
        style={dialogStyle}
      >
        {/* Header: close button */}
        <div
          style={{
            display: 'flex',
            justifyContent: 'flex-end',
            marginBottom: 'var(--space-2)',
          }}
        >
          <button
            aria-label="Close"
            onClick={handleClose}
            style={{
              background: 'none',
              border: 'none',
              cursor: 'pointer',
              minWidth: '44px',
              minHeight: '44px',
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
              fontSize: '20px',
              color: 'var(--color-text-secondary)',
              borderRadius: 'var(--space-1)',
              padding: 0,
            }}
          >
            ×
          </button>
        </div>

        {/* Color chip + title */}
        <div
          style={{
            display: 'flex',
            alignItems: 'flex-start',
            gap: 'var(--space-3)',
            marginBottom: 'var(--space-4)',
          }}
        >
          <span
            style={{
              width: '12px',
              height: '12px',
              borderRadius: '50%',
              background: occurrence.color,
              flexShrink: 0,
              marginTop: '4px',
            }}
            aria-hidden="true"
          />
          <h2
            style={{
              margin: 0,
              fontSize: 'var(--text-heading-size)',
              fontWeight: 'var(--text-heading-weight)',
              lineHeight: 'var(--text-heading-line-height)',
              color: 'var(--color-text-primary)',
              fontFamily: 'var(--font-family-base)',
            }}
          >
            {/* Plain text child only — XSS guard (T-02e-01) */}
            {occurrence.title}
          </h2>
        </div>

        {/* Date/time */}
        <div
          style={{
            fontSize: 'var(--text-label-size)',
            fontWeight: 'var(--text-label-weight)',
            lineHeight: 'var(--text-label-line-height)',
            color: 'var(--color-text-secondary)',
            marginBottom: 'var(--space-3)',
            fontFamily: 'var(--font-family-base)',
          }}
        >
          {/* Plain text — XSS guard */}
          {formatDateTime(occurrence.start, occurrence.end, occurrence.allDay)}
        </div>

        {/* Location (optional) */}
        {occurrence.location != null && (
          <div
            style={{
              display: 'flex',
              alignItems: 'flex-start',
              gap: 'var(--space-2)',
              fontSize: 'var(--text-label-size)',
              color: 'var(--color-text-secondary)',
              marginBottom: 'var(--space-3)',
              fontFamily: 'var(--font-family-base)',
            }}
          >
            <MapPin size={14} style={{ flexShrink: 0, marginTop: '2px' }} aria-hidden="true" />
            {/* Plain text — XSS guard */}
            <span>{occurrence.location}</span>
          </div>
        )}

        {/* Description (optional) — max 4 lines then scroll */}
        {occurrence.description != null && (
          <div
            data-testid="event-description"
            style={{
              fontSize: 'var(--text-body-size)',
              fontWeight: 'var(--text-body-weight)',
              lineHeight: 'var(--text-body-line-height)',
              color: 'var(--color-text-primary)',
              marginBottom: 'var(--space-4)',
              maxHeight: `calc(var(--text-body-size) * var(--text-body-line-height) * 4)`,
              overflowY: 'auto',
              fontFamily: 'var(--font-family-base)',
              // Plain text — XSS guard: rendered as {occurrence.description} text child only
              whiteSpace: 'pre-wrap',
            }}
          >
            {/* Plain text child only — XSS guard (T-02e-01) */}
            {occurrence.description}
          </div>
        )}

        {/* Calendar name + owner color swatch */}
        <div
          style={{
            display: 'flex',
            alignItems: 'center',
            gap: 'var(--space-2)',
            fontSize: 'var(--text-label-size)',
            color: 'var(--color-text-muted)',
            paddingTop: 'var(--space-3)',
            borderTop: '1px solid var(--color-border-subtle)',
            fontFamily: 'var(--font-family-base)',
          }}
        >
          <span
            style={{
              width: '10px',
              height: '10px',
              borderRadius: '2px',
              background: occurrence.color,
              flexShrink: 0,
            }}
            aria-hidden="true"
          />
          {/* Plain text — XSS guard (T-02e-01).
              Show 'Family' for shared-calendar events; owner display name for personal
              events; fall back to calendarName when ownerName is null. */}
          {occurrence.isShared ? 'Family' : (occurrence.ownerName ?? occurrence.calendarName)}
        </div>

        {/* Phase 3 footer: Edit / Delete actions (D-10) */}
        <div
          style={{
            display: 'flex',
            justifyContent: 'space-between',
            alignItems: 'center',
            marginTop: 'var(--space-4)',
            paddingTop: 'var(--space-3)',
            borderTop: '1px solid var(--color-border-subtle)',
          }}
        >
          {/* Edit button — ghost style, left-aligned */}
          <button
            aria-label="Edit event"
            onClick={() => {
              setEventForm(true, 'edit', occurrence.uid);
              setOpenEventId(null);
            }}
            style={{
              background: 'none',
              border: 'none',
              cursor: 'pointer',
              minWidth: '44px',
              minHeight: '44px',
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
              gap: 'var(--space-1)',
              fontSize: 'var(--text-label-size)',
              fontWeight: 'var(--text-label-weight)',
              color: 'var(--color-text-primary)',
              borderRadius: 'var(--space-1)',
              padding: '0 var(--space-2)',
              fontFamily: 'var(--font-family-base)',
            }}
          >
            <Edit2 size={16} aria-hidden="true" />
            {/* Plain text — XSS guard */}
            Edit
          </button>

          {/* Delete button — ghost style, right-aligned, destructive color */}
          <button
            aria-label="Delete event"
            onClick={() => {
              setDeleteDialog(true, occurrence.uid);
            }}
            style={{
              background: 'none',
              border: 'none',
              cursor: 'pointer',
              minWidth: '44px',
              minHeight: '44px',
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
              gap: 'var(--space-1)',
              fontSize: 'var(--text-label-size)',
              fontWeight: 'var(--text-label-weight)',
              color: 'var(--color-destructive)',
              borderRadius: 'var(--space-1)',
              padding: '0 var(--space-2)',
              fontFamily: 'var(--font-family-base)',
            }}
          >
            <Trash2 size={16} aria-hidden="true" />
            {/* Plain text — XSS guard */}
            Delete
          </button>
        </div>
      </div>
    </>
  );
}
