import { Form, Input, Popconfirm, Typography, Table } from "antd"
import { useState } from "react";

const EditableCell = ({
  editing,
  record,
  dataIndex,
  input,
  isRequired,
  title,
  formItemClass,
  formItemRules,
  children,
}) => {

  const inputNode = input ?? <Input/>
  const rules = formItemRules ?? [{
      required: isRequired,
      message: `Please Input ${title}!`,
    }]

  const editor = <Form.Item
    name={dataIndex}
    style={{margin:0}}
    className={formItemClass}
    rules={rules}>
    {inputNode}
  </Form.Item>

  return (<td>
      {editing ? editor: children}
    </td>)
}

export const EditableTable = ({columns, dataSource, onUpdateData: onChange, ...otherTableProps}) => {
  const [form] = Form.useForm()
  const [editingKey, setEditingKey] = useState('')

  const isEditing = (record) => record.key === editingKey

  const edit = (record) => {
    form.setFieldsValue({...record})
    setEditingKey(record.key)
  }

  const cancel = () => {
    setEditingKey('')
  }

  const save = async (key) => {
    try {
      const row = await form.validateFields()
      const newData = [...dataSource]
      const index = newData.findIndex((item) => key === item.key)

      if (index > -1) {
        const item = newData[index]
        newData.splice(index, 1, { ...item, ...row })
      } else {
        newData.push(row)
      }

      setEditingKey('')
      if(onChange)
        onChange(newData)
      else
        console.error(`EditableTable.onChange doesn't connected`)      
    } catch (errInfo) {
      console.log('Validate Failed:', errInfo)
    }
  }

  const operationColumn = {
    title: '',
    dataIndex: 'operation',
    render: (_, record) => {
      const editable = isEditing(record)
      return editable ? (
        <span>
          <a
            href="javascript:"
            onClick={() => save(record.key)}
            style={{
              marginRight: 8,
            }}
          >
            Save
          </a>
          <Popconfirm title="Sure to cancel?" onConfirm={cancel}>
            <a>Cancel</a>
          </Popconfirm>
        </span>
      ) : (
        <Typography.Link disabled={editingKey !== ''} onClick={() => edit(record)}>
          Edit
        </Typography.Link>
      )
    },
  }

  const handleColumn = (col) => {
    if (col.children)
      col.children = col.children.map(handleColumn)

    if (!col.editable) 
      return col    

    return {
      ...col,
      onCell: (record) => ({
        editing: isEditing(record),        
        record,        
        dataIndex: col.dataIndex ?? col.key,
        input: col.input,
        isRequired: col.isRequired,
        title: col.title,
        dataType: col.dataType,
        formItemClass: col.formItemClass,
        formItemRules: col.formItemRules,
      }),
    }
  }

  const mergedColumns = [...columns.map(handleColumn), operationColumn]

  return (
    <Form form={form} component={false}>
      <Table
        components={{
          body: {
            cell: EditableCell,
          },
        }}
        columns={mergedColumns}
        dataSource={dataSource}
        {...otherTableProps}
      />
    </Form>
  )
}