'use client';

import { useEffect, useMemo, useState } from 'react';
import { Tag as TagModel } from '@prisma/client';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Checkbox } from '@/components/ui/checkbox';
import { Badge } from '@/components/ui/badge';
import { Loader2, Tag as TagIcon, X } from 'lucide-react';

interface TagSelectionDialogProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  photoIds: number[];
  tags: TagModel[];
  onSuccess?: () => void;
}

export function TagSelectionDialog({
  open,
  onOpenChange,
  photoIds,
  tags,
  onSuccess,
}: TagSelectionDialogProps) {
  const [selectedTagIds, setSelectedTagIds] = useState<number[]>([]);
  const [searchQuery, setSearchQuery] = useState('');
  const [customTags, setCustomTags] = useState<string[]>([]);
  const [customTagInput, setCustomTagInput] = useState('');
  const [notes, setNotes] = useState('');
  const [error, setError] = useState<string | null>(null);
  const [isSubmitting, setIsSubmitting] = useState(false);

  const filteredTags = useMemo(() => {
    if (!searchQuery.trim()) {
      return tags;
    }
    const query = searchQuery.toLowerCase();
    return tags.filter((tag) => tag.tag_name.toLowerCase().includes(query));
  }, [searchQuery, tags]);

  useEffect(() => {
    if (!open) {
      setSelectedTagIds([]);
      setSearchQuery('');
      setCustomTags([]);
      setCustomTagInput('');
      setNotes('');
      setError(null);
    }
  }, [open]);

  useEffect(() => {
    setSelectedTagIds((prev) =>
      prev.filter((id) => tags.some((tag) => tag.id === id))
    );
  }, [tags]);

  const toggleTagSelection = (tagId: number) => {
    setSelectedTagIds((prev) =>
      prev.includes(tagId) ? prev.filter((id) => id !== tagId) : [...prev, tagId]
    );
  };

  const canSubmit =
    photoIds.length > 0 &&
    (selectedTagIds.length > 0 ||
      customTags.length > 0 ||
      customTagInput.trim().length > 0);

  const normalizeTagName = (value: string) => value.trim().replace(/\s+/g, ' ');

  const addCustomTag = () => {
    const candidate = normalizeTagName(customTagInput);
    if (!candidate) {
      setCustomTagInput('');
      return;
    }
    const exists = customTags.some(
      (tag) => tag.toLowerCase() === candidate.toLowerCase()
    );
    if (!exists) {
      setCustomTags((prev) => [...prev, candidate]);
    }
    setCustomTagInput('');
  };

  const removeCustomTag = (tag_name: string) => {
    setCustomTags((prev) =>
      prev.filter((tag) => tag.toLowerCase() !== tag_name.toLowerCase())
    );
  };

  const handleSubmit = async () => {
    setError(null);

    if (photoIds.length === 0) {
      setError('Select at least one photo before tagging.');
      return;
    }

    const normalizedInput = normalizeTagName(customTagInput);
    const proposedTags = [
      ...customTags,
      ...(normalizedInput ? [normalizedInput] : []),
    ];
    const uniqueNewTags = Array.from(
      new Map(
        proposedTags.map((tag) => [tag.toLowerCase(), tag])
      ).values()
    );
    const payload = {
      photoIds,
      tagIds: selectedTagIds.length > 0 ? selectedTagIds : undefined,
      newTagNames: uniqueNewTags.length > 0 ? uniqueNewTags : undefined,
      notes: notes.trim() || undefined,
    };

    try {
      setIsSubmitting(true);
      const response = await fetch('/api/photos/tag-linkages', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(payload),
      });

      const data = await response.json();
      if (!response.ok) {
        throw new Error(data.error || 'Failed to submit tag linkages');
      }

      alert(
        data.message ||
          'Tag submissions sent for approval. An administrator will review them soon.'
      );
      onOpenChange(false);
      onSuccess?.();
      setCustomTags([]);
      setCustomTagInput('');
    } catch (submissionError: any) {
      setError(submissionError.message || 'Failed to submit tag linkages');
    } finally {
      setIsSubmitting(false);
    }
  };

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-[600px]">
        <DialogHeader>
          <DialogTitle>Tag selected photos</DialogTitle>
          <DialogDescription>
            Choose existing tags or propose a new tag. Your request goes to the
            pending queue for admin approval before it appears on the site.
          </DialogDescription>
        </DialogHeader>

        <div className="space-y-5">
          <div className="rounded-md bg-muted/40 p-3 text-sm text-muted-foreground">
            Tagging{' '}
            <span className="font-medium text-foreground">
              {photoIds.length}
            </span>{' '}
            photo{photoIds.length === 1 ? '' : 's'}. Pending linkages require
            administrator approval.
          </div>

          <div className="space-y-2">
            <label className="text-sm font-medium">Choose existing tags</label>
            <Input
              placeholder="Start typing to filter tags..."
              value={searchQuery}
              onChange={(event) => setSearchQuery(event.target.value)}
            />
            <div className="max-h-52 overflow-y-auto rounded-md border p-2 space-y-1">
              {filteredTags.length === 0 ? (
                <p className="text-sm text-muted-foreground px-1">
                  No tags match your search.
                </p>
              ) : (
                filteredTags.map((tag) => (
                  <label
                    key={tag.id}
                    className="flex cursor-pointer items-center gap-2 rounded-md px-2 py-1 hover:bg-muted/60"
                  >
                    <Checkbox
                      checked={selectedTagIds.includes(tag.id)}
                      onCheckedChange={() => toggleTagSelection(tag.id)}
                    />
                    <span className="text-sm">{tag.tag_name}</span>
                  </label>
                ))
              )}
            </div>
            {selectedTagIds.length > 0 && (
              <div className="flex flex-wrap gap-2 pt-1">
                {selectedTagIds.map((id) => {
                  const tag = tags.find((item) => item.id === id);
                  if (!tag) return null;
                  return (
                    <Badge
                      key={id}
                      variant="secondary"
                      className="flex items-center gap-1"
                    >
                      <TagIcon className="h-3 w-3" />
                      {tag.tag_name}
                    </Badge>
                  );
                })}
              </div>
            )}
          </div>

          <div className="space-y-2">
            <label className="text-sm font-medium">
              Add a new tag
            </label>
            <div className="flex flex-col gap-2">
              <Input
                placeholder="Enter a new tag name, press Enter to add"
                value={customTagInput}
                onChange={(event) => setCustomTagInput(event.target.value)}
                onKeyDown={(event) => {
                  if (event.key === 'Enter') {
                    event.preventDefault();
                    addCustomTag();
                  }
                }}
              />
              <div className="flex gap-2">
                <Button
                  type="button"
                  variant="secondary"
                  onClick={addCustomTag}
                >
                  Add
                </Button>
                <Button
                  type="button"
                  variant="outline"
                  onClick={() => {
                    setCustomTags([]);
                    setCustomTagInput('');
                  }}
                  disabled={customTags.length === 0 && !customTagInput.trim()}
                >
                  Clear
                </Button>
              </div>
            </div>
            {customTags.length > 0 && (
              <div className="flex flex-wrap gap-2">
                {customTags.map((tag) => (
                  <Badge key={tag} variant="secondary" className="gap-1">
                    <TagIcon className="h-3 w-3" />
                    {tag}
                    <button
                      type="button"
                      className="ml-1 text-xs text-muted-foreground hover:text-foreground"
                      onClick={() => removeCustomTag(tag)}
                      aria-label={`Remove ${tag}`}
                    >
                      <X className="h-3 w-3" />
                    </button>
                  </Badge>
                ))}
              </div>
            )}
            <p className="text-xs text-muted-foreground">
              Add as many missing tags as you need. Admins will create them during
              review.
            </p>
          </div>

          <div className="space-y-2">
            <label className="text-sm font-medium">
              Notes for admins (optional)
            </label>
            <textarea
              value={notes}
              onChange={(event) => setNotes(event.target.value)}
              className="w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
              rows={3}
              placeholder="Add any additional context to help admins approve faster"
            />
          </div>

          {error && (
            <p className="text-sm text-red-500" role="alert">
              {error}
            </p>
          )}
        </div>

        <DialogFooter className="gap-2 sm:gap-0">
          <Button
            type="button"
            variant="outline"
            onClick={() => onOpenChange(false)}
            disabled={isSubmitting}
          >
            Cancel
          </Button>
          <Button
            type="button"
            onClick={handleSubmit}
            disabled={!canSubmit || isSubmitting}
          >
            {isSubmitting ? (
              <>
                <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                Submitting...
              </>
            ) : (
              'Submit for review'
            )}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

