import { useState, useEffect } from 'react'
import { useQuery } from '@tanstack/react-query'
import { testsApi } from '@/api/tests'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table'
import { Badge } from '@/components/ui/badge'
import { Search, Check } from 'lucide-react'

interface PackTestsManagerProps {
  currentTestIds: string[]
  onTestsChange: (addIds: string[], removeIds: string[]) => void
  disabled?: boolean
}

export function PackTestsManager({
  currentTestIds,
  onTestsChange,
  disabled = false,
}: PackTestsManagerProps) {
  const [search, setSearch] = useState('')
  const [selectedTests, setSelectedTests] = useState<Set<string>>(new Set())
  const [removedTests, setRemovedTests] = useState<Set<string>>(new Set())

  // Load all tests with search
  const { data: testsData, isLoading } = useQuery({
    queryKey: ['tests', 1, 100, search], // Limit to 100 (backend max)
    queryFn: () => testsApi.getTests({ page: 1, limit: 100, search }),
    enabled: !disabled,
  })

  // Initialize selected tests from currentTestIds when it changes
  useEffect(() => {
    const initialSelected = new Set<string>(
      currentTestIds.filter((id) => !removedTests.has(id.toString()))
    )
    setSelectedTests(initialSelected)
    // Reset removed tests when currentTestIds changes (e.g., when opening dialog)
    setRemovedTests(new Set())
  }, [currentTestIds.join(',')]) // Use join to detect array changes

  // Calculate which tests to add/remove when selection changes
  useEffect(() => {
    const currentlySelected = Array.from(selectedTests)
    const removed = Array.from(removedTests)

    // Tests to add: selected but not in currentTestIds and not removed
    const toAdd = currentlySelected.filter(
      (id) => !currentTestIds.includes(id) && !removed.includes(id)
    )
    // Tests to remove: in removedTests
    const toRemove = removed.filter((id) => currentTestIds.includes(id))

    if (toAdd.length > 0 || toRemove.length > 0) {
      onTestsChange(toAdd, toRemove)
    } else if (selectedTests.size > 0 || removedTests.size > 0) {
      // Also notify if selection was cleared
      onTestsChange([], [])
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [selectedTests.size, removedTests.size, currentTestIds.join(',')])

  const handleToggleTest = (testId: string) => {
    if (disabled || !testId) return

    const testIdStr = String(testId)
    const isCurrentlySelected = selectedTests.has(testIdStr) && !removedTests.has(testIdStr)
    const isInCurrentPack = currentTestIds.includes(testIdStr)

    if (isCurrentlySelected) {
      // Deselect test
      const newSelected = new Set(selectedTests)
      newSelected.delete(testIdStr)
      setSelectedTests(newSelected)
      
      // If it was in current pack, mark as removed
      if (isInCurrentPack) {
        setRemovedTests((prev) => new Set([...prev, testIdStr]))
      }
    } else {
      // Select test
      const newSelected = new Set(selectedTests)
      newSelected.add(testIdStr)
      setSelectedTests(newSelected)
      
      // If it was marked as removed, unmark it
      if (removedTests.has(testIdStr)) {
        setRemovedTests((prev) => {
          const newRemoved = new Set(prev)
          newRemoved.delete(testIdStr)
          return newRemoved
        })
      }
    }
  }

  const isTestSelected = (testId: string | number) => {
    const testIdStr = String(testId)
    return selectedTests.has(testIdStr) && !removedTests.has(testIdStr)
  }

  const isTestInCurrentPack = (testId: string | number) => {
    return currentTestIds.includes(String(testId))
  }

  const allTests = testsData?.items || []
  const filteredTests = search
    ? allTests.filter(
        (test) =>
          test.name?.toLowerCase().includes(search.toLowerCase()) ||
          test.id?.toLowerCase().includes(search.toLowerCase())
      )
    : allTests

  return (
    <div className="space-y-4">
      <div className="space-y-2">
        <Label>Manage Tests in Pack</Label>
        <div className="flex items-center space-x-2">
          <Search className="h-4 w-4 text-muted-foreground" />
          <Input
            placeholder="Search tests by name or ID..."
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            className="max-w-sm"
            disabled={disabled}
          />
        </div>
        <p className="text-sm text-muted-foreground">
          Selected tests: {selectedTests.size - removedTests.size} / {allTests.length}
        </p>
      </div>

      {isLoading ? (
        <div className="text-center py-4">Loading tests...</div>
      ) : (
        <div className="border rounded-lg max-h-[400px] overflow-y-auto">
          <Table>
            <TableHeader>
              <TableRow>
                <TableHead className="w-12"></TableHead>
                <TableHead>ID</TableHead>
                <TableHead>Name</TableHead>
                <TableHead>Questions</TableHead>
                <TableHead>Version</TableHead>
                <TableHead>Status</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {filteredTests.length === 0 ? (
                <TableRow>
                  <TableCell colSpan={6} className="text-center text-muted-foreground">
                    No tests found
                  </TableCell>
                </TableRow>
              ) : (
                filteredTests
                  .filter((test) => test.id) // Only show tests with IDs
                  .map((test) => {
                    const testIdStr = String(test.id!)
                    const selected = isTestSelected(testIdStr)
                    const inCurrentPack = isTestInCurrentPack(testIdStr)
                    const newlyRemoved = removedTests.has(testIdStr)

                    return (
                      <TableRow
                        key={test.id}
                        className={selected ? 'bg-muted/50' : ''}
                        onClick={() => handleToggleTest(testIdStr)}
                      >
                      <TableCell>
                        {selected ? (
                          <Check className="h-4 w-4 text-primary" />
                        ) : (
                          <div className="h-4 w-4 border rounded" />
                        )}
                      </TableCell>
                      <TableCell className="font-mono text-sm">{test.id || '-'}</TableCell>
                      <TableCell className="font-medium">{test.name}</TableCell>
                      <TableCell>
                        {typeof test.questions === 'number'
                          ? test.questions
                          : test.questions?.length || 0}
                      </TableCell>
                      <TableCell>{test.version || 'N/A'}</TableCell>
                      <TableCell>
                        {newlyRemoved ? (
                          <Badge variant="destructive">Removed</Badge>
                        ) : selected && inCurrentPack ? (
                          <Badge variant="default">In Pack</Badge>
                        ) : selected ? (
                          <Badge variant="secondary">Selected</Badge>
                        ) : inCurrentPack ? (
                          <Badge variant="outline">In Pack</Badge>
                        ) : null}
                      </TableCell>
                    </TableRow>
                  )
                })
              )}
            </TableBody>
          </Table>
        </div>
      )}
    </div>
  )
}
