import React, { useEffect, useMemo, useState } from 'react';
import { Box, VStack, Heading, Text, HStack, Badge, Select, Spinner, Table, Thead, Tr, Th, Tbody, Td, IconButton, Tooltip, Switch } from '@chakra-ui/react';
import { FiCheck, FiTrash2 } from 'react-icons/fi';
import { api } from '../services/api';

interface DuplicateItem {
  songId: string;
  title: string;
  artist: string;
  location?: string;
  totalTime?: string;
  averageBpm?: string;
  bitRate?: string;
  playlists: string[];
}

interface DuplicateGroup {
  key: string;
  normalizedTitle: string;
  normalizedArtist: string;
  count: number;
  items: DuplicateItem[];
}

export const DuplicatesViewer: React.FC = () => {
  const [groups, setGroups] = useState<DuplicateGroup[]>([]);
  const [loading, setLoading] = useState(false);
  const [minGroupSize, setMinGroupSize] = useState(2);
  const [processingGroupKey, setProcessingGroupKey] = useState<string | null>(null);
  const [onlyWithPlaylists, setOnlyWithPlaylists] = useState(false);

  const loadDuplicates = async (minSize: number) => {
    setLoading(true);
    try {
      const res = await api.getDuplicateSongs(minSize);
      setGroups(res.groups || []);
    } catch (e) {
      setGroups([]);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    loadDuplicates(minGroupSize);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [minGroupSize]);

  const filteredGroups = useMemo(() => {
    if (!onlyWithPlaylists) return groups;
    return groups.filter(g => g.items.some(it => (it.playlists || []).length > 0));
  }, [groups, onlyWithPlaylists]);

  return (
    <VStack spacing={4} align="stretch">
      <HStack justify="space-between">
        <Heading size="md" color="white">Possible Duplicates</Heading>
        <HStack>
          <Text color="gray.400">Minimum group size</Text>
          <Select
            size="sm"
            value={minGroupSize}
            onChange={(e) => setMinGroupSize(parseInt(e.target.value, 10))}
            bg="gray.700"
            borderColor="gray.600"
            color="white"
            w="120px"
          >
            <option value={2}>2+</option>
            <option value={3}>3+</option>
            <option value={4}>4+</option>
          </Select>
          <HStack pl={4} spacing={2}>
            <Text color="gray.400" fontSize="sm">Only with playlists</Text>
            <Switch
              size="sm"
              isChecked={onlyWithPlaylists}
              onChange={(e) => setOnlyWithPlaylists(e.target.checked)}
              colorScheme="blue"
            />
          </HStack>
        </HStack>
      </HStack>

      {loading ? (
        <HStack><Spinner size="sm" /><Text color="gray.400">Scanning duplicates…</Text></HStack>
      ) : filteredGroups.length === 0 ? (
        <Text color="gray.500">No duplicate groups found.</Text>
      ) : (
        <VStack spacing={4} align="stretch">
          {filteredGroups.map((group) => (
            <Box key={group.key} p={4} bg="gray.800" borderRadius="md" borderWidth="1px" borderColor="gray.700">
              <HStack justify="space-between" mb={2}>
                <HStack>
                  <Badge colorScheme="blue" variant="subtle">{group.count} items</Badge>
                  <Text color="gray.300">{group.normalizedArtist} — {group.normalizedTitle}</Text>
                </HStack>
              </HStack>
              <Box overflowX="auto">
                <Table size="sm" variant="simple" minW="1000px">
                  <Thead>
                    <Tr>
                      <Th color="gray.300">Keep</Th>
                      <Th color="gray.300">Title</Th>
                      <Th color="gray.300">Artist</Th>
                      <Th color="gray.300">Length</Th>
                      <Th color="gray.300">BPM</Th>
                      <Th color="gray.300">Bitrate</Th>
                      <Th color="gray.300">Playlists</Th>
                      <Th color="gray.300">Rekordbox Path</Th>
                    </Tr>
                  </Thead>
                  <Tbody>
                    {group.items.map((it) => (
                      <Tr key={it.songId}>
                        <Td>
                          <HStack>
                            <Tooltip label="Keep this song and merge playlists">
                              <IconButton
                                aria-label="Keep this song"
                                icon={<FiCheck />}
                                size="sm"
                                colorScheme="green"
                                variant="outline"
                                isLoading={processingGroupKey === group.key}
                                onClick={async () => {
                                  setProcessingGroupKey(group.key);
                                  try {
                                    const merged = Array.from(new Set(group.items.flatMap(x => x.playlists || [])));
                                    const allPlaylists = await api.getPlaylists();
                                    const targetId = it.songId;
                                    const idsToRemove = new Set(group.items.map(x => x.songId).filter(id => id !== targetId));
                                    const updated = allPlaylists.map(p => {
                                      if (p.type === 'playlist') {
                                        const tracks = Array.from(new Set([...(p.tracks || []).map(id => idsToRemove.has(id) ? targetId : id)]));
                                        if (merged.includes(p.name) && !tracks.includes(targetId)) {
                                          tracks.push(targetId);
                                        }
                                        return { ...p, tracks };
                                      }
                                      if (p.type === 'folder' && p.children) {
                                        const updateChildren = (nodes: any[]): any[] => nodes.map(node => {
                                          if (node.type === 'playlist') {
                                            const tracks = Array.from(new Set([...(node.tracks || []).map((id: string) => idsToRemove.has(id) ? targetId : id)]));
                                            if (merged.includes(node.name) && !tracks.includes(targetId)) {
                                              tracks.push(targetId);
                                            }
                                            return { ...node, tracks };
                                          }
                                          if (node.children) return { ...node, children: updateChildren(node.children) };
                                          return node;
                                        });
                                        return { ...p, children: updateChildren(p.children) };
                                      }
                                      return p;
                                    });
                                    await api.savePlaylists(updated as any);
                                    await loadDuplicates(minGroupSize);
                                  } finally {
                                    setProcessingGroupKey(null);
                                  }
                                }}
                              />
                            </Tooltip>
                            <Tooltip label="Delete other duplicates (optionally remove music files)">
                              <IconButton
                                aria-label="Delete duplicates"
                                icon={<FiTrash2 />}
                                size="sm"
                                colorScheme="red"
                                variant="outline"
                                isLoading={processingGroupKey === group.key}
                                onClick={async () => {
                                  setProcessingGroupKey(group.key);
                                  try {
                                    const targetId = it.songId;
                                    const others = group.items.map(x => x.songId).filter(id => id !== targetId);
                                    // First merge playlists (safe), then delete redundant songs and optionally their music files
                                    const allPlaylists = await api.getPlaylists();
                                    const updated = allPlaylists.map(p => {
                                      if (p.type === 'playlist') {
                                        const tracks = Array.from(new Set([...(p.tracks || []).map(id => others.includes(id) ? targetId : id)]));
                                        return { ...p, tracks };
                                      }
                                      if (p.type === 'folder' && p.children) {
                                        const updateChildren = (nodes: any[]): any[] => nodes.map(node => {
                                          if (node.type === 'playlist') {
                                            const tracks = Array.from(new Set([...(node.tracks || []).map((id: string) => others.includes(id) ? targetId : id)]));
                                            return { ...node, tracks };
                                          }
                                          if (node.children) return { ...node, children: updateChildren(node.children) };
                                          return node;
                                        });
                                        return { ...p, children: updateChildren(p.children) };
                                      }
                                      return p;
                                    });
                                    await api.savePlaylists(updated as any);
                                    await api.deleteDuplicateSongs(targetId, others, true);
                                    await loadDuplicates(minGroupSize);
                                  } finally {
                                    setProcessingGroupKey(null);
                                  }
                                }}
                              />
                            </Tooltip>
                          </HStack>
                        </Td>
                        <Td color="gray.200">{it.title}</Td>
                        <Td color="gray.200">{it.artist}</Td>
                        <Td color="gray.300">{it.totalTime || '-'}</Td>
                        <Td color="gray.300">{it.averageBpm || '-'}</Td>
                        <Td color="gray.300">{it.bitRate || '-'}</Td>
                        <Td color="gray.300" maxW="400px">{(it.playlists || []).join(', ')}</Td>
                        <Td color="gray.400" whiteSpace="nowrap">{it.location || '-'}</Td>
                      </Tr>
                    ))}
                  </Tbody>
                </Table>
              </Box>
            </Box>
          ))}
        </VStack>
      )}
    </VStack>
  );
};

