import { useMemo, useState } from 'react'
import Modal from '../../components/DraggableModal'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import dayjs, { type Dayjs } from 'dayjs'
import {
  Button,
  Card,
  Checkbox,
  DatePicker,
  Form,
  Input,
  InputNumber,
  Radio,
  Select,
  Space,
  Tabs,
  Tooltip,
  message } from 'antd'
import CareTable from '../../components/CareTable'
import {
  CloseOutlined,
  DownloadOutlined,
  EditOutlined,
  MailOutlined,
  PlusSquareOutlined,
  RadarChartOutlined,
  ReloadOutlined,
  SearchOutlined } from '@ant-design/icons'
import client, { apiPrefix, unwrap, type ApiResponse } from '../../api/client'
import { options, type PageResult } from './homesShared'

const { RangePicker } = DatePicker

const TABS = [
  ['ALL', '전체'],
  ['정산차감', '정산차감'],
  ['정산추가', '정산추가'],
] as const

type BalanceRow = {
  id: number
  balanceType?: string
  targetType?: string
  targetName?: string
  baseDate?: string
  reason?: string
  amount?: number
  memo?: string
}

type BalanceSearch = PageResult & {
  list: BalanceRow[]
  counts?: Record<string, number>
  employees?: string[]
  agencies?: string[]
  reasons?: string[]
}

const isDeduct = (gubun?: string) => Boolean(gubun && gubun.includes('차감'))

const initial = {
  page: 0,
  size: 10,
  tab: 'ALL' } as Record<string, unknown>

export default function ContractBalancePage() {
  const [form] = Form.useForm()
  const [editForm] = Form.useForm()
  const qc = useQueryClient()
  const [filters, setFilters] = useState<Record<string, unknown>>(initial)
  const [selected, setSelected] = useState<number[]>([])
  const [editing, setEditing] = useState<BalanceRow | null>(null)
  const [creating, setCreating] = useState(false)
  const [amountSign, setAmountSign] = useState<'+' | '-'>('-')

  const query = useQuery({
    queryKey: ['homes-balances', filters],
    queryFn: async () => {
      const { data } = await client.get<ApiResponse<BalanceSearch>>(`${apiPrefix()}/homes/balances`, { params: filters })
      return unwrap(data)
    } })

  const members = useQuery({
    queryKey: ['homes/members-options'],
    queryFn: async () => {
      const { data } = await client.get<ApiResponse<PageResult>>(`${apiPrefix()}/homes/members`, { params: { page: 0, size: 200 } })
      return unwrap(data)
    } })

  const agencies = useQuery({
    queryKey: ['homes/agencies-options'],
    queryFn: async () => {
      const { data } = await client.get<ApiResponse<PageResult>>(`${apiPrefix()}/homes/agencies`, { params: { page: 0, size: 200 } })
      return unwrap(data)
    } })

  const refresh = () => {
    qc.invalidateQueries({ queryKey: ['homes-balances'] })
    setSelected([])
  }

  const employeeOptions = useMemo(() => {
    const fromApi = (query.data?.employees || []) as string[]
    const fromMembers = (members.data?.list || []).map((m) => String(m.name || '')).filter(Boolean)
    return Array.from(new Set([...fromApi, ...fromMembers])).map((v) => ({ value: v, label: v }))
  }, [query.data?.employees, members.data])

  const agencyOptions = useMemo(() => {
    const fromApi = (query.data?.agencies || []) as string[]
    const fromAgencies = (agencies.data?.list || []).map((a) => String(a.name || '')).filter(Boolean)
    return Array.from(new Set([...fromApi, ...fromAgencies])).map((v) => ({ value: v, label: v }))
  }, [query.data?.agencies, agencies.data])

  const reasonOptions = useMemo(() => {
    const fromApi = (query.data?.reasons || []) as string[]
    return fromApi.map((v) => ({ value: v, label: v }))
  }, [query.data?.reasons])

  const save = useMutation({
    mutationFn: async (values: Record<string, unknown>) => {
      const raw = Number(values.amountAbs ?? 0)
      const signed = amountSign === '-' ? -Math.abs(raw) : Math.abs(raw)
      const payload: Record<string, unknown> = {
        targetType: values.targetType,
        targetName: values.targetName,
        balanceType: values.balanceType,
        reason: values.reason,
        memo: values.memo,
        amount: signed,
        baseDate: values.baseDate ? dayjs(values.baseDate as Dayjs).format('YYYY-MM-DD') : dayjs().format('YYYY-MM-DD') }
      if (editing) {
        const { data } = await client.put(`${apiPrefix()}/homes/balances/${editing.id}`, payload)
        return unwrap(data as ApiResponse)
      }
      const { data } = await client.post(`${apiPrefix()}/homes/balances`, payload)
      return unwrap(data as ApiResponse)
    },
    onSuccess: () => {
      message.success(editing ? '수정했습니다.' : '후정산을 등록했습니다.')
      setCreating(false)
      setEditing(null)
      editForm.resetFields()
      refresh()
    },
    onError: (e: Error) => message.error(e.message || '저장에 실패했습니다.') })

  const remove = useMutation({
    mutationFn: async (ids: number[]) => {
      const { data } = await client.post(`${apiPrefix()}/homes/balances/delete`, { ids })
      return unwrap(data as ApiResponse<{ deleted: number }>)
    },
    onSuccess: (data) => {
      message.success(`${data.deleted}건을 삭제했습니다.`)
      refresh()
    },
    onError: (e: Error) => message.error(e.message) })

  const setPreset = (from: Dayjs, to: Dayjs) => form.setFieldsValue({ dates: [from, to] })

  const onSearch = (values: Record<string, unknown>) => {
    const dates = values.dates as [Dayjs, Dayjs] | undefined
    setFilters({
      ...initial,
      employee: values.employee || undefined,
      agency: values.agency || undefined,
      reason: values.reason || undefined,
      q: values.q || undefined,
      dateFrom: dates?.[0]?.format('YYYY-MM-DD'),
      dateTo: dates?.[1]?.format('YYYY-MM-DD'),
      page: 0,
      size: values.size ?? filters.size ?? 10,
      tab: filters.tab })
  }

  const reset = () => {
    form.resetFields()
    form.setFieldsValue({ size: 10 })
    setFilters(initial)
  }

  const openCreate = () => {
    setEditing(null)
    setCreating(true)
    setAmountSign('-')
    editForm.setFieldsValue({
      targetType: '직원',
      targetName: undefined,
      balanceType: '정산차감',
      baseDate: dayjs(),
      amountAbs: undefined,
      reason: undefined,
      memo: undefined })
  }

  const openEdit = (row: BalanceRow) => {
    setCreating(false)
    setEditing(row)
    const amount = Number(row.amount ?? 0)
    setAmountSign(amount < 0 || isDeduct(row.balanceType) ? '-' : '+')
    editForm.setFieldsValue({
      targetType: row.targetType || '직원',
      targetName: row.targetName,
      balanceType: row.balanceType || '정산차감',
      amountAbs: Math.abs(amount),
      reason: row.reason,
      memo: row.memo,
      baseDate: row.baseDate ? dayjs(row.baseDate) : dayjs() })
  }

  const download = async () => {
    try {
      const { data } = await client.get(`${apiPrefix()}/homes/balances/export`, { params: filters, responseType: 'blob' })
      const url = URL.createObjectURL(data)
      const a = document.createElement('a')
      a.href = url
      a.download = '계약후정산.csv'
      a.click()
      URL.revokeObjectURL(url)
    } catch {
      message.error('엑셀 다운로드에 실패했습니다.')
    }
  }

  const targetType = Form.useWatch('targetType', editForm)

  const columns = [
    {
      title: (
        <Checkbox
          checked={!!query.data?.list?.length && selected.length === query.data.list.length}
          indeterminate={selected.length > 0 && selected.length < (query.data?.list?.length || 0)}
          onChange={(e) => setSelected(e.target.checked ? (query.data?.list || []).map((r) => r.id) : [])}
        />
      ),
      width: 42,
      render: (_: unknown, row: BalanceRow) => (
        <Checkbox
          checked={selected.includes(row.id)}
          onChange={(e) => setSelected((prev) => (e.target.checked ? [...prev, row.id] : prev.filter((id) => id !== row.id)))}
        />
      ) },
    { title: '후정산일', dataIndex: 'baseDate', width: 110, sorter: (a: BalanceRow, b: BalanceRow) => String(a.baseDate || '').localeCompare(String(b.baseDate || '')) },
    { title: '대상', dataIndex: 'targetType', width: 80 },
    { title: '대상명', dataIndex: 'targetName', width: 120, ellipsis: true },
    {
      title: '구분',
      dataIndex: 'balanceType',
      width: 100,
      render: (v: string) => <span className={isDeduct(v) ? 'balance-deduct' : ''}>{v}</span> },
    { title: '사유', dataIndex: 'reason', width: 140, ellipsis: true },
    {
      title: '정산금액',
      dataIndex: 'amount',
      width: 110,
      align: 'right' as const,
      render: (v: unknown, row: BalanceRow) => {
        if (v == null || v === '') return '-'
        const n = Number(v)
        const cls = isDeduct(row.balanceType) || n < 0 ? 'balance-amount-deduct' : 'balance-amount'
        return <span className={cls}>{n.toLocaleString()}</span>
      } },
    {
      title: '비고',
      dataIndex: 'memo',
      width: 54,
      align: 'center' as const,
      render: (v: string) => (v ? <Tooltip title={v}><MailOutlined className="memo-icon" /></Tooltip> : '-') },
    {
      title: '관리',
      width: 58,
      fixed: 'right' as const,
      render: (_: unknown, row: BalanceRow) => (
        <Button size="small" type="text" icon={<EditOutlined style={{ color: '#1677ff' }} />} onClick={() => openEdit(row)} />
      ) },
  ]

  const modalOpen = creating || Boolean(editing)

  return (
    <div className="stock-page balance-page contract-balance-page">
      <div className="stock-title">
        <div>
          <h2>
            <RadarChartOutlined className="product-title-icon" />
            계약후정산
          </h2>
          <p>등록된 정산 외 추가로 후정산을 등록 및 관리하실 수 있습니다.</p>
        </div>
        <Space className="stock-title-actions" wrap>
          <Button
            disabled={!selected.length}
            loading={remove.isPending}
            onClick={() => {
              if (!selected.length) return
              remove.mutate(selected)
            }}
          >
            삭제
          </Button>
          <Button className="balance-register-btn" type="primary" icon={<PlusSquareOutlined />} onClick={openCreate}>
            후정산등록
          </Button>
        </Space>
      </div>

      <Card className="stock-filter-card" size="small">
        <Form
          form={form}
          layout="inline"
          className="balance-filter"
          initialValues={{ size: 10 }}
          onFinish={onSearch}
        >
          <div className="stock-filter-row">
            <Form.Item name="dates">
              <RangePicker className="w-230" placeholder={['YYYY-MM-DD', 'YYYY-MM-DD']} />
            </Form.Item>
            <Space.Compact className="sheet-presets">
              <Button onClick={() => setPreset(dayjs(), dayjs())}>오늘</Button>
              <Button onClick={() => setPreset(dayjs().subtract(6, 'day'), dayjs())}>1주일</Button>
              <Button onClick={() => setPreset(dayjs().startOf('month'), dayjs().endOf('month'))}>당월</Button>
              <Button onClick={() => setPreset(dayjs().subtract(1, 'month').startOf('month'), dayjs().subtract(1, 'month').endOf('month'))}>전월</Button>
              <Button onClick={() => setPreset(dayjs().subtract(2, 'month').startOf('month'), dayjs().subtract(2, 'month').endOf('month'))}>전전월</Button>
            </Space.Compact>
            <Button className="sheet-clear" icon={<CloseOutlined />} onClick={() => form.setFieldValue('dates', undefined)} />
            <Form.Item name="employee">
              <Select allowClear placeholder="직원" className="w-120" options={employeeOptions} showSearch optionFilterProp="label" />
            </Form.Item>
            <Form.Item name="agency">
              <Select allowClear placeholder="하부점" className="w-130" options={agencyOptions} showSearch optionFilterProp="label" />
            </Form.Item>
            <Form.Item name="reason">
              <Select allowClear placeholder="사유" className="w-130" options={reasonOptions} showSearch optionFilterProp="label" />
            </Form.Item>
            <Form.Item name="q">
              <Input className="w-130" allowClear />
            </Form.Item>
            <Button type="primary" htmlType="submit" icon={<SearchOutlined />}>검색</Button>
            <Button icon={<ReloadOutlined />} onClick={reset}>초기화</Button>
            <Form.Item name="size" className="sheet-size">
              <Select
                className="w-150"
                options={[10, 15, 30, 50, 100].map((n) => ({ value: n, label: `목록 ${n}개씩 보기` }))}
                onChange={(size) => {
                  form.setFieldValue('size', size)
                  setFilters((v) => ({ ...v, size, page: 0 }))
                }}
              />
            </Form.Item>
          </div>
        </Form>
      </Card>

      <Card className="stock-table-card" size="small">
        <div className="stock-table-actions">
          <Tabs
            activeKey={String(filters.tab)}
            onChange={(tab) => setFilters((v) => ({ ...v, tab, page: 0 }))}
            items={TABS.map(([key, label]) => ({
              key,
              label: key === 'ALL'
                ? `${label} ${query.data?.counts?.ALL ?? query.data?.total ?? 0}`
                : `${label} ${query.data?.counts?.[key] ?? 0}` }))}
          />
          <Button type="link" icon={<DownloadOutlined />} onClick={download}>엑셀다운로드</Button>
        </div>
        <CareTable
          rowKey="id"
          size="small"
          loading={query.isLoading}
          dataSource={query.data?.list}
          columns={columns}
          scroll={{ x: 1000 }}
          pagination={{
            current: Number(filters.page) + 1,
            pageSize: Number(filters.size),
            total: query.data?.total,
            showSizeChanger: false,
            showTotal: (total) => `총 ${total}건`,
            onChange: (page) => setFilters((v) => ({ ...v, page: page - 1 })) }}
        />
      </Card>

      <Modal
        title={editing ? '계약후정산 수정' : '계약후정산 등록'}
        open={modalOpen}
        onCancel={() => { setCreating(false); setEditing(null) }}
        footer={null}
        destroyOnHidden
        width={520}
        className="balance-modal"
      >
        <Form
          form={editForm}
          layout="horizontal"
          labelCol={{ flex: '110px' }}
          wrapperCol={{ flex: 1 }}
          onFinish={(values) => save.mutate(values)}
          className="balance-edit-form"
        >
          <Form.Item name="targetType" label="후정산대상" rules={[{ required: true }]}>
            <Radio.Group
              options={options(['직원', '하부점'])}
              onChange={() => editForm.setFieldValue('targetName', undefined)}
            />
          </Form.Item>
          <Form.Item
            name="targetName"
            label={targetType === '하부점' ? '하부점' : '직원'}
            rules={[{ required: true, message: '대상을 선택하세요' }]}
          >
            <Select
              allowClear
              placeholder="- 선택 -"
              options={targetType === '하부점' ? agencyOptions : employeeOptions}
              showSearch
              optionFilterProp="label"
            />
          </Form.Item>
          <Form.Item name="baseDate" label="후정산일" rules={[{ required: true, message: '후정산일을 선택하세요' }]}>
            <DatePicker className="full-width" />
          </Form.Item>
          <Form.Item name="balanceType" label="구분" rules={[{ required: true }]}>
            <Radio.Group
              options={options(['정산차감', '정산추가'])}
              onChange={(e) => setAmountSign(String(e.target.value).includes('차감') ? '-' : '+')}
            />
          </Form.Item>
          <Form.Item label="정산금액" required>
            <Space.Compact className="balance-amount-input">
              <Button
                className={amountSign === '-' ? 'balance-sign-minus' : ''}
                onClick={() => setAmountSign((s) => (s === '+' ? '-' : '+'))}
              >
                {amountSign}
              </Button>
              <Form.Item name="amountAbs" noStyle rules={[{ required: true, message: '정산금액을 입력하세요' }]}>
                <InputNumber controls={false} min={0} className="full-width" />
              </Form.Item>
              <Button disabled>원</Button>
            </Space.Compact>
          </Form.Item>
          <Form.Item name="reason" label="사유" rules={[{ required: true, message: '사유를 입력하세요' }]}>
            <Input />
          </Form.Item>
          <Form.Item name="memo" label="비고">
            <Input.TextArea rows={3} />
          </Form.Item>
          <div className="balance-modal-footer">
            <Button className="balance-submit-btn" type="primary" htmlType="submit" loading={save.isPending}>
              {editing ? '수정합니다' : '등록'}
            </Button>
            <Button onClick={() => { setCreating(false); setEditing(null) }}>취소</Button>
          </div>
        </Form>
      </Modal>
    </div>
  )
}
