import * as React from "react";
import { useState, useCallback } from "react";
import { Loader2, Trash2 } from "lucide-react";
import { Button } from "@/components/ui/button";
import {
  Sheet,
  SheetDescription,
  SheetHeader,
  SheetTitle,
  SheetOverlay,
  SheetPortal,
} from "@/components/ui/sheet";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import * as SheetPrimitive from "@radix-ui/react-dialog";
import { cn } from "@/lib/utils";
import { cva } from "class-variance-authority";

const sheetVariants = cva(
  "fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
  {
    variants: {
      side: {
        right:
          "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
      },
    },
    defaultVariants: {
      side: "right",
    },
  }
);

interface EntitySidebarProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  title: string;
  description: string;
  icon: React.ReactNode;
  isCreateMode: boolean;
  isLoading?: boolean;
  hasChanges: boolean;
  isPending: boolean;
  isDeletePending?: boolean;
  onSave: () => void;
  onDelete?: () => void;
  children: React.ReactNode;
  footer?: React.ReactNode;
  className?: string;
  /** Layer level for stacking sidebars (0 = base, 1 = first overlay, etc.) */
  layer?: number;
}

export function EntitySidebar({
  open,
  onOpenChange,
  title,
  description,
  icon,
  isCreateMode,
  isLoading = false,
  hasChanges,
  isPending,
  isDeletePending = false,
  onSave,
  onDelete,
  children,
  footer,
  className,
  layer = 0,
}: EntitySidebarProps) {
  const [showDiscardDialog, setShowDiscardDialog] = useState(false);
  
  // Calculate z-index based on layer (base z-50, each layer adds 10)
  const baseZIndex = 50 + (layer * 10);
  const overlayZIndex = baseZIndex;
  const contentZIndex = baseZIndex + 1;
  
  // Handle attempting to close the sidebar
  const handleOpenChange = useCallback(
    (newOpen: boolean) => {
      if (!newOpen && hasChanges) {
        // User is trying to close but has unsaved changes
        setShowDiscardDialog(true);
      } else {
        setShowDiscardDialog(false);
        onOpenChange(newOpen);
      }
    },
    [hasChanges, onOpenChange]
  );

  // Handle continuing to edit (stay in sidebar)
  const handleContinueEditing = useCallback(() => {
    setShowDiscardDialog(false);
  }, []);

  // Handle discarding changes and closing
  const handleDiscard = useCallback(() => {
    setShowDiscardDialog(false);
    onOpenChange(false);
  }, [onOpenChange]);

  // Handle delete confirmation
  const handleDelete = useCallback(() => {
    if (onDelete && confirm("Are you sure you want to delete this item?")) {
      onDelete();
    }
  }, [onDelete]);

  return (
    <>
      <Sheet open={open} onOpenChange={handleOpenChange}>
        <SheetPortal>
          <SheetOverlay
            className={cn(layer > 0 && "bg-black/60")}
            style={{ zIndex: overlayZIndex }}
            onClick={(e) => {
              // Prevent closing on overlay click if there are unsaved changes
              if (hasChanges) {
                e.preventDefault();
                e.stopPropagation();
                setShowDiscardDialog(true);
              }
            }}
          />
          <SheetPrimitive.Content
            className={cn(sheetVariants({ side: "right" }), "sm:max-w-[480px] flex flex-col", className)}
            style={{ zIndex: contentZIndex }}
            onPointerDownOutside={(e) => {
              // Prevent default close behavior when clicking outside
              if (hasChanges) {
                e.preventDefault();
              }
            }}
            onEscapeKeyDown={(e) => {
              // Prevent default close on escape if has changes
              if (hasChanges) {
                e.preventDefault();
                setShowDiscardDialog(true);
              }
            }}
            onInteractOutside={(e) => {
              // Prevent any interaction outside from closing
              if (hasChanges) {
                e.preventDefault();
              }
            }}
          >
            <SheetHeader className="space-y-3">
              <div className="flex items-center gap-3">
                <div className="p-2 rounded-lg bg-gradient-to-br from-primary/20 to-primary/5 border border-primary/20">
                  {icon}
                </div>
                <div className="flex-1">
                  <SheetTitle>{title}</SheetTitle>
                  <SheetDescription>{description}</SheetDescription>
                </div>
              </div>
            </SheetHeader>

            {isLoading && !isCreateMode ? (
              <div className="flex-1 flex items-center justify-center">
                <Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
              </div>
            ) : (
              <div className="flex-1 flex flex-col gap-6 py-6 overflow-y-auto">
                {children}
              </div>
            )}

            {footer}

            <div className="flex items-center gap-3 pt-4 border-t">
              {!isCreateMode && onDelete && (
                <Button
                  variant="destructive"
                  size="sm"
                  onClick={handleDelete}
                  disabled={isDeletePending}
                >
                  {isDeletePending ? (
                    <Loader2 className="h-4 w-4 animate-spin" />
                  ) : (
                    <Trash2 className="h-4 w-4" />
                  )}
                  <span className="ml-2">Delete</span>
                </Button>
              )}
              <div className="flex-1" />
              <Button variant="outline" onClick={() => handleOpenChange(false)}>
                Cancel
              </Button>
              <Button
                onClick={onSave}
                disabled={isPending || !hasChanges}
              >
                {isPending && <Loader2 className="h-4 w-4 animate-spin mr-2" />}
                {isCreateMode ? "Create" : "Save Changes"}
              </Button>
            </div>
            <SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none disabled:pointer-events-none data-[state=open]:bg-secondary">
              <span className="h-4 w-4 flex items-center justify-center text-lg">&times;</span>
              <span className="sr-only">Close</span>
            </SheetPrimitive.Close>
          </SheetPrimitive.Content>
        </SheetPortal>
      </Sheet>

      {/* Unsaved Changes Confirmation Dialog */}
      <Dialog open={showDiscardDialog} onOpenChange={setShowDiscardDialog}>
        <DialogContent className="sm:max-w-[425px]">
          <DialogHeader>
            <DialogTitle>Unsaved Changes</DialogTitle>
            <DialogDescription>
              You have unsaved changes. Do you want to continue editing or discard your changes?
            </DialogDescription>
          </DialogHeader>
          <DialogFooter className="gap-2 sm:gap-0">
            <Button variant="outline" onClick={handleDiscard}>
              Discard Changes
            </Button>
            <Button onClick={handleContinueEditing}>
              Continue Editing
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </>
  );
}
