import {useMutation, useQuery} from "@apollo/client";
import {AddIcon} from "@chakra-ui/icons";
import {Stack} from "@chakra-ui/layout";
import {
    Badge,
    Button,
    Checkbox,
    HStack,
    IconButton,
    Image,
    Select,
    Table,
    Tag,
    Tbody,
    Td,
    Text,
    Th,
    Thead,
    Tr,
    useToast
} from "@chakra-ui/react";
import {capitalCase, snakeCase} from "change-case";
import React, {useEffect, useState} from "react";
import {deleteIcon, editIcon} from '../../images';
import {Col, TableType} from "../intefaces/interfaces";
import {deleteRecordByPrimaryKey, getSearchQuery} from "../utils/GenericQueries";
import ConfirmDialog from "./ConfirmDialog";
import CustomEditModal from "./CustomEditModal";
import {getSinglePrimaryKey} from "./CustomeTableUtils";
import FilterInput from "./FilterInput";
import MultipleDisplay from "./MultipleDisplay";
import ForeignKeyDisplay from "./ForeignKeyDisplay";

function DelightTable(props: TableType) {
    const toast = useToast()

    const {
        primaryColor,
        secondaryColor,
        isModal,
        title,
        tablename,
        colorRow,
        bgRow,
        fontFamily,
        fontSizeRow,
        fontSizeHeader,
        fontWeightRow = "400",
        showAllBorders = false,
        showRoundedTitle = true,
        showControls = true,
        showSearch = false,
        showPagination = false,
        showBackground = true,
        selectableRows = false,
        col,
        panels,
        addEditDisplayType,
        recordsDisplayType,
        searchByCol,
    } = props;

    const searchQuery = getSearchQuery(tablename, col)
    const {loading, error, data, refetch} = useQuery(searchQuery);
    const [displayRecords, setDisplayRecords] = useState([]);

    const [formdata, setFormData] = useState(null)

    //delete
    const [itemToBeDeleted, setItemToBeDeleted] = useState(null)
    const [isDialogOpen, setDialogOpen] = useState(false);

    //delete row
    const [deleteRow] = useMutation(deleteRecordByPrimaryKey(tablename, col))

    //modal
    const [isAddEdit, setIsAddEdit] = useState(false);

    const [isUpdate, setIsUpdate] = useState(false);

    const [selectedRows, setSelectedRows]: any[] = useState([]);

    useEffect(() => {
        if (data) {
            setDisplayRecords(data[tablename])
        }
    }, [data])

    function handleActionSelected(e: any) {
        const {value} = e.target
        if (value === 'delete') {
            deleteMultipleItems(selectedRows)
        }
    }

    function getDisplayStyle(mycol: Col, columnValue: string) {
        if (mycol.displayProperties) {
            let conditionalStyle = mycol.displayProperties.conditions.find(c => c.value == columnValue);
            if (conditionalStyle) {
                return conditionalStyle.styles;
            }
            //default chips style
            // return mycol.displayProperties.styles
        }
    }

    function displayType(mycol: Col) {
        return mycol?.displayProperties?.displayType ?? "default"
    }

    const addRecord = () => {
        let item: any = {}
        for (let i = 0; i < col.length; i++) {
            item[snakeCase(col[i].name)] = ''
        }
        setFormData(item)
        setIsUpdate(false)
        setIsAddEdit(true)
    }

    const editRecord = (item: any) => {
        setFormData(item)
        setIsUpdate(true)
        setIsAddEdit(true)
    }

    const deleteRecord = (item: any) => {
        setItemToBeDeleted(item);
        setDialogOpen(true);

    }

    async function deleteMultipleItems(items: any) {
        toast({
            description: `Deleting ${selectedRows.length} rows...`,
            status: "info",
            duration: 5000,
            position: "bottom",
            isClosable: false
        })

        for (let i = 0; i < items.length; i++) {
            let item: any = items[i];
            let primaryKey = getSinglePrimaryKey(col)
            let deleteObj = {
                [primaryKey]: item[primaryKey]
            }
            await deleteRow({
                variables: deleteObj
            }).then(r => {
                refetch()
                console.log("Deleted ", item)
            }).catch(e => {
                console.log("error ", e)
            })
        }
        setSelectedRows([]);
    }

    function deleteCallBack(shouldItemBeDeleted: any) {
        setDialogOpen(false);
        if (itemToBeDeleted == null)
            return;

        if (shouldItemBeDeleted) {
            let primaryKey = getSinglePrimaryKey(col)
            let deleteObj = {
                [primaryKey]: itemToBeDeleted[primaryKey]
            }
            deleteRow({
                variables: deleteObj

            }).then(r => {
                refetch()
            }).catch(e => {
                console.log("error ", e)
                toast({
                    title: "Error",
                    description: e.message,
                    status: "error",
                    duration: 9000,
                    isClosable: true
                })
            })

        }
    }

    if (loading) {
        return <div>Loading...</div>
    }
    if (error) {
        console.log("error ", error)
        return <div>{error.message}</div>
    }

    if (data)
        return (
            <>
                {!isAddEdit ?
                    <Stack w="100%"
                           borderRadius="4px"
                           p="30px"
                           spacing={6}
                           bg={showBackground ? "white" : ""}>

                        <HStack
                            spacing={6} minW="100%"
                            alignItems="center"
                            justifyContent="space-between">
                            <HStack alignItems={"center"} spacing="20px">
                                {title &&
                                <Text
                                    border={showRoundedTitle ? `1px solid ${primaryColor}` : ''}
                                    padding="10px"
                                    borderRadius="10px"
                                    bg={showRoundedTitle ? primaryColor : ""}
                                    color={showRoundedTitle ? secondaryColor : primaryColor}
                                    fontFamily={fontFamily ?? "Inter"}
                                    fontSize="16px"
                                    fontWeight="700"
                                    minW="fit-content">
                                    {title}
                                </Text>
                                }

                                {showSearch &&
                                <FilterInput
                                    records={data[tablename]}
                                    filterCols={searchByCol}
                                    value={""}
                                    placeholder={"Search"}
                                    onChange={(filteredRecords: any) => {
                                        setDisplayRecords(filteredRecords);
                                    }}
                                />
                                }

                            </HStack>
                            {showControls &&
                            <Button
                                leftIcon={<AddIcon height="8.8" width="8.8"/>}
                                bg={primaryColor}
                                color={secondaryColor}
                                variant="solid"
                                _hover={{bg: "blue.200"}}
                                onClick={() => {
                                    addRecord();
                                }}
                            >
                                <Text
                                    fontFamily={fontFamily ?? "Inter"}
                                    fontSize="13px"
                                    fontStyle="normal"
                                    fontWeight="700"
                                    lineHeight="18px"
                                    letterSpacing="0em"
                                    textAlign="center"
                                >
                                    Add {title}
                                </Text>
                            </Button>
                            }
                        </HStack>

                        {selectedRows.length > 0 &&
                        <Select w="fit-content" placeholder="With Selected" onChange={handleActionSelected}>
                            <option value="delete">Delete</option>
                        </Select>
                        }
                        <Table w="100%">
                            <Thead bg={primaryColor ?? "white"}>
                                <Tr>
                                    {selectableRows &&
                                    <Th border={showAllBorders ? "1px solid #E9E9EB" : ""}
                                        fontFamily={fontFamily ?? "Inter"}
                                        fontSize={fontSizeHeader ?? "17px"}
                                        color={secondaryColor ?? "#000000"}
                                        fontStyle="normal"
                                        fontWeight="700"
                                        textTransform="capitalize">
                                        Select
                                    </Th>
                                    }
                                    {col.map((item: any) => {
                                        return <Th border={showAllBorders ? "1px solid #E9E9EB" : ""}
                                                   fontFamily={fontFamily ?? "Inter"}
                                                   fontSize={fontSizeHeader ?? "16px"}
                                                   color={secondaryColor ?? "#000000"}
                                                   fontStyle="normal"
                                                   fontWeight="700"
                                                   letterSpacing="0em"
                                                   textAlign="left"
                                                   textTransform="capitalize"
                                                   key={item.name}>
                                            {capitalCase(item.name)}

                                        </Th>
                                    })}
                                    <Th border={showAllBorders ? "1px solid #E9E9EB" : ""}
                                        fontFamily={fontFamily ?? "Inter"}
                                        fontSize={fontSizeHeader ?? "17px"}
                                        color={secondaryColor ?? "#000000"}
                                        fontStyle="normal"
                                        fontWeight="700"
                                        textTransform="capitalize"
                                        key={"actions"}>
                                        Actions
                                    </Th>
                                </Tr>
                            </Thead>
                            <Tbody bg={bgRow ?? "white"}>
                                {displayRecords.map((item: any) => (
                                    <Tr cursor={"pointer"}>
                                        {selectableRows &&
                                        <Td border={showAllBorders ? "1px solid #E9E9EB" : ""}
                                            fontFamily={fontFamily ?? "Inter"}
                                            fontSize={fontSizeHeader ?? "17px"}
                                            color={secondaryColor ?? "#000000"}
                                            fontStyle="normal"
                                            fontWeight="700"
                                            textTransform="capitalize">
                                            <Checkbox
                                                isChecked={selectedRows.includes(item)}
                                                onChange={(e: any) => {
                                                    if (e.target.checked) {
                                                        let mRows = [selectedRows]
                                                        mRows.push(item)
                                                        setSelectedRows(mRows);
                                                    } else {
                                                        setSelectedRows(selectedRows.filter((e: any) => e.id !== item.id))
                                                    }
                                                }}
                                            />
                                        </Td>
                                        }
                                        {col.map((mycol: Col) => {
                                            return displayType(mycol) === "chip" ?
                                                <Td border={showAllBorders ? "1px solid #E9E9EB" : ""}
                                                    fontFamily={fontFamily ?? "Inter"}
                                                    fontSize="12px">
                                                    <Tag p={2}
                                                         borderRadius="full"
                                                         style={getDisplayStyle(mycol, item[snakeCase(mycol.name)])}
                                                         colorScheme={mycol.displayProperties?.styles.backgroundColor}
                                                    >
                                                        {item[snakeCase(mycol.name)]}
                                                    </Tag>
                                                </Td>
                                                :
                                                displayType(mycol) === "badge" ?
                                                    <Td border={showAllBorders ? "1px solid #E9E9EB" : ""}
                                                        fontFamily={fontFamily ?? "Inter"}
                                                        fontSize="12px">
                                                        <Badge
                                                            colorScheme={mycol.displayProperties?.styles.backgroundColor}
                                                        >
                                                            {item[snakeCase(mycol.name)]}
                                                        </Badge>
                                                    </Td>
                                                    :
                                                    mycol.hasManyRelationship ?
                                                        <Td border={showAllBorders ? "1px solid #E9E9EB" : ""}
                                                            fontFamily={fontFamily ?? "Inter"}
                                                            fontSize="12px">
                                                            <MultipleDisplay
                                                                tableName={mycol.tableName}
                                                                cols={mycol.cols}
                                                                placeholder={mycol.placeholder}
                                                                returnColumn={mycol.returnColumn}
                                                                displayColumns={mycol.displayColumns}
                                                                defaultValues={item[snakeCase(mycol.name)]}
                                                            /></Td>
                                                        :
                                                        <Td border={showAllBorders ? "1px solid #E9E9EB" : ""}
                                                            fontFamily={fontFamily ?? "Inter"}
                                                            fontSize={fontSizeRow ?? "16px"}
                                                            color={colorRow ?? "black"}
                                                            fontWeight={fontWeightRow}>
                                                            {
                                                                mycol.type === "image" ?
                                                                    <Image maxH="50px" maxW="115px"
                                                                           alt="alt" src={item[snakeCase(mycol.name)]}/>
                                                                    :
                                                                    mycol.isForeignKey ?
                                                                        <ForeignKeyDisplay
                                                                            foreignId={item[snakeCase(mycol.name)]}
                                                                            tableName={mycol.tableName}
                                                                            cols={mycol.cols}
                                                                            displayColumns={mycol.displayColumns}
                                                                        />

                                                                        :
                                                                        item[snakeCase(mycol.name)]?.toString()
                                                            }
                                                        </Td>
                                        })}
                                        <Td border={showAllBorders ? "1px solid #E9E9EB" : ""}>
                                            <HStack>
                                                <IconButton p="0.5" aria-label="delete icon"
                                                            onClick={() => deleteRecord(item)}
                                                            bg="transparent" children={<Image src={deleteIcon}/>}/>
                                                <IconButton p="0.5" aria-label="edit icon"
                                                            onClick={() => editRecord(item)}
                                                            bg="transparent" children={<Image src={editIcon}/>}/>
                                            </HStack>
                                        </Td>
                                    </Tr>
                                ))}
                            </Tbody>
                        </Table>
                    </Stack>

                    :
                    <CustomEditModal
                        primaryColor={primaryColor}
                        secondaryColor={secondaryColor}
                        title={title}
                        open={isAddEdit}
                        tablename={tablename}
                        col={col}
                        noOfCols={0}
                        isUpdate={isUpdate}
                        formdata={formdata}
                        isModal={isModal}
                        panels={panels}
                        addEditDisplayType={addEditDisplayType}
                        recordsDisplayType={recordsDisplayType}
                        close={() => setIsAddEdit(false)}
                        refetch={() => {
                            setIsAddEdit(false)
                            refetch()
                        }}
                    />
                }

                <ConfirmDialog
                    isOpen={isDialogOpen}
                    callBack={deleteCallBack}
                    confirmText='Are you sure?'
                    cancelBtnText='Cancel'
                    headerText={`Delete ${title}`}
                    confirmBtnText='Confirm'
                />

            </>

        )
    return <div>No Data</div>
}

export default DelightTable;
