import { useState, useRef, useCallback } from 'react';
import {
  Modal,
  Select,
  Typography,
  Radio,
  Tag,
  Space,
  Button,
  Divider,
  message,
} from 'antd';
import { SearchOutlined, SwapOutlined } from '@ant-design/icons';
import { api } from '@/lib/api';
import type { Contact, UnifiedPerson, PeopleListResponse, MergeContactPayload } from '@/types/api';
import { SUPPORT_LEVEL_LABELS, CONTACT_SOURCE_LABELS, CONTACT_SOURCE_COLORS } from '@/types/api';

interface MergeContactModalProps {
  open: boolean;
  targetContact: Contact;
  onClose: () => void;
  onMerged: () => void;
}

type MergeField = 'displayName' | 'email' | 'phone' | 'supportLevel' | 'tags' | 'notes';

export default function MergeContactModal({ open, targetContact, onClose, onMerged }: MergeContactModalProps) {
  const [searchResults, setSearchResults] = useState<UnifiedPerson[]>([]);
  const [searching, setSearching] = useState(false);
  const [sourcePerson, setSourcePerson] = useState<UnifiedPerson | null>(null);
  const [fieldChoices, setFieldChoices] = useState<Record<MergeField, 'target' | 'source'>>({
    displayName: 'target',
    email: 'target',
    phone: 'target',
    supportLevel: 'target',
    tags: 'target',
    notes: 'target',
  });
  const [merging, setMerging] = useState(false);
  const searchTimerRef = useRef<ReturnType<typeof setTimeout>>(undefined);

  const handleSearch = useCallback((value: string) => {
    clearTimeout(searchTimerRef.current);
    if (!value.trim()) {
      setSearchResults([]);
      return;
    }
    searchTimerRef.current = setTimeout(async () => {
      setSearching(true);
      try {
        const { data } = await api.get<PeopleListResponse>('/people', {
          params: { search: value, limit: 8 },
        });
        // Filter out the target contact
        setSearchResults(data.people.filter((p) => p.contactId !== targetContact.id));
      } catch {
        setSearchResults([]);
      } finally {
        setSearching(false);
      }
    }, 300);
  }, [targetContact.id]);

  const handleFieldChoice = (field: MergeField, value: 'target' | 'source') => {
    setFieldChoices((prev) => ({ ...prev, [field]: value }));
  };

  const handleMerge = async () => {
    if (!sourcePerson) {
      message.warning('Please select a person to merge');
      return;
    }

    const colonIdx = sourcePerson.id.indexOf(':');
    const sourceType = colonIdx !== -1 ? sourcePerson.id.substring(0, colonIdx) : 'contact';
    const sourceId = colonIdx !== -1 ? sourcePerson.id.substring(colonIdx + 1) : sourcePerson.id;

    setMerging(true);
    try {
      const payload: MergeContactPayload = {
        sourceType: sourceType as 'user' | 'addr' | 'contact',
        sourceId,
        keepFields: fieldChoices as Record<string, 'source' | 'target'>,
      };
      await api.post(`/people/contacts/${targetContact.id}/merge`, payload);
      message.success('Contacts merged successfully');
      onMerged();
    } catch {
      message.error('Failed to merge contacts');
    } finally {
      setMerging(false);
    }
  };

  const handleClose = () => {
    setSourcePerson(null);
    setSearchResults([]);
    setFieldChoices({
      displayName: 'target',
      email: 'target',
      phone: 'target',
      supportLevel: 'target',
      tags: 'target',
      notes: 'target',
    });
    onClose();
  };

  const getSourceValue = (field: MergeField): string => {
    if (!sourcePerson) return '--';
    switch (field) {
      case 'displayName':
        return sourcePerson.displayName || '--';
      case 'email':
        return sourcePerson.email || '--';
      case 'phone':
        return sourcePerson.phone || '--';
      case 'supportLevel':
        return sourcePerson.supportLevel ? SUPPORT_LEVEL_LABELS[sourcePerson.supportLevel] : '--';
      case 'tags':
        return sourcePerson.tags?.join(', ') || '--';
      case 'notes':
        return '(from source)';
      default:
        return '--';
    }
  };

  const getTargetValue = (field: MergeField): string => {
    switch (field) {
      case 'displayName':
        return targetContact.displayName || '--';
      case 'email':
        return targetContact.email || '--';
      case 'phone':
        return targetContact.phone || '--';
      case 'supportLevel':
        return targetContact.supportLevel ? SUPPORT_LEVEL_LABELS[targetContact.supportLevel] : '--';
      case 'tags':
        return targetContact.tags?.join(', ') || '--';
      case 'notes':
        return targetContact.notes || '--';
      default:
        return '--';
    }
  };

  const mergeFields: { field: MergeField; label: string }[] = [
    { field: 'displayName', label: 'Display Name' },
    { field: 'email', label: 'Email' },
    { field: 'phone', label: 'Phone' },
    { field: 'supportLevel', label: 'Support Level' },
    { field: 'tags', label: 'Tags (union of both)' },
    { field: 'notes', label: 'Notes (concatenated)' },
  ];

  return (
    <Modal
      title={
        <Space>
          <SwapOutlined />
          <span>Merge Contacts</span>
        </Space>
      }
      open={open}
      onCancel={handleClose}
      width={700}
      footer={[
        <Button key="cancel" onClick={handleClose}>
          Cancel
        </Button>,
        <Button
          key="merge"
          type="primary"
          danger
          onClick={handleMerge}
          loading={merging}
          disabled={!sourcePerson}
        >
          Confirm Merge
        </Button>,
      ]}
    >
      {/* Search for source person */}
      <div style={{ marginBottom: 20 }}>
        <Typography.Text type="secondary" style={{ fontSize: 12, display: 'block', marginBottom: 4 }}>
          Search for the person to merge INTO this contact:
        </Typography.Text>
        <Select
          showSearch
          placeholder="Search by name, email, or phone..."
          filterOption={false}
          onSearch={handleSearch}
          loading={searching}
          notFoundContent={searching ? 'Searching...' : 'No results'}
          style={{ width: '100%' }}
          value={sourcePerson?.id}
          onChange={(value) => {
            const person = searchResults.find((p) => p.id === value);
            setSourcePerson(person || null);
          }}
          options={searchResults.map((p) => ({
            value: p.id,
            label: (
              <div>
                <span style={{ fontWeight: 500 }}>{p.displayName}</span>
                {p.email && (
                  <span style={{ color: '#888', marginLeft: 8, fontSize: 12 }}>
                    {p.email}
                  </span>
                )}
                <Tag
                  color={CONTACT_SOURCE_COLORS[p.source]}
                  style={{ marginLeft: 8, fontSize: 10 }}
                >
                  {CONTACT_SOURCE_LABELS[p.source]}
                </Tag>
              </div>
            ),
          }))}
          suffixIcon={<SearchOutlined />}
        />
      </div>

      {sourcePerson && (
        <>
          {/* Side-by-side header */}
          <div style={{ display: 'flex', gap: 16, marginBottom: 16 }}>
            <div
              style={{
                flex: 1,
                padding: 12,
                background: 'rgba(82, 196, 26, 0.08)',
                borderRadius: 8,
                border: '1px solid rgba(82, 196, 26, 0.2)',
                textAlign: 'center',
              }}
            >
              <Typography.Text strong style={{ fontSize: 12, color: '#52c41a' }}>
                TARGET (Keep)
              </Typography.Text>
              <div style={{ marginTop: 4 }}>
                <Typography.Text strong>{targetContact.displayName}</Typography.Text>
              </div>
            </div>
            <div
              style={{
                flex: 1,
                padding: 12,
                background: 'rgba(24, 144, 255, 0.08)',
                borderRadius: 8,
                border: '1px solid rgba(24, 144, 255, 0.2)',
                textAlign: 'center',
              }}
            >
              <Typography.Text strong style={{ fontSize: 12, color: '#1890ff' }}>
                SOURCE (Merge In)
              </Typography.Text>
              <div style={{ marginTop: 4 }}>
                <Typography.Text strong>{sourcePerson.displayName}</Typography.Text>
              </div>
            </div>
          </div>

          <Divider style={{ margin: '12px 0' }}>Field Selection</Divider>

          {/* Field-by-field selection */}
          {mergeFields.map(({ field, label }) => (
            <div
              key={field}
              style={{
                display: 'flex',
                alignItems: 'center',
                gap: 12,
                marginBottom: 12,
                padding: '8px 0',
                borderBottom: '1px solid rgba(255,255,255,0.06)',
              }}
            >
              <Typography.Text style={{ width: 130, fontSize: 13, flexShrink: 0 }}>
                {label}
              </Typography.Text>
              <Radio.Group
                value={fieldChoices[field]}
                onChange={(e) => handleFieldChoice(field, e.target.value)}
                size="small"
              >
                <Radio.Button value="target">
                  <span style={{ fontSize: 11 }}>{getTargetValue(field)}</span>
                </Radio.Button>
                <Radio.Button value="source">
                  <span style={{ fontSize: 11 }}>{getSourceValue(field)}</span>
                </Radio.Button>
              </Radio.Group>
            </div>
          ))}

          <Typography.Text type="secondary" style={{ fontSize: 11, display: 'block', marginTop: 8 }}>
            The source person will be marked as merged. Tags will be combined from both contacts.
            Notes will be concatenated. All activity history will be preserved.
          </Typography.Text>
        </>
      )}
    </Modal>
  );
}
