import React, { useEffect, useState } from 'react';
import { useChatStore } from '../store/chatStore';
import { useUser } from '@/features/auth/hooks/useUser';
import { apiClient } from '@/services/api/client';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { cn } from '@/lib/utils';
import {
  Loader2,
  Plus,
  Trash2,
  LogOut,
  MessageSquare,
  Hash,
  User,
  MoreVertical,
} from 'lucide-react';
import { CreateRoomDialog } from './CreateRoomDialog';
import { useToast } from '@/hooks/useToast';
import { Button } from '@/components/ui/button';
import { ErrorDisplay } from '@/components/ui/ErrorDisplay';
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { ConfirmationDialog } from '@/components/ui/confirmation-dialog';

interface ConversationItemProps {
  conversation: {
    id: string;
    name: string;
    type: string;
    unread_count?: number;
  };
  onSelect: (id: string) => void;
  isSelected: boolean;
}

const ConversationItem: React.FC<ConversationItemProps> = ({
  conversation,
  onSelect,
  isSelected,
}) => {
  const { data: user } = useUser();
  const queryClient = useQueryClient();
  const toast = useToast();
  const { setCurrentConversation } = useChatStore();
  const [showLeaveDialog, setShowLeaveDialog] = useState(false);
  const [showDeleteDialog, setShowDeleteDialog] = useState(false);
  const [mutationError, setMutationError] = useState<Error | null>(null);
  const [retryCount, setRetryCount] = useState(0);
  const [lastMutationType, setLastMutationType] = useState<
    'leave' | 'delete' | null
  >(null);
  const [lastRoomId, setLastRoomId] = useState<string | null>(null);

  // Action 4.4.1.5: Add optimistic update
  const leaveRoomMutation = useMutation({
    mutationFn: async (roomId: string) => {
      await apiClient.delete(
        `/conversations/${roomId}/participants/${user?.id}`,
      );
    },
    onMutate: async (roomId: string) => {
      // Cancel outgoing refetches
      await queryClient.cancelQueries({
        queryKey: ['chatConversations', user?.id],
      });

      // Snapshot previous value
      const previousConversations = queryClient.getQueryData<any[]>(
        ['chatConversations', user?.id],
      );

      // Optimistically remove conversation from list
      if (previousConversations) {
        queryClient.setQueryData<any[]>(
          ['chatConversations', user?.id],
          previousConversations.filter((c) => c.id !== roomId),
        );
      }

      return { previousConversations };
    },
    onError: (error: any, _roomId, context) => {
      // Rollback on error
      if (context?.previousConversations) {
        queryClient.setQueryData(
          ['chatConversations', user?.id],
          context.previousConversations,
        );
      }
      const errorMessage =
        error.response?.data?.error || 'Failed to leave room';
      setMutationError(new Error(errorMessage));
    },
    onSuccess: () => {
      queryClient.invalidateQueries({
        queryKey: ['chatConversations', user?.id],
      });
      toast.success('Left room successfully');
      setCurrentConversation(null);
      setShowLeaveDialog(false);
      setMutationError(null);
    },
  });

  // Action 4.4.1.5: Add optimistic update
  const deleteRoomMutation = useMutation({
    mutationFn: async (roomId: string) => {
      await apiClient.delete(`/conversations/${roomId}`);
    },
    onMutate: async (roomId: string) => {
      // Cancel outgoing refetches
      await queryClient.cancelQueries({
        queryKey: ['chatConversations', user?.id],
      });

      // Snapshot previous value
      const previousConversations = queryClient.getQueryData<any[]>(
        ['chatConversations', user?.id],
      );

      // Optimistically remove conversation from list
      if (previousConversations) {
        queryClient.setQueryData<any[]>(
          ['chatConversations', user?.id],
          previousConversations.filter((c) => c.id !== roomId),
        );
      }

      return { previousConversations };
    },
    onError: (error: any, _roomId, context) => {
      // Rollback on error
      if (context?.previousConversations) {
        queryClient.setQueryData(
          ['chatConversations', user?.id],
          context.previousConversations,
        );
      }
      const errorMessage =
        error.response?.data?.error || 'Failed to delete room';
      setMutationError(new Error(errorMessage));
    },
    onSuccess: () => {
      queryClient.invalidateQueries({
        queryKey: ['chatConversations', user?.id],
      });
      toast.success('Room deleted successfully');
      setCurrentConversation(null);
      setShowDeleteDialog(false);
      setMutationError(null);
      setRetryCount(0);
      setLastMutationType(null);
      setLastRoomId(null);
    },
  });

  const handleLeave = (e: React.MouseEvent) => {
    e.stopPropagation();
    setShowLeaveDialog(true);
  };

  const handleDelete = (e: React.MouseEvent) => {
    e.stopPropagation();
    setShowDeleteDialog(true);
  };

  const confirmLeave = () => {
    setLastMutationType('leave');
    setLastRoomId(conversation.id);
    leaveRoomMutation.mutate(conversation.id);
  };

  const confirmDelete = () => {
    setLastMutationType('delete');
    setLastRoomId(conversation.id);
    deleteRoomMutation.mutate(conversation.id);
  };

  // Action 3.4.1.3: Retry handler for failed mutations
  const handleRetry = async () => {
    if (!lastMutationType || !lastRoomId || retryCount >= 3) return;

    setRetryCount((prev) => prev + 1);
    try {
      if (lastMutationType === 'leave') {
        await leaveRoomMutation.mutateAsync(lastRoomId);
      } else {
        await deleteRoomMutation.mutateAsync(lastRoomId);
      }
    } catch (error) {
      // Error will be handled by mutation's onError
    }
  };

  return (
    <>
      {mutationError && (
        <ErrorDisplay
          error={mutationError}
          variant="banner"
          severity="error"
          context={{
            action: 'managing room',
            resource: 'conversation',
            resourceId: conversation.id,
          }}
          onRetry={retryCount < 3 ? handleRetry : undefined}
          onDismiss={() => {
            setMutationError(null);
            setRetryCount(0);
            setLastMutationType(null);
            setLastRoomId(null);
          }}
        />
      )}
      <div
        onClick={() => onSelect(conversation.id)}
        className={cn(
          'group relative flex items-center justify-between p-3 rounded-xl cursor-pointer transition-all duration-300 border border-transparent',
          isSelected
            ? 'bg-kodo-cyan/10 border-kodo-cyan/30 shadow-[0_0_15px_rgba(102,252,241,0.1)]'
            : 'hover:bg-white/5 hover:border-white/5',
        )}
      >
        <div className="flex items-center gap-3 min-w-0">
          <div
            className={cn(
              'w-8 h-8 rounded-lg flex items-center justify-center transition-colors',
              isSelected
                ? 'bg-kodo-cyan text-kodo-void'
                : 'bg-white/5 text-kodo-secondary group-hover:text-white',
            )}
          >
            {conversation.type === 'direct' ? (
              <User size={14} />
            ) : (
              <Hash size={14} />
            )}
          </div>

          <div className="flex flex-col min-w-0">
            <span
              className={cn(
                'text-sm font-medium truncate transition-colors',
                isSelected
                  ? 'text-white'
                  : 'text-kodo-secondary group-hover:text-white',
              )}
            >
              {conversation.name ||
                `Channel ${conversation.id.substring(0, 4)}`}
            </span>
            {conversation.type !== 'direct' && (
              <span className="text-[10px] text-kodo-secondary/50 uppercase tracking-wider">
                {conversation.type}
              </span>
            )}
          </div>
        </div>

        {conversation.unread_count && conversation.unread_count > 0 ? (
          <span className="bg-kodo-magenta text-white text-[10px] px-1.5 py-0.5 rounded-full font-bold shadow-lg shadow-kodo-magenta/20">
            {conversation.unread_count}
          </span>
        ) : null}

        <DropdownMenu>
          <DropdownMenuTrigger asChild onClick={(e) => e.stopPropagation()}>
            <Button
              variant="ghost"
              size="sm"
              className={cn(
                'h-6 w-6 p-0 opacity-0 group-hover:opacity-100 transition-opacity',
                isSelected
                  ? 'text-kodo-cyan hover:bg-kodo-cyan/20'
                  : 'text-kodo-secondary hover:text-white',
              )}
            >
              <MoreVertical className="h-4 w-4" />
            </Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent
            align="end"
            className="bg-kodo-void border-white/10 text-white"
          >
            <DropdownMenuItem
              onClick={handleLeave}
              className="focus:bg-white/10 cursor-pointer"
            >
              <LogOut className="mr-2 h-4 w-4" />
              Leave Channel
            </DropdownMenuItem>
            {conversation.type !== 'direct' && (
              <DropdownMenuItem
                onClick={handleDelete}
                className="text-kodo-red focus:bg-kodo-red/10 cursor-pointer"
              >
                <Trash2 className="mr-2 h-4 w-4" />
                Delete Channel
              </DropdownMenuItem>
            )}
          </DropdownMenuContent>
        </DropdownMenu>

        {/* Active Indicator Line */}
        {isSelected && (
          <div className="absolute left-0 top-3 bottom-3 w-0.5 bg-kodo-cyan rounded-r-full shadow-[0_0_8px_rgba(102,252,241,0.8)]" />
        )}
      </div>

      <ConfirmationDialog
        open={showLeaveDialog}
        onClose={() => setShowLeaveDialog(false)}
        onConfirm={confirmLeave}
        title="Leave Channel"
        description="Disconnect from this secure frequency? Incoming transmission will cease."
        confirmLabel="Disconnect"
        cancelLabel="Cancel"
        variant="default"
        isLoading={leaveRoomMutation.isPending}
      />
      <ConfirmationDialog
        open={showDeleteDialog}
        onClose={() => setShowDeleteDialog(false)}
        onConfirm={confirmDelete}
        title="Delete Channel"
        description="Permanently purge this channel from the network? This action is irreversible."
        confirmLabel="Purge"
        cancelLabel="Cancel"
        variant="destructive"
        isLoading={deleteRoomMutation.isPending}
      />
    </>
  );
};

export const ChatSidebar: React.FC = () => {
  const { data: user } = useUser();
  const userId = user?.id;
  const queryClient = useQueryClient();
  const {
    conversations,
    currentConversationId,
    setCurrentConversation,
    addConversation,
  } = useChatStore();
  const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false);

  const { data, isLoading, error } = useQuery({
    queryKey: ['chatConversations', userId],
    queryFn: async () => {
      if (!userId) return [];
      const response = await apiClient.get('/conversations');
      return response.data.conversations;
    },
    enabled: !!userId,
  });

  useEffect(() => {
    if (data) {
      data.forEach((conv: any) => {
        if (!conversations.some((c) => c.id === conv.id)) {
          addConversation({
            id: conv.id,
            name: conv.name,
            type: conv.type,
            participants: conv.participants,
            unread_count: 0,
          });
        }
      });
    }
  }, [data, conversations, addConversation]);

  if (isLoading) {
    return (
      <div className="flex-1 flex items-center justify-center">
        <Loader2 className="animate-spin text-kodo-cyan" size={24} />
      </div>
    );
  }

  if (error) {
    return (
      <div className="flex-1 flex items-center justify-center p-4">
        <ErrorDisplay
          error={error instanceof Error ? error : new Error('Signal Lost')}
          variant="card"
          severity="error"
          context={{
            action: 'fetching conversations',
            resource: 'conversations',
          }}
          onRetry={() =>
            queryClient.invalidateQueries({
              queryKey: ['chatConversations', userId],
            })
          }
        />
      </div>
    );
  }

  return (
    <div className="flex flex-col h-full">
      <div className="p-4 border-b border-white/5 bg-white/2 backdrop-blur-sm">
        <div className="flex items-center justify-between mb-1">
          <h2 className="text-sm font-bold text-white tracking-wide uppercase flex items-center gap-2">
            <MessageSquare className="w-4 h-4 text-kodo-cyan" />
            Active Channels
          </h2>
          <span className="text-[10px] font-mono text-kodo-secondary bg-white/5 px-1.5 py-0.5 rounded">
            {conversations.length}
          </span>
        </div>
      </div>

      <div className="flex-1 overflow-y-auto custom-scrollbar p-3 space-y-1">
        {conversations.length === 0 ? (
          <div className="text-kodo-secondary/50 text-sm p-4 text-center italic border border-dashed border-white/5 rounded-xl m-2">
            No active frequencies detected.
            <br />
            Initialize a new channel.
          </div>
        ) : (
          conversations.map((conv) => (
            <ConversationItem
              key={conv.id}
              conversation={conv}
              onSelect={setCurrentConversation}
              isSelected={conv.id === currentConversationId}
            />
          ))
        )}
      </div>

      <div className="p-4 border-t border-white/5 bg-white/2 backdrop-blur-sm">
        <Button
          onClick={() => setIsCreateDialogOpen(true)}
          className="w-full shadow-lg shadow-kodo-cyan/10"
          variant="default"
        >
          <Plus className="mr-2 h-4 w-4" />
          New Channel
        </Button>
      </div>
      <CreateRoomDialog
        open={isCreateDialogOpen}
        onClose={() => setIsCreateDialogOpen(false)}
      />
    </div>
  );
};
