"use client"
import { Button } from "@/components/ui/button"
import {
  ContextMenu,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuTrigger,
} from "@/components/ui/context-menu"
import {
  DropdownMenu,
  DropdownMenuCheckboxItem,
  DropdownMenuContent,
  DropdownMenuTrigger,
  DropdownMenuRadioItem,
  DropdownMenuRadioGroup
} from "@/components/ui/dropdown-menu"
import { Input } from "@/components/ui/input"
import { Component, ComponentProps, use, useState } from "react"
import {
  ColumnDef,
  flexRender,
  SortingState,
  getSortedRowModel,
  ColumnFiltersState,
  VisibilityState,
  getFilteredRowModel,
  getCoreRowModel,
  getPaginationRowModel,
  useReactTable,
  Row
} from "@tanstack/react-table"

import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"
import { CircleHelp, EyeIcon, Trash2 } from "lucide-react"
import { usePathname, useSearchParams } from "next/navigation"
import FormContextMenu from "./contextMenu"
import { deleteRecord, deleteRecords } from "app/lib/del"
import { Pathname } from "app/types"
import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTrigger } from "@/components/ui/dialog"
import pluralize from "app/lib/pluralize"
import { updateField, updatePub, updateStory } from "app/lib/update"
import { tableNameToItemName } from "app/lib/nameMaps"
import { Genre, Pub, Response, Story } from "@prisma/client"
import EditSubmissionDialog from "app/submission/edit"
import { DialogTitle } from "@radix-ui/react-dialog"
import { toast } from "@/components/ui/use-toast"
import { useRouter } from "next/navigation"
import EditStoryDialog from "app/story/edit"
import EditPubDialog from "app/publication/edit"

export interface DataTableProps<TData, TValue> {
  columns: ColumnDef<TData, TValue>[]
  data: TData[]
}


export function DataTable<TData, TValue>({
  columns,
  data,
  children,
  tableName,
  stories,
  pubs,
  responses,
  genres
}: DataTableProps<TData, TValue> & ComponentProps<"div"> & { tableName: string, stories?: Story[], pubs?: Pub[], responses?: Response[], genres?: Genre[] }) {
  //STATE
  const [isEditDialogVisible, setIsEditDialogVisible] = useState<boolean>(false)
  const [isDeleteDialogVisible, setIsDeleteDialogVisible] = useState<boolean>(false)
  const [dialogRow, SetDialogRow] = useState<Row<any> | null>(null)
  const [sorting, setSorting] = useState<SortingState>([])
  const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>(
    []
  )
  const [columnVisibility, setColumnVisibility] =
    useState<VisibilityState>({})
  //
  const pathname: string = usePathname()
  const table = useReactTable({
    data,
    columns,
    enableRowSelection: true,
    enableMultiRowSelection: true,
    getCoreRowModel: getCoreRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
    onSortingChange: setSorting,
    getSortedRowModel: getSortedRowModel(),
    onColumnFiltersChange: setColumnFilters,
    getFilteredRowModel: getFilteredRowModel(),
    onColumnVisibilityChange: setColumnVisibility,
    state: {
      sorting,
      columnFilters,
      columnVisibility,
    },
    //this is where you put arbitrary functions etc to make them accessible via the table api
    meta: {
      updateTextField: updateField,
      tableName,
      pathname,
      stories,
      pubs,
      responses,
      genres
    }
  })


  function openEditDialog(row) {
    setIsEditDialogVisible(true)
    SetDialogRow(row)
  }
  function openDeleteDialog(row) {
    setIsDeleteDialogVisible(true)
    SetDialogRow(row)
  }
  function closeEditDialog() {
    setIsEditDialogVisible(false)
  }



  const router = useRouter()

  const [filterBy, setFilterBy] = useState(table.getAllColumns()[0])
  const [isContextMenuOpen, setIsContextMenuOpen] = useState(false)
  return (<>
    <div className="flex gap-1 justify-between items-center py-1 md:py-4">
      <div className="flex gap-0.5">
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <Button variant="outline" className="mx-0"> <p className="hidden md:block">Filter by</p><CircleHelp className="block md:hidden" /> </Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="end">
            {/*@ts-ignore*/}
            <DropdownMenuRadioGroup value={filterBy} onValueChange={setFilterBy} >
              {table
                .getAllColumns()
                .filter((column) => column.getCanFilter())
                //@ts-ignore
                .map((column) => { return (<DropdownMenuRadioItem value={column} className="capitalize" key={column.id}> {column.id} </DropdownMenuRadioItem>) })}
            </DropdownMenuRadioGroup>
          </DropdownMenuContent>
        </DropdownMenu>
        <Input
          placeholder={`${filterBy.id}`}
          value={(table.getColumn(filterBy.id)?.getFilterValue() as string) ?? ""}
          onChange={(event) =>
            table.getColumn(filterBy.id)?.setFilterValue(event.target.value)
          }
          disabled={filterBy.id === "select"}
          className="max-w-sm"
        />
      </div>

      {children}

      <Dialog open={isEditDialogVisible} onOpenChange={setIsEditDialogVisible}>
        <DialogContent>
          {tableName === "sub" ?
            <EditSubmissionDialog
              stories={stories}
              pubs={pubs}
              responses={responses}
              defaults={dialogRow?.original}
              closeDialog={closeEditDialog}
            />
            : tableName === "story" ?
              < EditStoryDialog
                dbAction={updateStory}
                genres={genres}
                defaults={dialogRow?.original}
                closeDialog={closeEditDialog}
              />
              : tableName === "pub" ?
                <EditPubDialog
                  dbAction={updatePub}
                  genres={genres}
                  defaults={dialogRow?.original}
                  closeDialog={closeEditDialog}
                />
                : ""
          }
        </DialogContent>
      </Dialog>


      <Dialog open={isDeleteDialogVisible} onOpenChange={setIsDeleteDialogVisible}>
        <DialogContent>

          <DialogHeader>
            <DialogTitle>Are you sure?</DialogTitle>
            <DialogDescription>
              Deleting a {tableNameToItemName(tableName)} cannot be undone!
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <DialogClose asChild>
              <Button variant="destructive"
                onClick={async () => {
                  const res = await deleteRecord(dialogRow.original.id, pathname)
                  if (!res) toast({ title: "Oh dear...", description: "Failed to delete." })
                  if (res) toast({ title: "Successfully deleted record of id:", description: dialogRow.original.id })
                  table.resetRowSelection()
                  router.refresh()
                }}>Yes, delete it!
              </Button>
            </DialogClose>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog>
        <DialogTrigger asChild>
          <Button variant="destructive" disabled={!(table.getIsSomeRowsSelected() || table.getIsAllRowsSelected())}>
            <Trash2 />
          </Button>
        </DialogTrigger>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Delete items?</DialogTitle>
            {`Delete ${Object.keys(table.getState().rowSelection).length} ${pluralize(pathname.slice(1))}?`}
          </DialogHeader>
          <DialogDescription>
            {/* @ts-ignore */}
            {`Deleting ${pluralize(tableNameToItemName(table.options.meta.tableName))} cannot be undone!`}
          </DialogDescription>
          <DialogFooter>
            <Button variant="destructive"
              onClick={async () => {
                const selectedRows = table.getState().rowSelection
                const rowIds = Object.keys(selectedRows)
                //@ts-ignore
                const recordIds = rowIds.map(id => Number(table.getRow(id).original.id))
                //@ts-ignore
                const res = await deleteRecords(recordIds, pathname)
                if (!res) toast({ title: "Oh dear...", description: "Failed to delete." })
                if (res) toast({ title: "Successfully deleted records of id:", description: JSON.stringify(recordIds) })
                table.resetRowSelection()
                setIsDeleteDialogVisible(false)
                router.refresh()
              }}>
              Yes, delete them!</Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>



      <DropdownMenu>
        <DropdownMenuTrigger asChild>
          <Button variant="outline" className="justify-self-end">
            <EyeIcon />
          </Button>
        </DropdownMenuTrigger>
        <DropdownMenuContent align="end">
          {table
            .getAllColumns()
            .filter(
              (column) => column.getCanHide()
            )
            .map((column) => {
              return (
                <DropdownMenuCheckboxItem
                  key={column.id}
                  className="capitalize"
                  checked={column.getIsVisible()}
                  onCheckedChange={(value) =>
                    column.toggleVisibility(!!value)
                  }
                >
                  {column.id}
                </DropdownMenuCheckboxItem>
              )
            })}
        </DropdownMenuContent>
      </DropdownMenu>
    </div>
    <div className="rounded-md">


      <Table>
        <TableHeader>
          {table.getHeaderGroups().map((headerGroup) => (
            <TableRow key={headerGroup.id}>
              {headerGroup.headers.map((header) => {
                return (
                  <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) => {
              const classes = () => {
                const classes = []
                if (row.getValue('response') === "Pending") classes.push("bg-accent")
                if (row.getValue('response') === "Acceptance") classes.push("bg-primary")
                return classes.join(" ")
              }
              return (
                <ContextMenu key={row.id + "contextMenu"}>
                  <ContextMenuTrigger asChild>
                    <TableRow
                      key={row.id}
                      className={classes()}
                      data-state={row.getIsSelected() && "selected"}
                      tabIndex={0}
                      onDoubleClick={() => {
                        if (tableName === "sub") {
                          openEditDialog(row)
                        }
                      }
                      }
                    >
                      {row.getVisibleCells().map((cell) => (
                        <TableCell key={cell.id}>
                          {flexRender(cell.column.columnDef.cell, cell.getContext())}
                        </TableCell>
                      ))}
                      <FormContextMenu
                        key={"formContextMenu" + row.id}
                        row={row}
                        table={table}
                        openEditDialog={openEditDialog}
                        openDeleteDialog={openDeleteDialog}
                      />
                    </TableRow>
                  </ContextMenuTrigger>
                </ContextMenu>
              )
            })
          ) : (
            <TableRow>
              <TableCell colSpan={columns.length} className="h-24 text-center">
                No results.
              </TableCell>
            </TableRow>
          )}
        </TableBody>
      </Table>
      <div className="flex items-center justify-end space-x-2 py-4">
        <Button
          variant="outline"
          size="sm"
          onClick={() => table.previousPage()}
          disabled={!table.getCanPreviousPage()}
        >
          Previous
        </Button>
        <Button
          variant="outline"
          size="sm"
          onClick={() => table.nextPage()}
          disabled={!table.getCanNextPage()}
        >
          Next
        </Button>
      </div>
    </div>
  </>
  )
}

