import React, { useState, useEffect, useRef } from 'react';
import type { ChainMetadata } from '../../../types/protein';

type SearchStatus = 'idle' | 'typing' | 'loading' | 'success' | 'not_found' | 'error';

interface ChainSearchInputProps {
  value: string;
  onValueChange: (value: string) => void;
  onChainSelect: (pdb_id: string, auth_asym_id: string) => void;
  onMetadataLoaded: (metadata: ChainMetadata) => void;
  onClear: () => void;
  resolveChain: (pdb_id: string, auth_asym_id: string) => Promise<ChainMetadata>;
  searchStatus: SearchStatus;
  resolvedLabel?: string;
  errorMessage?: string;
  disabled?: boolean;
}

interface ParsedChain {
  pdb_id: string;
  auth_asym_id: string;
  valid: boolean;
  error?: string;
}

export const ChainSearchInput: React.FC<ChainSearchInputProps> = ({
  value,
  onValueChange,
  onChainSelect,
  onMetadataLoaded,
  onClear,
  resolveChain,
  searchStatus,
  resolvedLabel,
  errorMessage,
  disabled
}) => {
  const [parsed, setParsed] = useState<ParsedChain | null>(null);
  const [debouncedValue, setDebouncedValue] = useState('');
  const lastResolvedKey = useRef<string | null>(null);

  // Debounce input (500ms)
  useEffect(() => {
    const timer = setTimeout(() => {
      setDebouncedValue(value);
    }, 500);

    return () => clearTimeout(timer);
  }, [value]);

  // Parse chain identifier
  const parseChainId = (value: string): ParsedChain => {
    const trimmed = value.trim();
    if (!trimmed) {
      return { pdb_id: '', auth_asym_id: '', valid: false };
    }

    // Accept formats: "3vgm.A", "3VGM:A", "3VGM_A", "3vgm A"
    const separatorRegex = /[.\s:_]+/;
    const parts = trimmed.split(separatorRegex);

    if (parts.length < 2) {
      return {
        pdb_id: '',
        auth_asym_id: '',
        valid: false,
        error: 'Format: PDB_ID + Chain (e.g., "3vgm.A", "3VGM:A", "3VGM_A")'
      };
    }

    const pdb_id = parts[0].trim();
    const auth_asym_id = parts.slice(1).join('').trim(); // Handle multi-char chain IDs

    // Validate PDB ID (4 characters)
    if (pdb_id.length !== 4) {
      return {
        pdb_id,
        auth_asym_id,
        valid: false,
        error: 'PDB ID must be exactly 4 characters'
      };
    }

    // Validate chain ID (at least 1 character)
    if (auth_asym_id.length === 0) {
      return {
        pdb_id,
        auth_asym_id,
        valid: false,
        error: 'Chain ID is required (e.g., "A", "B", "AA")'
      };
    }

    return {
      pdb_id: pdb_id.toLowerCase(),
      auth_asym_id: auth_asym_id.toUpperCase(),
      valid: true
    };
  };

  // Parse and validate when debounced value changes
  useEffect(() => {
    if (!debouncedValue) {
      setParsed(null);
      lastResolvedKey.current = null;
      return;
    }

    const result = parseChainId(debouncedValue);
    setParsed(result);

    if (!result.valid) {
      return;
    }

    // Create key for this chain
    const currentKey = `${result.pdb_id}|${result.auth_asym_id}`;
    
    // Only resolve if key changed (prevent duplicate requests)
    if (currentKey === lastResolvedKey.current) {
      return;
    }
    
    lastResolvedKey.current = currentKey;

    // Valid - trigger resolution (parent manages loading/error state)
    resolveChain(result.pdb_id, result.auth_asym_id)
      .then(metadata => {
        onChainSelect(result.pdb_id, result.auth_asym_id);
        onMetadataLoaded(metadata);
      })
      .catch(() => {
        // Parent handles error state
      });
  }, [debouncedValue, resolveChain, onChainSelect, onMetadataLoaded]);

  const handleClear = () => {
    setParsed(null);
    setDebouncedValue('');
    lastResolvedKey.current = null;
    onClear();
  };

  const getBorderColor = () => {
    if (searchStatus === 'loading') return 'border-blue-400';
    if (searchStatus === 'error' || searchStatus === 'not_found' || (parsed && !parsed.valid)) return 'border-red-400';
    if (searchStatus === 'success') return 'border-green-400';
    return 'border-gray-300';
  };

  const showError = searchStatus === 'error' || searchStatus === 'not_found' || (parsed && !parsed.valid && value);
  const displayError = errorMessage || parsed?.error || 'Invalid chain identifier';

  return (
    <div className="space-y-3">
      <label className="block">
        <span className="text-sm font-medium text-slate-900">Chain Identifier</span>
        <span className="block text-xs text-slate-500 mt-1">
          Format: PDB ID + Chain (e.g., 3vgm.A, 3VGM:A, 3VGM_A, 3vgm A)
        </span>
      </label>
      
      <div className={`relative flex items-center border-2 ${getBorderColor()} rounded-lg transition-all duration-200 focus-within:ring-2 focus-within:ring-slate-900 focus-within:ring-offset-2 bg-white`}>
        <input
          type="text"
          className="flex-1 px-4 py-3 text-sm text-slate-900 bg-transparent rounded-lg outline-none placeholder:text-slate-400 disabled:bg-slate-50 disabled:cursor-not-allowed"
          value={value}
          onChange={(e) => onValueChange(e.target.value)}
          placeholder="e.g., 3vgm.A"
          disabled={disabled}
        />
        
        {value && searchStatus !== 'loading' && (
          <button
            className="absolute right-3 w-7 h-7 flex items-center justify-center text-slate-400 hover:text-slate-600 hover:bg-slate-100 rounded-md transition-colors disabled:cursor-not-allowed"
            onClick={handleClear}
            disabled={disabled}
            title="Clear"
          >
            ✕
          </button>
        )}

        {searchStatus === 'loading' && (
          <div className="absolute right-3 w-5 h-5 border-2 border-slate-200 border-t-slate-900 rounded-full animate-spin" title="Resolving chain..."></div>
        )}
      </div>

      {searchStatus === 'success' && resolvedLabel && (
        <div className="flex items-center gap-2 text-sm text-green-700 bg-green-50 px-3 py-2 rounded-lg border border-green-200">
          <span className="text-base">✓</span>
          <span className="font-medium">{resolvedLabel}</span>
        </div>
      )}

      {showError && (
        <div className="flex items-center gap-2 text-sm text-red-700 bg-red-50 px-3 py-2 rounded-lg border border-red-200">
          <span className="text-base">✗</span>
          <span>{displayError}</span>
        </div>
      )}
    </div>
  );
};
