import React, { useEffect, useMemo, useRef, useState } from 'react';
import styled from 'styled-components';
import { useQuery } from '@tanstack/react-query';
import { Input, Spinner } from '@/shared/components/ui';
import { searchDependencyTickets } from '@/features/tickets/services/ticketDependencyService';
import type { TicketDependencySearchHit } from '@/features/tickets/services/ticketDependencyService';

const Wrapper = styled.div`
  position: relative;
  width: 100%;
`;

const Dropdown = styled.ul`
  position: absolute;
  z-index: 20;
  top: calc(100% + 4px);
  inset-inline: 0;
  margin: 0;
  padding: 0;
  list-style: none;
  max-height: 240px;
  overflow-y: auto;
  background: ${({ theme }) => theme.colors.background};
  border: 1px solid ${({ theme }) => theme.colors.border};
  border-radius: ${({ theme }) => theme.borderRadius.md};
  box-shadow: ${({ theme }) => theme.shadows.md};
`;

const OptionButton = styled.button`
  width: 100%;
  padding: ${({ theme }) => theme.spacing[3]} ${({ theme }) => theme.spacing[4]};
  border: none;
  background: transparent;
  text-align: start;
  cursor: pointer;
  font-size: ${({ theme }) => theme.typography.fontSize.sm};
  color: ${({ theme }) => theme.colors.text.primary};

  &:hover,
  &:focus-visible {
    background: ${({ theme }) => theme.colors.surface};
    outline: none;
  }
`;

const OptionKey = styled.span`
  font-weight: ${({ theme }) => theme.typography.fontWeight.semibold};
  margin-inline-end: ${({ theme }) => theme.spacing[2]};
`;

const OptionTitle = styled.span`
  color: ${({ theme }) => theme.colors.text.secondary};
`;

const StatusMessage = styled.div`
  padding: ${({ theme }) => theme.spacing[3]} ${({ theme }) => theme.spacing[4]};
  display: flex;
  align-items: center;
  gap: ${({ theme }) => theme.spacing[2]};
  font-size: ${({ theme }) => theme.typography.fontSize.sm};
  color: ${({ theme }) => theme.colors.text.secondary};
`;

interface Props {
  ticketId: string;
  value: TicketDependencySearchHit | null;
  onChange: (hit: TicketDependencySearchHit | null) => void;
  placeholder: string;
  loadingLabel: string;
  errorLabel: string;
  emptyLabel: string;
  disabled?: boolean;
}

export const TicketDependencySearchPicker: React.FC<Props> = ({
  ticketId,
  value,
  onChange,
  placeholder,
  loadingLabel,
  errorLabel,
  emptyLabel,
  disabled = false,
}) => {
  const [search, setSearch] = useState('');
  const [open, setOpen] = useState(false);
  const wrapperRef = useRef<HTMLDivElement>(null);

  const searchQuery = useQuery({
    queryKey: ['ticket-dependency-search', ticketId, search],
    queryFn: () => searchDependencyTickets(ticketId, search),
    enabled: !disabled && search.trim().length >= 2,
  });

  useEffect(() => {
    if (value) {
      setSearch(`${value.ticket_number} — ${value.subject}`);
    } else {
      setSearch('');
    }
  }, [value]);

  useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      if (wrapperRef.current && !wrapperRef.current.contains(event.target as Node)) {
        setOpen(false);
      }
    };
    document.addEventListener('mousedown', handleClickOutside);
    return () => document.removeEventListener('mousedown', handleClickOutside);
  }, []);

  const options = useMemo(() => searchQuery.data ?? [], [searchQuery.data]);

  const handleSelect = (hit: TicketDependencySearchHit) => {
    onChange(hit);
    setSearch(`${hit.ticket_number} — ${hit.subject}`);
    setOpen(false);
  };

  const handleInputChange = (next: string) => {
    setSearch(next);
    setOpen(true);
    if (value && next !== `${value.ticket_number} — ${value.subject}`) {
      onChange(null);
    }
  };

  return (
    <Wrapper ref={wrapperRef}>
      <Input
        value={search}
        onChange={(event) => handleInputChange(event.target.value)}
        onFocus={() => setOpen(true)}
        placeholder={placeholder}
        fullWidth
        disabled={disabled}
        autoComplete="off"
        aria-autocomplete="list"
        aria-expanded={open}
      />

      {open && !disabled && search.trim().length >= 2 && (
        <Dropdown role="listbox">
          {searchQuery.isLoading && (
            <li>
              <StatusMessage role="status">
                <Spinner size="sm" /> {loadingLabel}
              </StatusMessage>
            </li>
          )}
          {searchQuery.isError && (
            <li>
              <StatusMessage role="alert">{errorLabel}</StatusMessage>
            </li>
          )}
          {!searchQuery.isLoading && !searchQuery.isError && options.length === 0 && (
            <li>
              <StatusMessage>{emptyLabel}</StatusMessage>
            </li>
          )}
          {options.map((hit) => (
            <li key={hit.id}>
              <OptionButton type="button" role="option" onClick={() => handleSelect(hit)}>
                <OptionKey>{hit.ticket_number}</OptionKey>
                <OptionTitle>— {hit.subject}</OptionTitle>
              </OptionButton>
            </li>
          ))}
        </Dropdown>
      )}
    </Wrapper>
  );
};
