import { useState, useMemo, useCallback, useEffect } from "react";
import { apiFetch } from '@/utils/api';
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { Button } from "@/components/ui/button";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Checkbox } from "@/components/ui/checkbox";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { ArrowUpDown, Pencil, Trash2, PlusCircle, Image, Eye } from "lucide-react";
import config from "@/config";
import {
  useReactTable,
  getCoreRowModel,
  getSortedRowModel,
  SortingState,
  flexRender,
  type ColumnDef,
} from "@tanstack/react-table";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogClose
} from "@/components/ui/dialog";
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { toast } from "sonner";
import { useDropzone } from "react-dropzone";
import { cn } from "@/lib/utils";
import { AuthedImage } from "@/components/ui/authed-image";

interface FieldOption {
  label: string;
  value: string;
}

interface ImageFormData {
  id?: number;
  name: string;
  is_global: boolean;
  company: string | null;
  file?: File;
}

interface ReusableImage {
  id: number;
  name: string;
  filename: string;
  file_path: string;
  image_url: string;
  is_global: boolean;
  company: string | null;
  mime_type: string;
  file_size: number;
  created_at: string;
  updated_at: string;
}

interface FieldOptions {
  companies: FieldOption[];
}

const ImageForm = ({ 
  editingImage, 
  formData, 
  setFormData, 
  onSubmit, 
  onCancel, 
  fieldOptions,
  getRootProps,
  getInputProps,
  isDragActive 
}: {
  editingImage: ReusableImage | null;
  formData: ImageFormData;
  setFormData: (data: ImageFormData | ((prev: ImageFormData) => ImageFormData)) => void;
  onSubmit: (e: React.FormEvent) => void;
  onCancel: () => void;
  fieldOptions: FieldOptions | undefined;
  getRootProps: any;
  getInputProps: any;
  isDragActive: boolean;
}) => {
  const handleNameChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
    setFormData((prev: ImageFormData) => ({ ...prev, name: e.target.value }));
  }, [setFormData]);

  const handleGlobalChange = useCallback((checked: boolean) => {
    setFormData((prev: ImageFormData) => ({ 
      ...prev, 
      is_global: checked,
      company: checked ? null : prev.company
    }));
  }, [setFormData]);

  const handleCompanyChange = useCallback((value: string) => {
    setFormData((prev: ImageFormData) => ({ ...prev, company: value }));
  }, [setFormData]);

  return (
    <form onSubmit={onSubmit}>
      <div className="grid gap-4 py-4">
        <div className="grid gap-2">
          <Label htmlFor="image_name">Image Name</Label>
          <Input
            id="image_name"
            name="image_name"
            value={formData.name}
            onChange={handleNameChange}
            placeholder="Enter image name"
            required
          />
        </div>
        
        {!editingImage && (
          <div className="grid gap-2">
            <Label htmlFor="image">Upload Image</Label>
            <div 
              {...getRootProps()}
              className={cn(
                "border-2 border-dashed border-secondary-foreground/30 bg-muted/90 rounded-md w-full py-6 flex flex-col items-center justify-center cursor-pointer hover:bg-muted/70 transition-colors",
                isDragActive && "border-primary bg-muted"
              )}
            >
              <input {...getInputProps()} />
              <div className="flex flex-col items-center justify-center py-2">
                {formData.file ? (
                  <>
                    <div className="mb-4">
                      <ImagePreview file={formData.file} />
                    </div>
                    <div className="flex items-center gap-2 mb-2">
                      <Image className="h-4 w-4 text-primary" />
                      <span className="text-sm">{formData.file.name}</span>
                    </div>
                    <p className="text-xs text-muted-foreground">Click or drag to replace</p>
                  </>
                ) : isDragActive ? (
                  <>
                    <Image className="h-8 w-8 mb-2 text-primary" />
                    <p className="text-base text-muted-foreground">Drop image here</p>
                  </>
                ) : (
                  <>
                    <Image className="h-8 w-8 mb-2 text-muted-foreground" />
                    <p className="text-base text-muted-foreground">Click or drag to upload</p>
                  </>
                )}
              </div>
            </div>
          </div>
        )}
        
        <div className="flex items-center space-x-2">
          <Checkbox 
            id="is_global" 
            checked={formData.is_global}
            onCheckedChange={handleGlobalChange}
          />
          <Label htmlFor="is_global">Available for all companies</Label>
        </div>
        
        {!formData.is_global && (
          <div className="grid gap-2">
            <Label htmlFor="company">Company</Label>
            <Select
              value={formData.company || ''}
              onValueChange={handleCompanyChange}
              required={!formData.is_global}
            >
              <SelectTrigger>
                <SelectValue placeholder="Select company" />
              </SelectTrigger>
              <SelectContent>
                {fieldOptions?.companies.map((company) => (
                  <SelectItem key={company.value} value={company.value}>
                    {company.label}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
        )}
      </div>
      
      <DialogFooter>
        <Button type="button" variant="outline" onClick={onCancel}>
          Cancel
        </Button>
        <Button type="submit">
          {editingImage ? "Update" : "Upload"} Image
        </Button>
      </DialogFooter>
    </form>
  );
};

export function ReusableImageManagement() {
  const [isFormOpen, setIsFormOpen] = useState(false);
  const [isDeleteOpen, setIsDeleteOpen] = useState(false);
  const [isPreviewOpen, setIsPreviewOpen] = useState(false);
  const [imageToDelete, setImageToDelete] = useState<ReusableImage | null>(null);
  const [previewImage, setPreviewImage] = useState<ReusableImage | null>(null);
  const [editingImage, setEditingImage] = useState<ReusableImage | null>(null);
  const [sorting, setSorting] = useState<SortingState>([
    { id: "created_at", desc: true }
  ]);
  const [searchQuery, setSearchQuery] = useState("");
  const [formData, setFormData] = useState<ImageFormData>({
    name: "",
    is_global: false,
    company: null,
    file: undefined
  });

  const queryClient = useQueryClient();

  const { data: images, isLoading } = useQuery<ReusableImage[]>({
    queryKey: ["reusable-images"],
    queryFn: async () => {
      const response = await apiFetch(`${config.apiUrl}/reusable-images`);
      if (!response.ok) {
        throw new Error("Failed to fetch reusable images");
      }
      return response.json();
    },
  });

  const { data: fieldOptions } = useQuery<FieldOptions>({
    queryKey: ["fieldOptions"],
    queryFn: async () => {
      const response = await apiFetch(`${config.apiUrl}/import/field-options`);
      if (!response.ok) {
        throw new Error("Failed to fetch field options");
      }
      return response.json();
    },
  });

  const createMutation = useMutation({
    mutationFn: async (data: ImageFormData) => {
      // Create FormData for file upload
      const formData = new FormData();
      formData.append('name', data.name);
      formData.append('is_global', String(data.is_global));
      
      if (!data.is_global && data.company) {
        formData.append('company', data.company);
      }
      
      if (data.file) {
        formData.append('image', data.file);
      } else {
        throw new Error("Image file is required");
      }
      
      const response = await apiFetch(`${config.apiUrl}/reusable-images/upload`, {
        method: "POST",
        body: formData,
      });
      
      if (!response.ok) {
        const error = await response.json();
        throw new Error(error.message || error.error || "Failed to upload image");
      }
      
      return response.json();
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["reusable-images"] });
      toast.success("Image uploaded successfully");
      resetForm();
    },
    onError: (error) => {
      toast.error(error instanceof Error ? error.message : "Failed to upload image");
    },
  });

  const updateMutation = useMutation({
    mutationFn: async (data: ImageFormData) => {
      if (!data.id) throw new Error("Image ID is required for update");
      
      const response = await apiFetch(`${config.apiUrl}/reusable-images/${data.id}`, {
        method: "PUT",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          name: data.name,
          is_global: data.is_global,
          company: data.is_global ? null : data.company
        }),
      });
      
      if (!response.ok) {
        const error = await response.json();
        throw new Error(error.message || error.error || "Failed to update image");
      }
      
      return response.json();
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["reusable-images"] });
      toast.success("Image updated successfully");
      resetForm();
    },
    onError: (error) => {
      toast.error(error instanceof Error ? error.message : "Failed to update image");
    },
  });

  const deleteMutation = useMutation({
    mutationFn: async (id: number) => {
      const response = await apiFetch(`${config.apiUrl}/reusable-images/${id}`, {
        method: "DELETE",
      });
      if (!response.ok) {
        throw new Error("Failed to delete image");
      }
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["reusable-images"] });
      toast.success("Image deleted successfully");
    },
    onError: (error) => {
      toast.error(error instanceof Error ? error.message : "Failed to delete image");
    },
  });

  const handleEdit = (image: ReusableImage) => {
    setEditingImage(image);
    setFormData({
      id: image.id,
      name: image.name,
      is_global: image.is_global,
      company: image.company,
    });
    setIsFormOpen(true);
  };

  const handleDeleteClick = (image: ReusableImage) => {
    setImageToDelete(image);
    setIsDeleteOpen(true);
  };

  const handlePreview = (image: ReusableImage) => {
    setPreviewImage(image);
    setIsPreviewOpen(true);
  };

  const handleDeleteConfirm = () => {
    if (imageToDelete) {
      deleteMutation.mutate(imageToDelete.id);
      setIsDeleteOpen(false);
      setImageToDelete(null);
    }
  };

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    
    // If is_global is true, ensure company is null
    const submitData = {
      ...formData,
      company: formData.is_global ? null : formData.company,
    };
    
    if (editingImage) {
      updateMutation.mutate(submitData);
    } else {
      if (!submitData.file) {
        toast.error("Please select an image file");
        return;
      }
      createMutation.mutate(submitData);
    }
  };

  const resetForm = () => {
    setFormData({
      name: "",
      is_global: false,
      company: null,
      file: undefined
    });
    setEditingImage(null);
    setIsFormOpen(false);
  };

  const handleCreateClick = () => {
    resetForm();
    setIsFormOpen(true);
  };

  // Configure dropzone for image uploads
  const onDrop = useCallback((acceptedFiles: File[]) => {
    if (acceptedFiles.length > 0) {
      const file = acceptedFiles[0]; // Take only the first file
      setFormData(prev => ({
        ...prev,
        file
      }));
    }
  }, []);

  const { getRootProps, getInputProps, isDragActive } = useDropzone({
    accept: {
      'image/*': ['.jpeg', '.jpg', '.png', '.gif', '.webp']
    },
    onDrop,
    multiple: false // Only accept single files
  });

  const columns = useMemo<ColumnDef<ReusableImage>[]>(() => [
    {
      accessorKey: "name",
      header: ({ column }) => (
        <Button
          variant="ghost"
          onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
        >
          Name
          <ArrowUpDown className="ml-2 h-4 w-4" />
        </Button>
      ),
    },
    {
      accessorKey: "is_global",
      header: ({ column }) => (
        <Button
          variant="ghost"
          onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
        >
          Type
          <ArrowUpDown className="ml-2 h-4 w-4" />
        </Button>
      ),
      cell: ({ row }) => {
        const isGlobal = row.getValue("is_global") as boolean;
        return isGlobal ? "Global" : "Company Specific";
      },
    },
    {
      accessorKey: "company",
      header: ({ column }) => (
        <Button
          variant="ghost"
          onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
        >
          Company
          <ArrowUpDown className="ml-2 h-4 w-4" />
        </Button>
      ),
      cell: ({ row }) => {
        const isGlobal = row.getValue("is_global") as boolean;
        if (isGlobal) return 'N/A';
        
        const companyId = row.getValue("company");
        if (!companyId) return 'None';
        return fieldOptions?.companies.find(c => c.value === companyId)?.label || companyId;
      },
    },
    {
      accessorKey: "file_size",
      header: ({ column }) => (
        <Button
          variant="ghost"
          onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
        >
          Size
          <ArrowUpDown className="ml-2 h-4 w-4" />
        </Button>
      ),
      cell: ({ row }) => {
        const size = row.getValue("file_size") as number;
        return `${(size / 1024).toFixed(1)} KB`;
      },
    },
    {
      accessorKey: "created_at",
      header: ({ column }) => (
        <Button
          variant="ghost"
          onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
        >
          Created
          <ArrowUpDown className="ml-2 h-4 w-4" />
        </Button>
      ),
      cell: ({ row }) => new Date(row.getValue("created_at")).toLocaleDateString(),
    },
    {
      accessorKey: "image_url",
      header: "Thumbnail",
      cell: ({ row }) => (
        <div className="flex items-center justify-center">
          <AuthedImage
            src={row.getValue("image_url") as string}
            alt={row.getValue("name") as string}
            className="w-10 h-10 object-contain border rounded"
          />
        </div>
      ),
    },
    {
      id: "actions",
      cell: ({ row }) => (
        <div className="flex gap-2 justify-end">
          <Button
            variant="ghost"
            size="icon"
            onClick={() => handlePreview(row.original)}
            title="Preview Image"
          >
            <Eye className="h-4 w-4" />
          </Button>
          <Button
            variant="ghost"
            size="icon"
            onClick={() => handleEdit(row.original)}
            title="Edit Image"
          >
            <Pencil className="h-4 w-4" />
          </Button>
          <Button
            variant="ghost"
            size="icon"
            className="text-destructive hover:text-destructive"
            onClick={() => handleDeleteClick(row.original)}
            title="Delete Image"
          >
            <Trash2 className="h-4 w-4" />
          </Button>
        </div>
      ),
    },
  ], [fieldOptions]);

  const filteredData = useMemo(() => {
    if (!images) return [];
    return images.filter((image) => {
      const searchString = searchQuery.toLowerCase();
      return (
        image.name.toLowerCase().includes(searchString) ||
        (image.is_global ? "global" : "company").includes(searchString) ||
        (image.company && image.company.toLowerCase().includes(searchString))
      );
    });
  }, [images, searchQuery]);

  const table = useReactTable({
    data: filteredData,
    columns,
    state: {
      sorting,
    },
    onSortingChange: setSorting,
    getSortedRowModel: getSortedRowModel(),
    getCoreRowModel: getCoreRowModel(),
  });

  return (
    <div className="space-y-6">
      <div className="flex items-center justify-between">
        <h2 className="text-2xl font-bold">Reusable Images</h2>
        <Button onClick={handleCreateClick}>
          <PlusCircle className="mr-2 h-4 w-4" />
          Upload New Image
        </Button>
      </div>

      <div className="flex items-center gap-4">
        <Input
          placeholder="Search images..."
          value={searchQuery}
          onChange={(e) => setSearchQuery(e.target.value)}
          className="max-w-sm"
        />
      </div>

      {isLoading ? (
        <div>Loading images...</div>
      ) : (
        <div className="border rounded-lg">
          <Table>
            <TableHeader className="bg-muted">
              {table.getHeaderGroups().map((headerGroup) => (
                <TableRow key={headerGroup.id}>
                  {headerGroup.headers.map((header) => (
                    <TableHead key={header.id}>
                      {header.isPlaceholder
                        ? null
                        : flexRender(
                            header.column.columnDef.header,
                            header.getContext()
                          )}
                    </TableHead>
                  ))}
                </TableRow>
              ))}
            </TableHeader>
            <TableBody>
              {table.getRowModel().rows?.length ? (
                table.getRowModel().rows.map((row) => (
                  <TableRow key={row.id} className="hover:bg-gray-100">
                    {row.getVisibleCells().map((cell) => (
                      <TableCell key={cell.id} className="pl-6">
                        {flexRender(cell.column.columnDef.cell, cell.getContext())}
                      </TableCell>
                    ))}
                  </TableRow>
                ))
              ) : (
                <TableRow>
                  <TableCell colSpan={columns.length} className="text-center">
                    No images found
                  </TableCell>
                </TableRow>
              )}
            </TableBody>
          </Table>
        </div>
      )}

      {/* Image Form Dialog */}
      <Dialog open={isFormOpen} onOpenChange={setIsFormOpen}>
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>{editingImage ? "Edit Image" : "Upload New Image"}</DialogTitle>
            <DialogDescription>
              {editingImage 
                ? "Update this reusable image's details."
                : "Upload a new reusable image that can be used across products."}
            </DialogDescription>
          </DialogHeader>
          
          <ImageForm
            editingImage={editingImage}
            formData={formData}
            setFormData={setFormData}
            onSubmit={handleSubmit}
            onCancel={() => {
              resetForm();
              setIsFormOpen(false);
            }}
            fieldOptions={fieldOptions}
            getRootProps={getRootProps}
            getInputProps={getInputProps}
            isDragActive={isDragActive}
          />
        </DialogContent>
      </Dialog>

      {/* Delete Confirmation Dialog */}
      <AlertDialog open={isDeleteOpen} onOpenChange={setIsDeleteOpen}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Delete Image</AlertDialogTitle>
            <AlertDialogDescription>
              Are you sure you want to delete this image? This action cannot be undone.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel onClick={() => {
              setIsDeleteOpen(false);
              setImageToDelete(null);
            }}>
              Cancel
            </AlertDialogCancel>
            <AlertDialogAction onClick={handleDeleteConfirm}>
              Delete
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>

      {/* Preview Dialog */}
      <Dialog open={isPreviewOpen} onOpenChange={setIsPreviewOpen}>
        <DialogContent className="max-w-3xl">
          <DialogHeader>
            <DialogTitle>{previewImage?.name}</DialogTitle>
            <DialogDescription>
              {previewImage?.is_global 
                ? "Global image" 
                : `Company specific image for ${fieldOptions?.companies.find(c => c.value === previewImage?.company)?.label}`}
            </DialogDescription>
          </DialogHeader>
          
          <div className="flex justify-center p-4">
            {previewImage && (
              <div className="bg-checkerboard rounded-md overflow-hidden">
                <AuthedImage
                  src={previewImage.image_url}
                  alt={previewImage.name}
                  className="max-h-[500px] max-w-full object-contain"
                />
              </div>
            )}
          </div>
          
          <div className="grid grid-cols-2 gap-4 text-sm">
            <div>
              <span className="font-medium">Filename:</span> {previewImage?.filename}
            </div>
            <div>
              <span className="font-medium">Size:</span> {previewImage && `${(previewImage.file_size / 1024).toFixed(1)} KB`}
            </div>
            <div>
              <span className="font-medium">Type:</span> {previewImage?.mime_type}
            </div>
            <div>
              <span className="font-medium">Uploaded:</span> {previewImage && new Date(previewImage.created_at).toLocaleString()}
            </div>
          </div>
          
          <DialogFooter>
            <DialogClose asChild>
              <Button>Close</Button>
            </DialogClose>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* Add global styles for this component using regular style tag */}
      <style>{`
        .reusable-image-table thead tr th,
        .reusable-image-table tbody tr td {
          padding-left: 1rem;
          padding-right: 1rem;
        }
        .bg-checkerboard {
          background-image: linear-gradient(45deg, #f0f0f0 25%, transparent 25%),
                          linear-gradient(-45deg, #f0f0f0 25%, transparent 25%),
                          linear-gradient(45deg, transparent 75%, #f0f0f0 75%),
                          linear-gradient(-45deg, transparent 75%, #f0f0f0 75%);
          background-size: 20px 20px;
          background-position: 0 0, 0 10px, 10px -10px, -10px 0px;
        }
      `}</style>
    </div>
  );
}

const ImagePreview = ({ file }: { file: File }) => {
  const [previewUrl, setPreviewUrl] = useState<string>('');

  useEffect(() => {
    const url = URL.createObjectURL(file);
    setPreviewUrl(url);
    return () => {
      URL.revokeObjectURL(url);
    };
  }, [file]);

  return (
    <img 
      src={previewUrl}
      alt="Preview"
      className="max-h-32 max-w-full object-contain rounded-md"
    />
  );
}; 
