import React, { useEffect, useRef, useState } from 'react'
import type { InputNumberProps, TableProps } from 'antd'
import {
    Button,
    Form,
    Input,
    InputNumber,
    Popconfirm,
    Select,
    Space,
    Switch,
    Table,
    Tooltip,
} from 'antd'
import {
    type InvoiceBodyList,
    type EdittableStateInterface,
    type EdittableInterface,
} from '../../../Types/Invoice/Invoicing'
import { connect, useDispatch } from 'react-redux'
import { GetServiceDropDownList } from '../../../Services/Corporate'
import { DeleteOutlined, EditOutlined, PlusOutlined } from '@ant-design/icons'
// interface DataType {
//     key: string
//     service: string
//     discription: string
//     grossTotal: number
//     discountType: number
//     discountValue: number
//     tax: number
//     netAmount: number
//     taxStatus: number
// }

const originData = Array.from({ length: 1 }).map<InvoiceBodyList>((_, i) => ({
    key: i.toString(),
    invoiceDetailId: 0,
    invoiceId: 0,
    lineDescription: '',
    quantity: 0,
    unitPrice: 0,
    grossTotal: 0,
    discountType: 1,
    discountValue: 0,
    discount: 0,
    totalAfterDiscount: 0,
    serviceName: '',
    taxApplied: 0,
    tax: 0,
    netAmount: 0,
    description: '',
}))

interface EditableCellProps extends React.HTMLAttributes<HTMLElement> {
    editing: boolean
    dataIndex: string
    title: any
    inputType: 'number' | 'text' | 'select' | 'discount' | 'taxBox'
    record: InvoiceBodyList
    index: number
}

const EditTable = (props: EdittableInterface): React.ReactElement => {
    const {
        invoiceBodyList,
        serviceDropDownList,
        setTaxTotal,
        setSubTotal,
        setDiscount,
        setNetTotal,
        setTabledata,
    } = props
    const [form] = Form.useForm()
    const [data, setData] = useState<InvoiceBodyList[]>(originData)
    const [editingKey, setEditingKey] = useState('')
    const dispatch = useDispatch()
    const [servicevalue, setServicevalue] = useState('')
    const hasFetchedOnce = useRef(false)
    useEffect(() => {
        setTabledata(data)
    }, [invoiceBodyList, data])
    useEffect(() => {
        if (invoiceBodyList !== undefined && invoiceBodyList?.length > 0) {
            const dataa = invoiceBodyList?.map((item, index) => ({
                ...item,
                key: index.toString(),
            }))
            setData(dataa)
        } else {
            setData(originData)
        }
    }, [invoiceBodyList])
    useEffect(() => {
        if (!hasFetchedOnce.current) {
            hasFetchedOnce.current = true
            return
        }
        GetServiceDropDownList(dispatch)
    }, [])

    const onServicechange = (value: string): void => {
        setServicevalue(value)
    }
    useEffect(() => {
        form.setFieldValue('lineDescription', servicevalue)
    }, [servicevalue])

    const EditableCell: React.FC<
        React.PropsWithChildren<EditableCellProps>
    > = ({
        editing,
        dataIndex,
        title,
        inputType,
        record,
        index,
        children,
        ...restProps
    }) => {
        const [switchChecked, setSwitchChecked] = useState(record?.taxApplied)
        const [discoountTypeId, setDicountType] = useState(1)
        const [discountValue, setDiscountvalue] = useState(0)
        const calculateNetAmount = (): {
            tax: number
            netAmount: number
        } => {
            const row = form.getFieldsValue()
            const grossTotal = row?.grossTotal ?? 0
            const discountValue = row?.discountValue ?? 0
            let afterDiscountTotal = 0
            if (discoountTypeId === 1) {
                afterDiscountTotal = grossTotal - discountValue
            } else if (discoountTypeId === 2) {
                afterDiscountTotal =
                    grossTotal - (grossTotal * discountValue) / 100
            }
            let taxv = 0
            if (discountValue !== 0 && discountValue !== undefined) {
                taxv = afterDiscountTotal * 0.2
            } else {
                taxv = grossTotal * 0.2
            }
            const tax = row?.taxApplied === 1 ? taxv : 0

            let netAmount = 0

            if (row.taxApplied === 1) {
                if (afterDiscountTotal !== 0) {
                    netAmount = afterDiscountTotal + tax
                } else {
                    netAmount = grossTotal + tax
                }
            } else {
                if (afterDiscountTotal !== 0) {
                    netAmount = afterDiscountTotal
                } else {
                    netAmount = grossTotal
                }
            }
            return { tax, netAmount }
        }

        useEffect(() => {
            const obj = calculateNetAmount()
            form.setFieldsValue({
                tax: obj.tax ?? 0,
                netAmount: obj.netAmount ?? 0,
            })
        }, [
            form.getFieldValue('grossTotal'),
            form.getFieldValue('discountValue'),
            discoountTypeId,
            discountValue,
        ])

        const onChangeGrossTotal: InputNumberProps['onChange'] = (value) => {
            form.setFieldsValue({ netAmount: value ?? 0 })
        }

        const onChangeDicountvalue: InputNumberProps['onChange'] = (value) => {
            form.setFieldsValue({ discountValue: value })
            if (value !== null) {
                setDiscountvalue(Number(value))
            }
        }

        const handleDiscountTypeChange = (value: number): void => {
            setDicountType(value)
        }

        const handleSwitchChange = (checked: boolean): void => {
            setSwitchChecked(checked ? 1 : 0)
            form.setFieldValue('taxApplied', checked ? 1 : 0)
            const obj = calculateNetAmount()
            form.setFieldsValue({
                tax: obj.tax ?? 0,
                netAmount: obj.netAmount ?? 0,
            })
        }
        const inputNode =
            inputType === 'number' ? (
                dataIndex === 'grossTotal' ? (
                    <Form.Item name={'grossTotal'} style={{ margin: 0 }}>
                        <InputNumber onChange={onChangeGrossTotal} />
                    </Form.Item>
                ) : (
                    <InputNumber disabled={dataIndex === 'netAmount'} />
                )
            ) : inputType === 'select' ? (
                <Select
                    allowClear
                    placeholder="Please select"
                    onChange={(value) => {
                        onServicechange(value)
                    }}
                    options={serviceDropDownList?.map(
                        (data: { label: string }) => {
                            return {
                                value: data.label,
                                label: data.label,
                            }
                        }
                    )}
                />
            ) : inputType === 'discount' ? (
                <Space>
                    <Form.Item name={'discountType'} style={{ margin: 0 }}>
                        <Select
                            style={{ width: 60 }}
                            onChange={handleDiscountTypeChange}
                            value={discoountTypeId}
                        >
                            <Select.Option value={1}>£</Select.Option>
                            <Select.Option value={2}>%</Select.Option>
                        </Select>
                    </Form.Item>
                    <Form.Item name={'discountValue'} style={{ margin: 0 }}>
                        <InputNumber
                            min={0}
                            onChange={onChangeDicountvalue}
                            defaultValue={0}
                        />
                    </Form.Item>
                </Space>
            ) : inputType === 'taxBox' ? (
                <Space>
                    <Form.Item name={'taxApplied'} style={{ margin: 0 }}>
                        <Switch
                            checked={switchChecked === 1}
                            onChange={handleSwitchChange}
                        />
                    </Form.Item>
                    <Form.Item name={'tax'} style={{ margin: 0 }}>
                        <InputNumber min={0} disabled />
                    </Form.Item>
                </Space>
            ) : (
                <Input />
            )

        return (
            <td {...restProps}>
                {editing ? (
                    <Form.Item name={dataIndex} style={{ margin: 0 }}>
                        {inputNode}
                    </Form.Item>
                ) : (
                    children
                )}
            </td>
        )
    }

    const isEditing = (record: InvoiceBodyList): boolean =>
        record.key === editingKey

    const edit = (
        record: Partial<InvoiceBodyList> & { key: React.Key }
    ): void => {
        form.setFieldsValue({
            ...record,
            invoiceDetailId: record.invoiceDetailId ?? 0,
            invoiceId: record.invoiceId ?? 0,
            lineDescription: record.lineDescription ?? '',
            quantity: record.quantity ?? 0,
            unitPrice: record.unitPrice ?? 0,
            grossTotal: record.grossTotal ?? 0,
            discountType: record.discountType ?? 1,
            discountValue: record.discountValue ?? 0,
            discount: record.discount ?? 0,
            totalAfterDiscount: record.totalAfterDiscount ?? 0,
            serviceName: record.serviceName ?? '',
            taxApplied: record.taxApplied ?? 0,
            tax: record.tax ?? 0,
            netAmount: record.netAmount ?? 0,
            description: record.description ?? '',
        })
        setEditingKey(record.key)
    }

    // const cancel = (): void => {
    //     setEditingKey('')
    // }

    const save = async (key: React.Key): Promise<void> => {
        try {
            const row = (await form.validateFields()) as InvoiceBodyList
            const newData = [...data]
            const index = newData.findIndex((item) => key === item.key)
            if (index > -1) {
                const item = newData[index]
                newData.splice(index, 1, {
                    ...item,
                    ...row,
                    invoiceDetailId: row.invoiceDetailId ?? 0,
                    invoiceId: row.invoiceId ?? 0,
                    lineDescription: row.lineDescription ?? '',
                    quantity: row.quantity ?? 0,
                    unitPrice: row.unitPrice ?? 0,
                    grossTotal: isNaN(row.grossTotal)
                        ? 0
                        : (Number(row.grossTotal) ?? 0),
                    discountType: row.discountType ?? 1,
                    discountValue: row.discountValue ?? 0,
                    discount: row.discount ?? 0,
                    totalAfterDiscount: row.totalAfterDiscount ?? 0,
                    serviceName: row.serviceName ?? '',
                    taxApplied: row.taxApplied ?? 0,
                    tax: row.tax ?? 0,
                    netAmount: row.netAmount ?? 0,
                    description: row.description ?? '',
                })
                setData(newData)
                setEditingKey('')
                form.resetFields()
            } else {
                newData.push(row)
                setData(newData)
                setEditingKey('')
                form.resetFields()
            }
            const grossTotal = newData?.reduce((acc, row) => {
                if (row?.grossTotal !== undefined) {
                    acc += Number(row?.grossTotal)
                }
                return acc
            }, 0)

            const dis = newData?.reduce((acc, row) => {
                if (row?.discountValue !== undefined) {
                    acc += row?.discountValue
                }
                return acc
            }, 0)

            const net = newData?.reduce((acc, row) => {
                if (row?.netAmount !== undefined) {
                    acc += row?.netAmount
                }
                return acc
            }, 0)

            const taxs = newData?.reduce((acc, row) => {
                if (row?.tax !== undefined) {
                    acc += row?.tax
                }
                return acc
            }, 0)

            setTaxTotal(taxs ?? 0)
            setSubTotal(grossTotal ?? 0)
            setDiscount(dis ?? 0)
            setNetTotal(net ?? 0)
        } catch (errInfo) {
            console.log('Validate Failed:', errInfo)
        }
    }
    const handleDelete = (key: React.Key): void => {
        const newData = data.filter((item) => item.key !== key)
        setData(newData)
    }
    const [count, setCount] = useState(data?.length)
    const columns = [
        {
            title: 'Service',
            dataIndex: 'serviceName',
            width: '25%',
            editable: true,
        },
        {
            title: 'Description',
            dataIndex: 'lineDescription',
            width: '25%',
            editable: true,
        },
        {
            title: 'Total',
            dataIndex: 'grossTotal',
            width: '10%',
            editable: true,
        },
        {
            title: 'Discount',
            dataIndex: 'discount',
            width: '10%',
            editable: true,
            inputType: 'discount',
            render: (_: any, record: InvoiceBodyList) => {
                return (
                    <>
                        <div>
                            {record.discountValue}{' '}
                            {record.discountType === 1 ? '(£)' : '(%)'}
                        </div>
                    </>
                )
            },
        },
        {
            title: 'Tax',
            dataIndex: 'tax',
            width: '10%',
            editable: true,
            inputType: 'taxBox',
        },
        {
            title: 'NetTotal',
            dataIndex: 'netAmount',
            width: '10%',
            editable: true,
        },
        {
            dataIndex: 'operation',
            render: (_: any, record: InvoiceBodyList) => {
                const editable = isEditing(record)
                const handeladd = (): void => {
                    if (editable) {
                        void save(record.key)
                    } else {
                        handleAdd()
                        // setTaxTotal(taxvalue ?? 0)
                        // setSubTotal(grossTotal ?? 0)
                        // setDiscount(discountTotal ?? 0)
                        // setNetTotal(netTotal ?? 0)
                    }
                }
                return (
                    <>
                        <Space>
                            <Tooltip title="Edit Record">
                                <Button
                                    disabled={editingKey !== ''}
                                    onClick={() => {
                                        edit(record)
                                    }}
                                    icon={<EditOutlined />}
                                />
                            </Tooltip>

                            <Tooltip title="Delete Record">
                                <Popconfirm
                                    title="Sure to delete?"
                                    onConfirm={() => {
                                        handleDelete(record.key)
                                    }}
                                >
                                    <Button
                                        disabled={data?.length === 1}
                                        type="primary"
                                        danger
                                        icon={<DeleteOutlined />}
                                    />
                                </Popconfirm>
                            </Tooltip>
                            <Tooltip title="Add Item">
                                <Button
                                    type="primary"
                                    onClick={() => {
                                        handeladd()
                                    }}
                                    icon={<PlusOutlined />}
                                />
                            </Tooltip>
                        </Space>
                    </>
                )
            },
        },
    ]

    const handleAdd = (): void => {
        form.resetFields()
        const newData: InvoiceBodyList = {
            key: count.toString(),
            invoiceDetailId: 0,
            invoiceId: 0,
            lineDescription: '',
            quantity: 0,
            unitPrice: 0,
            grossTotal: 0,
            discountType: 1,
            discountValue: 0,
            discount: 0,
            totalAfterDiscount: 0,
            serviceName: '',
            taxApplied: 0,
            tax: 0,
            netAmount: 0,
            description: '',
        }
        setData([...data, newData])
        setCount(count + 1)
        setEditingKey(count.toString())
    }
    const mergedColumns: TableProps<InvoiceBodyList>['columns'] = columns.map(
        (col) => {
            if (!(col.editable ?? false)) {
                return col
            }
            return {
                ...col,
                onCell: (record: InvoiceBodyList) => ({
                    record,
                    inputType:
                        col.dataIndex === 'serviceName'
                            ? 'select'
                            : col.dataIndex === 'lineDescription'
                              ? 'text'
                              : col.dataIndex === 'discount'
                                ? 'discount'
                                : col.dataIndex === 'tax'
                                  ? 'taxBox'
                                  : 'number',
                    dataIndex: col.dataIndex,
                    title: col.title,
                    editing: isEditing(record),
                }),
            }
        }
    )

    return (
        <>
            <Form form={form} component={false}>
                <Table<InvoiceBodyList>
                    components={{
                        body: { cell: EditableCell },
                    }}
                    bordered
                    dataSource={data}
                    columns={mergedColumns}
                    rowClassName="editable-row"
                    pagination={false}
                />
            </Form>
        </>
    )
}

const mapStateToProps = (state: any): EdittableStateInterface => {
    return {
        serviceDropDownList: state.initial.serviceDropDownList,
    }
}

export default connect(mapStateToProps)(EditTable)
