import React, { ReactNode, useRef, useState } from 'react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Plus, Search, Check, X, LucideIcon } from 'lucide-react';
import { cn } from '@/lib/utils';
import { sharedStyles } from './styles';
import { EmptyState } from './EmptyState';

export type CreationMode = 'instant' | 'inline-form' | 'dialog';

export interface ListItem {
  /**
   * Unique identifier for the item
   */
  id: string;
  /**
   * Display name/title of the item
   */
  display_name: string;
  /**
   * Additional data that can be used for filtering or display
   */
  [key: string]: unknown;
}

export interface ListPanelProps<T extends ListItem> {
  /**
   * Panel title
   */
  title: string;
  /**
   * Icon for the panel header
   */
  icon?: LucideIcon;
  /**
   * Array of items to display
   */
  items: T[];
  /**
   * ID of the currently selected item
   */
  selectedId?: string;
  /**
   * Function to handle item selection
   */
  onItemSelect?: (id: string) => void;
  /**
   * Function to handle item creation
   */
  onCreateItem?: (data?: string) => void | boolean | Promise<void | boolean>;
  /**
   * Function to render each item
   */
  renderItem: (item: T, isSelected: boolean) => ReactNode;
  /**
   * Whether to show search functionality
   */
  showSearch?: boolean;
  /**
   * Custom search filter function
   */
  searchFilter?: (item: T, searchTerm: string) => boolean;
  /**
   * Placeholder text for search input
   */
  searchPlaceholder?: string;
  /**
   * Creation mode
   */
  creationMode?: CreationMode;
  /**
   * Text for the create button
   */
  createButtonText?: string;
  /**
   * Placeholder for creation input (for inline-form mode)
   */
  createPlaceholder?: string;
  /**
   * Icon for empty state
   */
  emptyIcon?: LucideIcon;
  /**
   * Empty state message
   */
  emptyMessage?: string;
  /**
   * Empty state subtitle
   */
  emptySubtitle?: string;
  /**
   * Additional CSS classes
   */
  className?: string;
  /**
   * Whether to show create button
   */
  showCreateButton?: boolean;
  /**
   * Creation form border color variant
   */
  creationBorderVariant?: 'blue' | 'orange';
}

/**
 * Default search filter function
 */
function defaultSearchFilter<T extends ListItem>(item: T, searchTerm: string): boolean {
  const term = searchTerm.toLowerCase();
  return (
    item.display_name.toLowerCase().includes(term) ||
    (typeof item.description === 'string' && item.description.toLowerCase().includes(term)) ||
    (typeof item.role === 'string' && item.role.toLowerCase().includes(term))
  );
}

/**
 * Reusable list sidebar component with consistent header, search, item rendering, and creation
 */
export function ListPanel<T extends ListItem>({
  title,
  icon: Icon,
  items,
  selectedId,
  onItemSelect: _onItemSelect,
  onCreateItem,
  renderItem,
  showSearch = false,
  searchFilter = defaultSearchFilter,
  searchPlaceholder,
  creationMode = 'instant',
  createButtonText = 'Add',
  createPlaceholder,
  emptyIcon: EmptyIcon,
  emptyMessage = 'No items found',
  emptySubtitle,
  className = '',
  showCreateButton = true,
  creationBorderVariant = 'blue',
}: ListPanelProps<T>) {
  const [searchTerm, setSearchTerm] = useState('');
  const [isCreating, setIsCreating] = useState(false);
  const [newItemName, setNewItemName] = useState('');
  const [isSubmittingCreate, setIsSubmittingCreate] = useState(false);
  const createInFlightRef = useRef(false);

  // Filter items based on search term
  const filteredItems = showSearch ? items.filter(item => searchFilter(item, searchTerm)) : items;

  const handleCreateItem = async () => {
    if (createInFlightRef.current) return;
    if (creationMode === 'inline-form' && !newItemName.trim()) return;

    createInFlightRef.current = true;
    setIsSubmittingCreate(true);

    if (creationMode === 'instant') {
      try {
        await onCreateItem?.();
      } finally {
        createInFlightRef.current = false;
        setIsSubmittingCreate(false);
      }
    } else if (creationMode === 'inline-form') {
      try {
        const shouldClose = (await onCreateItem?.(newItemName.trim())) !== false;
        if (shouldClose) {
          setNewItemName('');
          setIsCreating(false);
        }
      } finally {
        createInFlightRef.current = false;
        setIsSubmittingCreate(false);
      }
    } else if (creationMode === 'dialog') {
      try {
        await onCreateItem?.();
      } finally {
        createInFlightRef.current = false;
        setIsSubmittingCreate(false);
      }
    }
  };

  const handleKeyDown = (e: React.KeyboardEvent) => {
    if (isSubmittingCreate) return;

    if (e.key === 'Enter') {
      void handleCreateItem();
    } else if (e.key === 'Escape') {
      setIsCreating(false);
      setNewItemName('');
    }
  };

  const containerClass = sharedStyles.panel.container;
  const headerClass = sharedStyles.panel.header;
  const contentClass = sharedStyles.panel.content;

  const creationBorderClass =
    creationBorderVariant === 'orange' ? 'border-2 border-orange-500' : 'border-2 border-blue-500';

  const headerContent = (
    <>
      <div className={sharedStyles.header.titleContainer}>
        <CardTitle className={Icon ? sharedStyles.header.titleWithIcon : undefined}>
          {Icon && <Icon className="h-5 w-5" />}
          {title}
        </CardTitle>
        {showCreateButton && onCreateItem && (
          <Button
            size="sm"
            variant="default"
            disabled={isSubmittingCreate}
            onClick={() => {
              if (creationMode === 'inline-form') {
                setIsCreating(true);
              } else {
                void handleCreateItem();
              }
            }}
            className={sharedStyles.header.createButton}
            data-testid="create-button"
          >
            <Plus className="h-4 w-4 mr-1" />
            {createButtonText}
          </Button>
        )}
      </div>
      {showSearch && (
        <div className={`${sharedStyles.search.container} mt-3`}>
          <Search className={sharedStyles.search.icon} />
          <Input
            placeholder={searchPlaceholder || `Search ${title.toLowerCase()}...`}
            value={searchTerm}
            onChange={e => setSearchTerm(e.target.value)}
            className={sharedStyles.search.input}
          />
        </div>
      )}
    </>
  );

  const contentArea = (
    <div className={contentClass}>
      {/* Inline creation form */}
      {isCreating && creationMode === 'inline-form' && (
        <Card className={creationBorderClass}>
          <CardContent className={sharedStyles.creation.content}>
            <div className={sharedStyles.creation.inputContainer}>
              <Input
                placeholder={createPlaceholder || `${title.slice(0, -1)} name...`}
                value={newItemName}
                onChange={e => setNewItemName(e.target.value)}
                onKeyDown={handleKeyDown}
                disabled={isSubmittingCreate}
                autoFocus
                className={sharedStyles.creation.input}
              />
              <Button
                size="sm"
                onClick={() => void handleCreateItem()}
                variant="default"
                disabled={isSubmittingCreate || !newItemName.trim()}
                data-testid="form-create-button"
              >
                <Check className="h-4 w-4" />
              </Button>
              <Button
                size="sm"
                onClick={() => {
                  setIsCreating(false);
                  setNewItemName('');
                }}
                variant="ghost"
                disabled={isSubmittingCreate}
                data-testid="form-cancel-button"
              >
                <X className="h-4 w-4" />
              </Button>
            </div>
          </CardContent>
        </Card>
      )}

      {/* Empty state */}
      {filteredItems.length === 0 && !isCreating && EmptyIcon && (
        <EmptyState
          icon={EmptyIcon}
          title={emptyMessage}
          subtitle={emptySubtitle || `Click "${createButtonText}" to create one`}
        />
      )}

      {/* Items list */}
      {filteredItems.length > 0 && (
        <div className={sharedStyles.list.containerWithSpacing}>
          {filteredItems.map(item => (
            <div key={item.id}>{renderItem(item, selectedId === item.id)}</div>
          ))}
        </div>
      )}
    </div>
  );

  return (
    <Card className={cn(containerClass, className)}>
      <CardHeader className={headerClass}>{headerContent}</CardHeader>
      {contentArea}
    </Card>
  );
}
