import {
  CheckOutlined,
  CloseOutlined,
  EditOutlined,
  QuestionCircleOutlined
} from '@ant-design/icons'
import {
  Button,
  Input,
  notification,
  Popconfirm,
  Select,
  Space,
  Tag
} from 'antd'
import { ColumnsType, TableProps } from 'antd/lib/table'
import dayjs from 'dayjs'
import { useMemo, useState } from 'react'

import {
  useDeleteApiV1DevopsBillingProxyApiV1BillingArTablesId,
  useGetApiV1DevopsBillingProxyApiV1BillingArTables,
  usePutApiV1DevopsBillingProxyApiV1BillingArTablesId
} from 'apiClient/services/billing'
import {
  FormsARTableRecordResponse,
  FormsARTableUpdateInput
} from 'apiClient/services/billing/interface'
import { DatePicker } from 'components/DatePicker'
import { getErrorMessage } from 'utils/error'

import ARTableDrawer from './ARTableDrawer'
import ARTableList from './ARTableList'
import {
  AR_TABLE_FIELDS,
  ARTableDisplayField,
  downloadARTableByFilters,
  formatARTableFieldLabel,
  formatARTableValue,
  getARTablePaymentType
} from './shared'

type ARTableFilter = {
  year: number
  month: number
  isEstimated: boolean
  tenantId: string
}

type EditableAmountField =
  | 'stripe_amount'
  | 'payment_type'
  | 'prepayment_credits'
  | 'invoice_amount'
  | 'starter_amount'
  | 'dedicated_amount'
  | 'essential_amount'
  | 'lake_amount'
  | 'support_amount'
  | 'premium_amount'
  | 'raw_starter_program_credits_amount'
  | 'raw_starter_redeem_credits_amount'
  | 'raw_starter_customer_success_amount'
  | 'raw_dedicated_program_credits_amount'
  | 'raw_dedicated_redeem_credits_amount'
  | 'raw_dedicated_customer_success_amount'
  | 'raw_lake_program_credits_amount'
  | 'raw_lake_redeem_credits_amount'
  | 'raw_lake_customer_success_amount'
  | 'raw_essential_program_credits_amount'
  | 'raw_essential_redeem_credits_amount'
  | 'raw_essential_customer_success_amount'
  | 'raw_support_program_credits_amount'
  | 'raw_support_redeem_credits_amount'
  | 'raw_support_customer_success_amount'
  | 'raw_premium_program_credits_amount'
  | 'raw_premium_redeem_credits_amount'
  | 'raw_premium_customer_success_amount'
  | 'cppo_discountable_product_amount'
  | 'cppo_non_discountable_product_amount'
  | 'stripe_amount_including_tax'

type EditableField =
  | EditableAmountField
  | 'stripe_invoice_paid'
  | 'stripe_invoice_paid_date'

type InlineEditState = {
  field: EditableField
  id: number
  value: string
}

const EDITABLE_FIELDS: EditableField[] = [
  'stripe_amount',
  'payment_type',
  'prepayment_credits',
  'invoice_amount',
  'starter_amount',
  'dedicated_amount',
  'essential_amount',
  'lake_amount',
  'support_amount',
  'premium_amount',
  'raw_starter_program_credits_amount',
  'raw_starter_redeem_credits_amount',
  'raw_starter_customer_success_amount',
  'raw_dedicated_program_credits_amount',
  'raw_dedicated_redeem_credits_amount',
  'raw_dedicated_customer_success_amount',
  'raw_lake_program_credits_amount',
  'raw_lake_redeem_credits_amount',
  'raw_lake_customer_success_amount',
  'raw_essential_program_credits_amount',
  'raw_essential_redeem_credits_amount',
  'raw_essential_customer_success_amount',
  'raw_support_program_credits_amount',
  'raw_support_redeem_credits_amount',
  'raw_support_customer_success_amount',
  'raw_premium_program_credits_amount',
  'raw_premium_redeem_credits_amount',
  'raw_premium_customer_success_amount',
  'cppo_discountable_product_amount',
  'cppo_non_discountable_product_amount',
  'stripe_amount_including_tax',
  'stripe_invoice_paid',
  'stripe_invoice_paid_date'
]

const PAYMENT_EXTRA_EDITABLE_FIELDS: EditableField[] = [
  'stripe_amount_including_tax',
  'stripe_invoice_paid',
  'stripe_invoice_paid_date'
]

const STRIPE_PAYMENT_EXTRA_FIELDS: Array<keyof FormsARTableRecordResponse> = [
  'stripe_tax_rate',
  'stripe_amount_including_tax',
  'stripe_invoice_number',
  'stripe_invoice',
  'stripe_invoice_paid',
  'stripe_invoice_finalized_date',
  'stripe_invoice_paid_date'
]

const DISPLAY_AMOUNT_UPDATE_FIELD_CONFIG = {
  starter_amount: {
    lossField: 'starter_allocated_loss',
    rawField: 'raw_starter_amount'
  },
  dedicated_amount: {
    lossField: 'dedicated_allocated_loss',
    rawField: 'raw_dedicated_amount'
  },
  essential_amount: {
    lossField: 'essential_allocated_loss',
    rawField: 'raw_essential_amount'
  },
  lake_amount: {
    lossField: 'lake_allocated_loss',
    rawField: 'raw_lake_amount'
  },
  support_amount: {
    lossField: 'support_allocated_loss',
    rawField: 'raw_support_amount'
  },
  premium_amount: {
    lossField: 'premium_allocated_loss',
    rawField: 'raw_premium_amount'
  }
} as const

const getEditableFieldsForRecord = (record?: FormsARTableRecordResponse) => {
  if (getARTablePaymentType(record) === 'stripe') {
    return EDITABLE_FIELDS
  }

  return EDITABLE_FIELDS.filter(
    (field) =>
      field !== 'stripe_invoice_paid' &&
      field !== 'stripe_invoice_paid_date' &&
      field !== 'stripe_amount_including_tax'
  )
}

const getPaymentAmountTargetField = (record: FormsARTableRecordResponse) => {
  const paymentType = getARTablePaymentType(record)

  if (paymentType === 'marketplace') {
    return 'marketplace_amount' as const
  }

  if (paymentType === 'wire_transfer') {
    return 'wire_transfer_amount' as const
  }

  return 'stripe_amount' as const
}

const getEditableFieldValue = (
  record: FormsARTableRecordResponse,
  field: EditableField
) => {
  if (field === 'stripe_amount') {
    const targetField = getPaymentAmountTargetField(record)

    if (targetField === 'wire_transfer_amount') {
      return record.wire_transfer_amount || ''
    }

    if (targetField === 'marketplace_amount') {
      return record.marketplace_amount || ''
    }

    return Array.isArray(record.stripe_amount)
      ? record.stripe_amount.join(', ')
      : ''
  }

  if (field === 'payment_type') {
    return record.payment_type || ''
  }

  const value = record[field]

  if (Array.isArray(value)) {
    return value.join(', ')
  }

  return value || ''
}

const normalizeStripeInvoicePaid = (value: string) => {
  return value
    .split(',')
    .map((item) => item.trim())
    .filter(Boolean)
}

const normalizeStringArrayField = (value: string) => {
  return value
    .split(',')
    .map((item) => item.trim())
    .filter(Boolean)
}

const parseNumericValue = (
  value?: FormsARTableRecordResponse[keyof FormsARTableRecordResponse]
) => {
  if (typeof value === 'number') {
    return value
  }

  if (typeof value === 'string') {
    const parsed = Number(value)
    return Number.isFinite(parsed) ? parsed : 0
  }

  if (Array.isArray(value)) {
    const parsed = Number(value[0])
    return Number.isFinite(parsed) ? parsed : 0
  }

  return 0
}

const addAllocatedLossBack = (
  displayValue: string,
  allocatedLoss?: FormsARTableRecordResponse[keyof FormsARTableRecordResponse]
) => {
  const numericDisplayValue = Number(displayValue)

  if (!Number.isFinite(numericDisplayValue)) {
    return displayValue
  }

  return (numericDisplayValue + parseNumericValue(allocatedLoss)).toFixed(2)
}

const buildUpdatePayload = (
  record: FormsARTableRecordResponse,
  updates: Partial<Record<EditableField, string>>
): FormsARTableUpdateInput | null => {
  const nextPaymentType = updates.payment_type ?? record.payment_type

  if (
    !record.bill_month ||
    record.binded_billing_config_id === undefined ||
    !nextPaymentType ||
    record.tenant_id === undefined
  ) {
    return null
  }

  const payload: FormsARTableUpdateInput = {
    bill_month: record.bill_month,
    binded_billing_config_id: record.binded_billing_config_id,
    payment_type: nextPaymentType,
    tenant_id: record.tenant_id
  }

  Object.entries(updates).forEach(([field, rawValue]) => {
    if (rawValue === undefined) {
      return
    }

    const value = rawValue as string

    switch (field as EditableField) {
      case 'stripe_amount':
        if (getPaymentAmountTargetField(record) === 'stripe_amount') {
          payload.stripe_amount = normalizeStringArrayField(value)
        } else if (
          getPaymentAmountTargetField(record) === 'wire_transfer_amount'
        ) {
          payload.wire_transfer_amount = value
        } else if (
          getPaymentAmountTargetField(record) === 'marketplace_amount'
        ) {
          payload.marketplace_amount = value
        }
        break
      case 'payment_type':
        break
      case 'invoice_amount':
        payload.invoice_amount = value
        break
      case 'starter_amount':
      case 'dedicated_amount':
      case 'essential_amount':
      case 'lake_amount':
      case 'support_amount':
      case 'premium_amount': {
        const amountField = field as
          | 'starter_amount'
          | 'dedicated_amount'
          | 'essential_amount'
          | 'lake_amount'
          | 'support_amount'
          | 'premium_amount'
        const config = DISPLAY_AMOUNT_UPDATE_FIELD_CONFIG[amountField]
        ;(payload as unknown as Record<string, unknown>)[config.rawField] =
          addAllocatedLossBack(
            value,
            record[config.lossField as keyof FormsARTableRecordResponse]
          )
        break
      }
      case 'stripe_amount_including_tax':
        payload.stripe_amount_including_tax = normalizeStringArrayField(value)
        break
      case 'stripe_invoice_paid':
        payload.stripe_invoice_paid = normalizeStripeInvoicePaid(value)
        break
      case 'stripe_invoice_paid_date':
        payload.stripe_invoice_paid_date = normalizeStringArrayField(value)
        break
      default:
        payload[field as keyof FormsARTableUpdateInput] = value as never
        break
    }
  })

  return payload
}

const renderARTableFieldValue = (
  field: ARTableDisplayField,
  value?: FormsARTableRecordResponse[keyof FormsARTableRecordResponse],
  record?: FormsARTableRecordResponse | null
) => {
  if (field === 'is_estimated') {
    return value ? <Tag color="gold">Estimated</Tag> : <Tag>Actual</Tag>
  }

  if (field === 'stripe_amount') {
    if (
      record &&
      getPaymentAmountTargetField(record) === 'wire_transfer_amount'
    ) {
      return formatARTableValue(record.wire_transfer_amount)
    }

    if (
      record &&
      getPaymentAmountTargetField(record) === 'marketplace_amount'
    ) {
      return formatARTableValue(record.marketplace_amount)
    }

    return formatARTableValue(value)
  }

  if (field === 'bill_month') {
    return (
      <Space direction="vertical" size={2}>
        <span>{formatARTableValue(value)}</span>
        <span style={{ color: '#8c8c8c', fontSize: 12 }}>
          {formatARTableValue(record?.start_date)}
        </span>
        <span style={{ color: '#8c8c8c', fontSize: 12 }}>
          {formatARTableValue(record?.end_date)}
        </span>
      </Space>
    )
  }

  if (field === 'stripe_invoice') {
    if (!Array.isArray(value) || !value.length) {
      return '-'
    }

    return (
      <Space direction="vertical" size={0}>
        {value.map((invoice) => (
          <a key={invoice} href={invoice} target="_blank" rel="noreferrer">
            {invoice}
          </a>
        ))}
      </Space>
    )
  }

  return formatARTableValue(value)
}

const PAGE_SIZE = 20

const getDefaultFilter = (): ARTableFilter => {
  const defaultMonth = dayjs().subtract(1, 'month')

  return {
    year: defaultMonth.year(),
    month: defaultMonth.month() + 1,
    isEstimated: false,
    tenantId: ''
  }
}

export const ARTable = () => {
  const defaultFilter = useMemo(() => getDefaultFilter(), [])
  const maxMonth = useMemo(
    () => dayjs().subtract(1, 'month').endOf('month'),
    []
  )
  const [draftFilter, setDraftFilter] = useState<ARTableFilter>(defaultFilter)
  const [queryFilter, setQueryFilter] = useState<ARTableFilter>(defaultFilter)
  const [isDownloadingList, setIsDownloadingList] = useState(false)
  const [inlineEditState, setInlineEditState] =
    useState<InlineEditState | null>(null)
  const [drawerRecord, setDrawerRecord] =
    useState<FormsARTableRecordResponse | null>(null)
  const [isDrawerEditing, setIsDrawerEditing] = useState(false)
  const [drawerEditValues, setDrawerEditValues] = useState<
    Partial<Record<EditableField, string>>
  >({})
  const [pageConfig, setPageConfig] = useState({
    page: 1,
    pageSize: PAGE_SIZE
  })

  const queryParams = useMemo(
    () => ({
      year: queryFilter.year,
      month: queryFilter.month,
      is_estimated: queryFilter.isEstimated,
      tenant_id: /^\d+$/.test(queryFilter.tenantId)
        ? Number(queryFilter.tenantId)
        : undefined,
      page: pageConfig.page,
      page_size: pageConfig.pageSize
    }),
    [pageConfig.page, pageConfig.pageSize, queryFilter]
  )

  const { data, isFetching, refetch } =
    useGetApiV1DevopsBillingProxyApiV1BillingArTables(queryParams, {
      query: {
        keepPreviousData: true,
        refetchOnWindowFocus: false,
        retry: false,
        onError: (error) => {
          notification.error({ message: getErrorMessage(error) })
        }
      }
    })
  const { mutateAsync: deleteRecord, isLoading: isDeleting } =
    useDeleteApiV1DevopsBillingProxyApiV1BillingArTablesId()
  const { mutateAsync: updateRecord, isLoading: isUpdating } =
    usePutApiV1DevopsBillingProxyApiV1BillingArTablesId()
  const isQueryLocked = isFetching

  const tableData = data?.data.records || []
  const total = data?.data.total_results || 0
  const currentDrawerIndex = useMemo(() => {
    if (!drawerRecord?.id) {
      return -1
    }

    return tableData.findIndex((record) => record.id === drawerRecord.id)
  }, [drawerRecord, tableData])

  const openDrawer = (record: FormsARTableRecordResponse) => {
    setDrawerRecord(record)
    setIsDrawerEditing(false)
    setDrawerEditValues(
      getEditableFieldsForRecord(record).reduce((result, field) => {
        result[field] = getEditableFieldValue(record, field)
        return result
      }, {} as Partial<Record<EditableField, string>>)
    )
  }

  const renderPaymentExtraInfo = (
    record: FormsARTableRecordResponse,
    options: {
      isDrawer?: boolean
    }
  ) => {
    if (getARTablePaymentType(record) !== 'stripe') {
      return '-'
    }

    const activePaymentExtraEditState =
      inlineEditState &&
      inlineEditState.id === record.id &&
      PAYMENT_EXTRA_EDITABLE_FIELDS.includes(inlineEditState.field)
        ? inlineEditState
        : null

    return (
      <Space direction="vertical" size={4}>
        <Space direction="vertical" size={2}>
          {STRIPE_PAYMENT_EXTRA_FIELDS.map((extraField) => (
            <div key={extraField}>
              <span style={{ fontWeight: 500 }}>
                {formatARTableFieldLabel(extraField)}:
              </span>{' '}
              {options.isDrawer &&
              isDrawerEditing &&
              PAYMENT_EXTRA_EDITABLE_FIELDS.includes(
                extraField as EditableField
              ) ? (
                extraField === 'stripe_invoice_paid' ? (
                  <Select
                    style={{ width: 120 }}
                    value={drawerEditValues.stripe_invoice_paid || undefined}
                    onChange={(nextValue) => {
                      setDrawerEditValues((prev) => ({
                        ...prev,
                        stripe_invoice_paid: nextValue
                      }))
                    }}
                  >
                    <Select.Option value="true">true</Select.Option>
                    <Select.Option value="false">false</Select.Option>
                  </Select>
                ) : extraField === 'stripe_invoice_paid_date' ? (
                  <DatePicker
                    showTime
                    style={{ width: 220 }}
                    value={
                      drawerEditValues.stripe_invoice_paid_date
                        ? dayjs(drawerEditValues.stripe_invoice_paid_date)
                        : undefined
                    }
                    onChange={(nextValue) => {
                      setDrawerEditValues((prev) => ({
                        ...prev,
                        stripe_invoice_paid_date: nextValue
                          ? nextValue.toISOString()
                          : ''
                      }))
                    }}
                  />
                ) : (
                  <Input
                    value={drawerEditValues[extraField as EditableField] || ''}
                    onChange={(event) => {
                      const editableField = extraField as EditableField
                      setDrawerEditValues((prev) => ({
                        ...prev,
                        [editableField]: event.target.value
                      }))
                    }}
                  />
                )
              ) : PAYMENT_EXTRA_EDITABLE_FIELDS.includes(
                  extraField as EditableField
                ) &&
                record.id &&
                !options.isDrawer ? (
                activePaymentExtraEditState?.field === extraField ? (
                  <Space size={4}>
                    {extraField === 'stripe_invoice_paid' ? (
                      <Select
                        size="small"
                        style={{ width: 76 }}
                        value={activePaymentExtraEditState.value || undefined}
                        onChange={(nextValue) => {
                          setInlineEditState((currentState) =>
                            currentState
                              ? {
                                  ...currentState,
                                  value: nextValue
                                }
                              : currentState
                          )
                        }}
                      >
                        <Select.Option value="true">true</Select.Option>
                        <Select.Option value="false">false</Select.Option>
                      </Select>
                    ) : extraField === 'stripe_invoice_paid_date' ? (
                      <DatePicker
                        showTime
                        size="small"
                        style={{ width: 180 }}
                        value={
                          activePaymentExtraEditState.value
                            ? dayjs(activePaymentExtraEditState.value)
                            : undefined
                        }
                        onChange={(nextValue) => {
                          setInlineEditState((currentState) =>
                            currentState
                              ? {
                                  ...currentState,
                                  value: nextValue
                                    ? nextValue.toISOString()
                                    : ''
                                }
                              : currentState
                          )
                        }}
                      />
                    ) : (
                      <Input
                        size="small"
                        style={{ width: 140 }}
                        value={activePaymentExtraEditState.value}
                        onChange={(event) => {
                          setInlineEditState((currentState) =>
                            currentState
                              ? {
                                  ...currentState,
                                  value: event.target.value
                                }
                              : currentState
                          )
                        }}
                      />
                    )}
                    <Button
                      type="link"
                      size="small"
                      style={{ padding: 0 }}
                      icon={<CheckOutlined />}
                      loading={isUpdating}
                      onClick={() =>
                        handleUpdate(record, {
                          [extraField]: activePaymentExtraEditState.value
                        })
                      }
                    />
                    <Button
                      type="link"
                      size="small"
                      style={{ padding: 0 }}
                      icon={<CloseOutlined />}
                      onClick={() => setInlineEditState(null)}
                    />
                  </Space>
                ) : (
                  <Space size={4}>
                    <span>
                      {renderARTableFieldValue(
                        extraField,
                        record[extraField],
                        record
                      )}
                    </span>
                    <Button
                      type="link"
                      size="small"
                      style={{ padding: 0 }}
                      icon={<EditOutlined />}
                      onClick={() =>
                        setInlineEditState({
                          field: extraField as EditableField,
                          id: record.id!,
                          value: getEditableFieldValue(
                            record,
                            extraField as EditableField
                          )
                        })
                      }
                    />
                  </Space>
                )
              ) : (
                renderARTableFieldValue(extraField, record[extraField], record)
              )}
            </div>
          ))}
        </Space>
      </Space>
    )
  }

  const handleDownloadByFilters = async () => {
    try {
      setIsDownloadingList(true)
      await downloadARTableByFilters(
        {
          year: queryFilter.year,
          month: queryFilter.month,
          is_estimated: queryFilter.isEstimated,
          tenant_id: /^\d+$/.test(queryFilter.tenantId)
            ? Number(queryFilter.tenantId)
            : undefined
        },
        `ARTable-${queryFilter.year}-${String(queryFilter.month).padStart(
          2,
          '0'
        )}`
      )
    } catch (error) {
      notification.error({ message: getErrorMessage(error) })
    } finally {
      setIsDownloadingList(false)
    }
  }

  const handleDelete = async (record: FormsARTableRecordResponse) => {
    try {
      if (!record.id) {
        return
      }

      await deleteRecord({ id: record.id })
      notification.success({ message: 'Deleted successfully' })
      if (drawerRecord?.id === record.id) {
        setDrawerRecord(null)
      }
      await refetch()
    } catch (error) {
      notification.error({ message: getErrorMessage(error) })
    }
  }

  const handleUpdate = async (
    record: FormsARTableRecordResponse,
    updates: Partial<Record<EditableField, string>>
  ) => {
    if (!record.id) {
      return
    }

    const payload = buildUpdatePayload(record, updates)

    if (!payload) {
      notification.error({
        message: 'Missing required record fields for update'
      })
      return
    }

    try {
      const response = await updateRecord({
        id: record.id,
        data: payload
      })
      const updatedRecord = response.data

      notification.success({ message: 'Updated successfully' })
      setInlineEditState(null)
      if (drawerRecord?.id === record.id) {
        openDrawer(updatedRecord)
      }
      await refetch()
    } catch (error) {
      notification.error({ message: getErrorMessage(error) })
    }
  }

  const columns = useMemo<ColumnsType<FormsARTableRecordResponse>>(
    () => [
      ...AR_TABLE_FIELDS.map((field) => ({
        title: formatARTableFieldLabel(field),
        key: field,
        dataIndex:
          field === 'payment_extra_info'
            ? undefined
            : (field as keyof FormsARTableRecordResponse),
        width: field === 'payment_extra_info' ? 340 : 180,
        fixed: field === 'tenant_id' ? ('left' as const) : undefined,
        render: (
          value: FormsARTableRecordResponse[keyof FormsARTableRecordResponse],
          record: FormsARTableRecordResponse
        ) => {
          if (field === 'payment_extra_info') {
            return renderPaymentExtraInfo(record, {})
          }

          if (
            getEditableFieldsForRecord(record).includes(
              field as EditableField
            ) &&
            record.id
          ) {
            const editableField = field as EditableField
            const isEditing =
              inlineEditState?.id === record.id &&
              inlineEditState.field === editableField

            if (isEditing) {
              return (
                <Space size="small">
                  {editableField === 'stripe_invoice_paid' ? (
                    <Select
                      size="small"
                      style={{ width: 88 }}
                      value={inlineEditState.value || undefined}
                      onChange={(nextValue) => {
                        setInlineEditState((currentState) =>
                          currentState
                            ? {
                                ...currentState,
                                value: nextValue
                              }
                            : currentState
                        )
                      }}
                    >
                      <Select.Option value="true">true</Select.Option>
                      <Select.Option value="false">false</Select.Option>
                    </Select>
                  ) : editableField === 'payment_type' ? (
                    <Input
                      size="small"
                      style={{ width: 110 }}
                      value={inlineEditState.value}
                      onChange={(event) => {
                        setInlineEditState((currentState) =>
                          currentState
                            ? {
                                ...currentState,
                                value: event.target.value
                              }
                            : currentState
                        )
                      }}
                    />
                  ) : (
                    <Input
                      size="small"
                      style={{ width: 88 }}
                      value={inlineEditState.value}
                      onChange={(event) => {
                        setInlineEditState((currentState) =>
                          currentState
                            ? {
                                ...currentState,
                                value: event.target.value
                              }
                            : currentState
                        )
                      }}
                    />
                  )}
                  <Button
                    type="link"
                    size="small"
                    style={{ padding: 0 }}
                    icon={<CheckOutlined />}
                    loading={isUpdating}
                    onClick={() =>
                      handleUpdate(record, {
                        [editableField]: inlineEditState.value
                      })
                    }
                  />
                  <Button
                    type="link"
                    size="small"
                    style={{ padding: 0 }}
                    icon={<CloseOutlined />}
                    onClick={() => setInlineEditState(null)}
                  />
                </Space>
              )
            }

            return (
              <Space size="small">
                <span>{renderARTableFieldValue(field, value, record)}</span>
                <Button
                  type="link"
                  size="small"
                  style={{ padding: 0 }}
                  icon={<EditOutlined />}
                  onClick={() =>
                    setInlineEditState({
                      field: editableField,
                      id: record.id!,
                      value: getEditableFieldValue(record, editableField)
                    })
                  }
                />
              </Space>
            )
          }

          return renderARTableFieldValue(field, value, record)
        }
      })),
      {
        title: 'Action',
        key: 'action',
        width: 120,
        fixed: 'right' as const,
        render: (_, record) => {
          if (!record.id) {
            return '-'
          }

          return (
            <Space size="small">
              <Button
                type="link"
                size="small"
                style={{ padding: '0 4px' }}
                onClick={() => openDrawer(record)}
              >
                Details
              </Button>
              <Popconfirm
                icon={<QuestionCircleOutlined style={{ color: 'red' }} />}
                title="Are you sure to delete this record?"
                okText="Yes"
                cancelText="No"
                onConfirm={() => handleDelete(record)}
              >
                <Button
                  type="link"
                  size="small"
                  style={{ padding: '0 4px' }}
                  loading={isDeleting}
                >
                  Delete
                </Button>
              </Popconfirm>
            </Space>
          )
        }
      }
    ],
    [inlineEditState, isDeleting, isUpdating]
  )

  const handleSearch = () => {
    if (isQueryLocked) {
      return
    }

    setQueryFilter(draftFilter)
    setPageConfig((prev) => ({
      ...prev,
      page: 1
    }))
  }

  const handleReset = () => {
    if (isQueryLocked) {
      return
    }

    const nextFilter = getDefaultFilter()

    setDraftFilter(nextFilter)
    setQueryFilter(nextFilter)
    setPageConfig({
      page: 1,
      pageSize: PAGE_SIZE
    })
  }

  const handleTableChange: TableProps<FormsARTableRecordResponse>['onChange'] =
    (pagination) => {
      if (isQueryLocked) {
        return
      }

      setPageConfig({
        page: pagination.current || 1,
        pageSize: pagination.pageSize || PAGE_SIZE
      })
    }

  const handleEstimatedChange = (checked: boolean) => {
    if (isQueryLocked) {
      return
    }

    const nextFilter = {
      ...draftFilter,
      isEstimated: checked
    }

    setDraftFilter(nextFilter)
    setQueryFilter(nextFilter)
    setPageConfig((prev) => ({
      ...prev,
      page: 1
    }))
  }

  const handleMonthChange = (date: dayjs.Dayjs) => {
    if (isQueryLocked) {
      return
    }

    const nextFilter = {
      ...draftFilter,
      year: date.year(),
      month: date.month() + 1
    }

    setDraftFilter(nextFilter)
    setQueryFilter(nextFilter)
    setPageConfig((prev) => ({
      ...prev,
      page: 1
    }))
  }

  const handleTenantIdChange = (value: string) => {
    if (isQueryLocked) {
      return
    }

    setDraftFilter((prev) => ({
      ...prev,
      tenantId: value.replace(/\D/g, '')
    }))
  }

  const handleDrawerSave = () => {
    if (!drawerRecord) {
      return
    }

    const allowedFields = getEditableFieldsForRecord(drawerRecord)
    const updates = allowedFields.reduce((result, field) => {
      result[field] = drawerEditValues[field]
      return result
    }, {} as Partial<Record<EditableField, string>>)

    handleUpdate(drawerRecord, updates)
  }

  const renderDrawerFieldContent = (field: ARTableDisplayField) => {
    if (field === 'payment_extra_info') {
      return drawerRecord
        ? renderPaymentExtraInfo(drawerRecord, { isDrawer: true })
        : '-'
    }

    if (
      isDrawerEditing &&
      drawerRecord &&
      getEditableFieldsForRecord(drawerRecord).includes(field as EditableField)
    ) {
      if (field === 'stripe_invoice_paid') {
        return (
          <Select
            style={{ width: 120 }}
            value={drawerEditValues[field] || undefined}
            onChange={(nextValue) => {
              const editableField = field as EditableField
              setDrawerEditValues((prev) => ({
                ...prev,
                [editableField]: nextValue
              }))
            }}
          >
            <Select.Option value="true">true</Select.Option>
            <Select.Option value="false">false</Select.Option>
          </Select>
        )
      }

      if (field === 'payment_type') {
        return (
          <Input
            value={drawerEditValues[field] || ''}
            onChange={(event) => {
              const editableField = field as EditableField
              setDrawerEditValues((prev) => ({
                ...prev,
                [editableField]: event.target.value
              }))
            }}
          />
        )
      }

      return (
        <Input
          value={drawerEditValues[field as EditableField]}
          onChange={(event) => {
            const editableField = field as EditableField
            setDrawerEditValues((prev) => ({
              ...prev,
              [editableField]: event.target.value
            }))
          }}
        />
      )
    }

    return renderARTableFieldValue(
      field,
      drawerRecord?.[field as keyof FormsARTableRecordResponse],
      drawerRecord
    )
  }

  return (
    <div>
      <ARTableList
        columns={columns}
        draftFilter={draftFilter}
        isDeleting={isDeleting}
        isDownloadingList={isDownloadingList}
        isFetching={isFetching}
        isQueryLocked={isQueryLocked}
        maxMonth={maxMonth}
        onDownload={handleDownloadByFilters}
        onEstimatedChange={handleEstimatedChange}
        onMonthChange={handleMonthChange}
        onReset={handleReset}
        onSearch={handleSearch}
        onTableChange={handleTableChange}
        onTenantIdChange={handleTenantIdChange}
        pageConfig={pageConfig}
        tableData={tableData}
        total={total}
      />
      <ARTableDrawer
        currentDrawerIndex={currentDrawerIndex}
        drawerRecord={drawerRecord}
        isDeleting={isDeleting}
        isDrawerEditing={isDrawerEditing}
        isUpdating={isUpdating}
        onCancel={() => {
          if (drawerRecord) {
            openDrawer(drawerRecord)
          }
        }}
        onClose={() => {
          setDrawerRecord(null)
        }}
        onDelete={() => {
          if (drawerRecord) {
            handleDelete(drawerRecord)
          }
        }}
        onEdit={() => setIsDrawerEditing(true)}
        onNext={() => {
          if (currentDrawerIndex < tableData.length - 1) {
            openDrawer(tableData[currentDrawerIndex + 1])
          }
        }}
        onPrevious={() => {
          if (currentDrawerIndex > 0) {
            openDrawer(tableData[currentDrawerIndex - 1])
          }
        }}
        onSave={handleDrawerSave}
        renderFieldContent={renderDrawerFieldContent}
        tableDataLength={tableData.length}
      />
    </div>
  )
}

export default ARTable
