import clsx from 'clsx';
/**
 * Bulk tag assignment dialog.
 * Assigns selected tags to multiple entities at once.
 */

import React, { useState, useEffect, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { Modal } from '@/components/ui/Modal';
import { Button } from '@/components/ui/Button';
import { Input } from '@/components/ui/Input';
import { EmptyState } from '@/components/ui/EmptyState';
import { useToast } from '@/components/ui/Toast';
import {
  fetchTags,
  bulkAssignTags,
  type Tag,
  type EntityType,
} from '@/api/tags';

export interface BulkTagDialogProps {
  open: boolean;
  entityType: EntityType;
  entityIds: string[];
  onClose: () => void;
  onAssigned: () => void;
}

export function BulkTagDialog({
  open,
  entityType,
  entityIds,
  onClose,
  onAssigned,
}: BulkTagDialogProps) {
  const { t } = useTranslation();
  const toast = useToast();
  const [tags, setTags] = useState<Tag[]>([]);
  const [loading, setLoading] = useState(false);
  const [selectedTagIds, setSelectedTagIds] = useState<Set<string>>(new Set());
  const [searchQuery, setSearchQuery] = useState('');
  const [submitting, setSubmitting] = useState(false);

  useEffect(() => {
    if (open) {
      setLoading(true);
      fetchTags()
        .then((allTags) => {
          setTags(allTags);
        })
        .catch((err) => {
          const msg = err instanceof Error ? err.message : String(err);
          toast.error(msg);
        })
        .finally(() => setLoading(false));
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [open]);

  const filteredTags = tags.filter((tag) =>
    tag.name.toLowerCase().includes(searchQuery.toLowerCase())
  );

  const handleToggleTag = useCallback((tagId: string) => {
    setSelectedTagIds((prev) => {
      const next = new Set(prev);
      if (next.has(tagId)) {
        next.delete(tagId);
      } else {
        next.add(tagId);
      }
      return next;
    });
  }, []);

  const handleAssign = useCallback(async () => {
    if (selectedTagIds.size === 0 || entityIds.length === 0) return;
    setSubmitting(true);
    try {
      await bulkAssignTags({
        tag_ids: Array.from(selectedTagIds),
        entity_type: entityType,
        entity_ids: entityIds,
      });
      toast.success(t('tags.assignSuccess'));
      setSelectedTagIds(new Set());
      setSearchQuery('');
      onAssigned();
      onClose();
    } catch (err) {
      const msg = err instanceof Error ? err.message : String(err);
      toast.error(msg);
    }
    setSubmitting(false);
  }, [selectedTagIds, entityIds, entityType, toast, t, onAssigned, onClose]);

  return (
    <Modal
      open={open}
      onClose={onClose}
      title={t('tags.bulkAssignTitle')}
      size="md"
      data-testid="bulk-tag-dialog"
    >
      <div className="space-y-4">
        <p className="text-sm text-secondary-500">
          {t('tags.selectedEntities', { count: entityIds.length })}
        </p>

        <Input
          label={t('tags.search')}
          value={searchQuery}
          onChange={(e) => setSearchQuery(e.target.value)}
          placeholder={t('tags.search')}
        />

        {loading ? (
          <p className="text-sm text-secondary-500">{t('tags.loading')}...</p>
        ) : filteredTags.length === 0 ? (
          <EmptyState title={t('tags.noTags')} />
        ) : (
          <div className="flex flex-wrap gap-2 max-h-60 overflow-y-auto" role="list" data-testid="bulk-tag-list">
            {filteredTags.map((tag) => {
              const isSelected = selectedTagIds.has(tag.id);
              return (
                <button
                  key={tag.id}
                  onClick={() => handleToggleTag(tag.id)}
                  className={clsx(
                    'inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-sm font-medium motion-safe:transition-colors min-h-touch',
                    isSelected
                      ? 'bg-primary-600 text-white'
                      : 'bg-secondary-100 text-secondary-700 hover:bg-secondary-200'
                  )}
                  aria-pressed={isSelected}
                  aria-label={`${tag.name} ${isSelected ? '(selected)' : ''}`}
                >
                  <span
                    className="w-2 h-2 rounded-full inline-block"
                    style={{ backgroundColor: tag.color }}
                    aria-hidden="true"
                  />
                  {tag.name}
                </button>
              );
            })}
          </div>
        )}

        {selectedTagIds.size > 0 && (
          <p className="text-sm text-primary-600">
            {t('tags.selectTags', { count: selectedTagIds.size })}
          </p>
        )}

        <div className="flex justify-end gap-3">
          <Button variant="secondary" onClick={onClose}>
            {t('tags.cancel')}
          </Button>
          <Button
            onClick={handleAssign}
            isLoading={submitting}
            disabled={selectedTagIds.size === 0 || entityIds.length === 0}
          >
            {t('tags.bulkAssign')}
          </Button>
        </div>
      </div>
    </Modal>
  );
}
