/**
 * CreateListSheet — new-list creation form (LIST-01, D-01).
 *
 * UI-SPEC §CreateListSheet:
 *   - Mobile: bottom sheet (slides up from bottom, 50vh height, backdrop overlay)
 *   - Desktop: centered modal (max-width 360px)
 *   - Heading: "New list"
 *   - Name input: auto-focused, placeholder "e.g. Groceries"
 *   - Shared/Private toggle: "Shared" default (D-01), clearly labeled
 *   - "Create" button: accent var(--color-member-0), disabled while name empty,
 *     destructive border on blank-submit attempt
 *   - "Cancel": ghost text button
 *   - Escape to close, backdrop click to close
 *
 * Behavior:
 *   - Open/close driven by listsStore.createListSheetOpen
 *   - useMutation(createList) with optimistic insert + onError rollback + onSettled invalidate
 *
 * T-04-06 XSS guard: all text is static or plain-text JSX children (no dangerouslySetInnerHTML).
 */

import { useEffect, useRef, useState } from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { createList } from '../api/listsClient.js';
import type { ListsResponse } from '../api/listsClient.js';
import { useListsStore } from '../store/listsStore.js';

export function CreateListSheet() {
  const isOpen = useListsStore((s) => s.createListSheetOpen);
  const setOpen = useListsStore((s) => s.setCreateListSheetOpen);
  const queryClient = useQueryClient();

  const [name, setName] = useState('');
  const [isShared, setIsShared] = useState(true); // D-01: default shared
  const [attemptedEmpty, setAttemptedEmpty] = useState(false);
  const inputRef = useRef<HTMLInputElement>(null);

  // Auto-focus name input when sheet opens
  useEffect(() => {
    if (isOpen && inputRef.current) {
      inputRef.current.focus();
      // Reset form state on open
      setName('');
      setIsShared(true);
      setAttemptedEmpty(false);
    }
  }, [isOpen]);

  // Escape key listener
  useEffect(() => {
    if (!isOpen) return;
    const onKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'Escape') {
        handleClose();
      }
    };
    document.addEventListener('keydown', onKeyDown);
    return () => document.removeEventListener('keydown', onKeyDown);
  }, [isOpen]); // eslint-disable-line react-hooks/exhaustive-deps

  const handleClose = () => {
    setOpen(false);
    setName('');
    setIsShared(true);
    setAttemptedEmpty(false);
  };

  const mutation = useMutation({
    mutationFn: (payload: { name: string; isShared: boolean }) => createList(payload),
    onMutate: async (payload) => {
      // Optimistic insert: add a temporary entry to the lists cache
      await queryClient.cancelQueries({ queryKey: ['lists'] });
      const previous = queryClient.getQueryData<ListsResponse>(['lists']);
      const tempId = -Date.now(); // negative temp ID so it won't collide with real IDs
      queryClient.setQueryData<ListsResponse>(['lists'], (old) => ({
        lists: [
          ...(old?.lists ?? []),
          {
            id: tempId,
            name: payload.name,
            isShared: payload.isShared,
            ownerId: 0, // unknown until response
            activeCount: 0,
            doneCount: 0,
          },
        ],
      }));
      return { previous };
    },
    onError: (_err, _vars, context) => {
      // Rollback on error
      if (context?.previous) {
        queryClient.setQueryData(['lists'], context.previous);
      }
    },
    onSettled: () => {
      // Always invalidate to get canonical server state; fire-and-forget (React Query handles cache update)
      void queryClient.invalidateQueries({ queryKey: ['lists'] });
    },
    onSuccess: () => {
      handleClose();
    },
  });

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    if (!name.trim()) {
      setAttemptedEmpty(true);
      return;
    }
    mutation.mutate({ name: name.trim(), isShared });
  };

  if (!isOpen) return null;

  const isNameEmpty = !name.trim();
  const inputBorderColor =
    attemptedEmpty && isNameEmpty ? 'var(--color-destructive)' : 'var(--color-border)';

  return (
    <>
      {/* Backdrop */}
      <div
        onClick={handleClose}
        style={{
          position: 'fixed',
          inset: 0,
          background: 'var(--color-overlay)',
          zIndex: 300,
        }}
        aria-hidden="true"
      />

      {/* Sheet / Modal */}
      <div
        role="dialog"
        aria-modal="true"
        aria-label="New list"
        style={{
          position: 'fixed',
          // Mobile: bottom sheet; Desktop: centered modal (via media-query-like inline approach)
          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.15)',
          padding: 'var(--space-6)',
          zIndex: 301,
          fontFamily: 'var(--font-family-base)',
          maxWidth: '480px',
          margin: '0 auto',
        }}
      >
        {/* Heading */}
        <h2
          style={{
            margin: '0 0 var(--space-6) 0',
            fontSize: 'var(--text-heading-size)',
            fontWeight: 600,
            lineHeight: 'var(--text-heading-line-height)',
            color: 'var(--color-text-primary)',
          }}
        >
          {/* Plain text — XSS guard */}
          New list
        </h2>

        <form onSubmit={handleSubmit}>
          {/* Name input */}
          <div style={{ marginBottom: 'var(--space-4)' }}>
            <label
              htmlFor="create-list-name"
              style={{
                display: 'block',
                fontSize: 'var(--text-label-size)',
                fontWeight: 600,
                color: 'var(--color-text-secondary)',
                marginBottom: 'var(--space-2)',
              }}
            >
              {/* Plain text — XSS guard */}
              Name
            </label>
            <input
              ref={inputRef}
              id="create-list-name"
              type="text"
              value={name}
              onChange={(e) => {
                setName(e.target.value);
                if (e.target.value.trim()) setAttemptedEmpty(false);
              }}
              placeholder="e.g. Groceries"
              maxLength={255}
              style={{
                width: '100%',
                boxSizing: 'border-box',
                fontSize: 'var(--text-body-size)',
                fontFamily: 'var(--font-family-base)',
                padding: 'var(--space-2) var(--space-4)',
                border: `1px solid ${inputBorderColor}`,
                borderRadius: 'var(--space-1)',
                background: 'var(--color-surface)',
                color: 'var(--color-text-primary)',
                minHeight: '44px',
                outline: 'none',
              }}
            />
          </div>

          {/* Sharing toggle — Shared / Private (D-01: default Shared) */}
          <div style={{ marginBottom: 'var(--space-6)' }}>
            <div
              style={{
                fontSize: 'var(--text-label-size)',
                fontWeight: 600,
                color: 'var(--color-text-secondary)',
                marginBottom: 'var(--space-2)',
              }}
            >
              {/* Plain text — XSS guard */}
              Visibility
            </div>
            <div
              style={{
                display: 'flex',
                border: '1px solid var(--color-border)',
                borderRadius: 'var(--space-1)',
                overflow: 'hidden',
              }}
              role="group"
              aria-label="List visibility"
            >
              <button
                type="button"
                onClick={() => setIsShared(true)}
                aria-pressed={isShared}
                style={{
                  flex: 1,
                  padding: 'var(--space-2) var(--space-4)',
                  fontSize: 'var(--text-label-size)',
                  fontWeight: 600,
                  fontFamily: 'var(--font-family-base)',
                  border: 'none',
                  cursor: 'pointer',
                  minHeight: '44px',
                  background: isShared ? 'var(--color-member-0)' : 'var(--color-surface)',
                  color: isShared ? '#ffffff' : 'var(--color-text-secondary)',
                }}
              >
                {/* Plain text — XSS guard */}
                Shared
              </button>
              <button
                type="button"
                onClick={() => setIsShared(false)}
                aria-pressed={!isShared}
                style={{
                  flex: 1,
                  padding: 'var(--space-2) var(--space-4)',
                  fontSize: 'var(--text-label-size)',
                  fontWeight: 600,
                  fontFamily: 'var(--font-family-base)',
                  border: 'none',
                  borderLeft: '1px solid var(--color-border)',
                  cursor: 'pointer',
                  minHeight: '44px',
                  background: !isShared ? 'var(--color-member-0)' : 'var(--color-surface)',
                  color: !isShared ? '#ffffff' : 'var(--color-text-secondary)',
                }}
              >
                {/* Plain text — XSS guard */}
                Private
              </button>
            </div>
          </div>

          {/* Actions */}
          <div
            style={{
              display: 'flex',
              flexDirection: 'column',
              gap: 'var(--space-3)',
            }}
          >
            {/* Create button */}
            <button
              type="submit"
              disabled={isNameEmpty || mutation.isPending}
              style={{
                width: '100%',
                minHeight: '48px',
                background: isNameEmpty ? 'var(--color-surface-dim)' : 'var(--color-member-0)',
                color: isNameEmpty ? 'var(--color-text-muted)' : '#ffffff',
                border:
                  attemptedEmpty && isNameEmpty ? '1px solid var(--color-destructive)' : 'none',
                borderRadius: 'var(--space-1)',
                fontSize: 'var(--text-label-size)',
                fontWeight: 600,
                fontFamily: 'var(--font-family-base)',
                cursor: isNameEmpty || mutation.isPending ? 'not-allowed' : 'pointer',
              }}
            >
              {/* Plain text — XSS guard */}
              {mutation.isPending ? 'Creating…' : 'Create'}
            </button>

            {/* Cancel — ghost style */}
            <button
              type="button"
              onClick={handleClose}
              disabled={mutation.isPending}
              style={{
                width: '100%',
                minHeight: '44px',
                background: 'none',
                border: 'none',
                fontSize: 'var(--text-label-size)',
                fontWeight: 600,
                fontFamily: 'var(--font-family-base)',
                color: 'var(--color-text-secondary)',
                cursor: mutation.isPending ? 'not-allowed' : 'pointer',
              }}
            >
              {/* Plain text — XSS guard */}
              Cancel
            </button>
          </div>
        </form>
      </div>
    </>
  );
}
