import { useMemo, useState } from 'react'
import { useSearchParams } from 'react-router-dom'
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,
  message } from 'antd'
import CareTable from '../../components/CareTable'
import SubjectSettingsModal from '../../components/SubjectSettingsModal'
import {
  BookOutlined,
  CloseOutlined,
  DownloadOutlined,
  EditOutlined,
  LeftOutlined,
  PlusSquareOutlined,
  ReloadOutlined,
  RightOutlined,
  SearchOutlined,
  SettingOutlined } from '@ant-design/icons'
import client, { apiPrefix, unwrap, type ApiResponse } from '../../api/client'
import { options } from './homesShared'

const { RangePicker } = DatePicker

type AbookRow = {
  id: number
  entryDate?: string
  entryType?: string
  category?: string
  item?: string
  amount?: number
  deposit?: number | null
  withdraw?: number | null
  cardDeposit?: number | null
  cardWithdraw?: number | null
  memo?: string
  employee?: string
}

type AbookSummary = {
  carryOver?: number
  deposit?: number
  withdraw?: number
  total?: number
}

type AbookResult = {
  total: number
  list: AbookRow[]
  counts?: Record<string, number>
  categoryCounts?: Record<string, number>
  categories?: string[]
  employees?: string[]
  items?: string[]
  summary?: AbookSummary
}

const ENTRY_TYPES = ['입금', '출금', '카드입금', '카드출금'] as const

const money = (v?: number | null) => {
  if (v == null || Number.isNaN(Number(v))) return '-'
  return Number(v).toLocaleString('ko-KR')
}

const isOut = (type?: string) => type === '출금' || type === '카드출금'
const typeClass = (type?: string) => {
  if (type === '입금' || type === '카드입금') return 'abook-in'
  if (isOut(type)) return 'abook-out'
  return ''
}

export default function AbooksPage() {
  const [form] = Form.useForm()
  const [editForm] = Form.useForm()
  const qc = useQueryClient()
  const [searchParams] = useSearchParams()
  const initialView = searchParams.get('view') === 'detail' ? 'detail' : 'month'
  const [view, setView] = useState<'month' | 'detail'>(initialView)
  const [month, setMonth] = useState(dayjs())
  const [day, setDay] = useState<number | 'ALL'>('ALL')
  const [categoryTab, setCategoryTab] = useState('ALL')
  const [detailFilters, setDetailFilters] = useState<Record<string, unknown>>({
    page: 0,
    size: 10,
    tab: 'ALL' })
  const [selected, setSelected] = useState<number[]>([])
  const [editing, setEditing] = useState<AbookRow | null>(null)
  const [creating, setCreating] = useState(false)
  const [catOpen, setCatOpen] = useState(false)

  const monthParams = useMemo(() => ({
    yearMonth: month.format('YYYY-MM'),
    day: day === 'ALL' ? undefined : day,
    category: categoryTab === 'ALL' ? undefined : categoryTab,
    page: 0,
    size: 200 }), [month, day, categoryTab])

  const query = useQuery({
    queryKey: ['homes-abooks', view, view === 'month' ? monthParams : detailFilters],
    queryFn: async () => {
      const params = view === 'month'
        ? monthParams
        : {
            ...detailFilters,
            entryType: detailFilters.tab === 'ALL' ? undefined : detailFilters.tab }
      const { data } = await client.get<ApiResponse<AbookResult>>(`${apiPrefix()}/homes/abooks`, { params })
      return unwrap(data)
    } })

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

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

  const staffOptions = useMemo(() => {
    const fromApi = query.data?.employees || []
    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, members.data])

  const categories = useMemo(
    () => query.data?.categories || ['일반', '123'],
    [query.data?.categories],
  )

  const categoryTabs = useMemo(
    () => [
      { key: 'ALL', label: `전체 ${query.data?.categoryCounts?.ALL ?? query.data?.total ?? 0}` },
      ...categories.map((c) => ({
        key: c,
        label: `${c} ${query.data?.categoryCounts?.[c] ?? 0}` })),
    ],
    [query.data, categories],
  )

  const detailTabs = useMemo(
    () => [
      { key: 'ALL', label: `전체 ${query.data?.counts?.ALL ?? query.data?.total ?? 0}` },
      ...ENTRY_TYPES.map((t) => ({ key: t, label: `${t} ${query.data?.counts?.[t] ?? 0}` })),
    ],
    [query.data],
  )

  const daysInMonth = month.daysInMonth()
  const today = dayjs()

  const save = useMutation({
    mutationFn: async (values: Record<string, unknown>) => {
      const payload: Record<string, unknown> = {
        employee: values.employee,
        entryDate: values.entryDate ? dayjs(values.entryDate as Dayjs).format('YYYY-MM-DD') : undefined,
        entryType: values.entryType,
        category: values.category,
        item: values.item,
        amount: values.amount,
        memo: values.memo }
      if (editing) {
        const { data } = await client.put(`${apiPrefix()}/homes/abooks/${editing.id}`, payload)
        return unwrap(data as ApiResponse)
      }
      const { data } = await client.post(`${apiPrefix()}/homes/abooks`, 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 deleteMut = useMutation({
    mutationFn: async (ids: number[]) => {
      const { data } = await client.post(`${apiPrefix()}/homes/abooks/delete`, { ids })
      return unwrap(data as ApiResponse<{ deleted: number }>)
    },
    onSuccess: (data) => {
      message.success(`${data.deleted}건을 삭제했습니다.`)
      refresh()
    },
    onError: (e: Error) => message.error(e.message) })

  const saveCategories = useMutation({
    mutationFn: async (cats: string[]) => {
      const { data } = await client.put(`${apiPrefix()}/homes/abooks/categories`, { categories: cats })
      return unwrap(data as ApiResponse<{ categories: string[] }>)
    },
    onSuccess: () => {
      message.success('과목을 저장했습니다.')
      setCatOpen(false)
      refresh()
    },
    onError: (e: Error) => message.error(e.message) })

  const openCreate = () => {
    setEditing(null)
    setCreating(true)
    editForm.setFieldsValue({
      employee: staffOptions[0]?.value || '홍길동',
      entryDate: dayjs(),
      entryType: '입금',
      category: categories[0] || '일반',
      item: undefined,
      amount: undefined,
      memo: undefined })
  }

  const openEdit = (row: AbookRow) => {
    setCreating(false)
    setEditing(row)
    editForm.setFieldsValue({
      employee: row.employee,
      entryDate: row.entryDate ? dayjs(row.entryDate) : dayjs(),
      entryType: row.entryType || '입금',
      category: row.category || '일반',
      item: row.item,
      amount: row.amount,
      memo: row.memo })
  }

  const openCatSettings = () => setCatOpen(true)

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

  const onDetailSearch = (values: Record<string, unknown>) => {
    const dates = values.dates as [Dayjs, Dayjs] | undefined
    setDetailFilters({
      page: 0,
      size: values.size ?? detailFilters.size ?? 10,
      tab: detailFilters.tab,
      category: values.category || undefined,
      employee: values.employee || undefined,
      item: values.item || undefined,
      q: values.q || undefined,
      dateFrom: dates?.[0]?.format('YYYY-MM-DD'),
      dateTo: dates?.[1]?.format('YYYY-MM-DD') })
  }

  const resetDetail = () => {
    form.resetFields()
    form.setFieldsValue({ size: 10 })
    setDetailFilters({ page: 0, size: 10, tab: 'ALL' })
  }

  const download = async () => {
    try {
      const params = view === 'month'
        ? monthParams
        : { ...detailFilters, entryType: detailFilters.tab === 'ALL' ? undefined : detailFilters.tab }
      const { data } = await client.get(`${apiPrefix()}/homes/abooks/export`, {
        params,
        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 summary = query.data?.summary
  const summaryText = `현금시제 : (전월) 이월금 ${money(summary?.carryOver)} 원 + 입금 ${money(summary?.deposit)} 원 - 출금 ${money(summary?.withdraw)} 원 = 합계 ${money(summary?.total)} 원`

  const monthColumns = [
    { title: '거래일', dataIndex: 'entryDate', width: 110 },
    { title: '과목', dataIndex: 'category', width: 90 },
    { title: '품목', dataIndex: 'item', width: 140, ellipsis: true },
    {
      title: '입금(+)',
      dataIndex: 'deposit',
      width: 100,
      align: 'right' as const,
      render: (v: number | null) => <span className="abook-in">{v != null ? money(v) : '-'}</span> },
    {
      title: '출금(-)',
      dataIndex: 'withdraw',
      width: 100,
      align: 'right' as const,
      render: (v: number | null) => <span className="abook-out">{v != null ? money(v) : '-'}</span> },
    {
      title: '카드입금(+)',
      dataIndex: 'cardDeposit',
      width: 110,
      align: 'right' as const,
      render: (v: number | null) => <span className="abook-in">{v != null ? money(v) : '-'}</span> },
    {
      title: '카드출금(-)',
      dataIndex: 'cardWithdraw',
      width: 110,
      align: 'right' as const,
      render: (v: number | null) => <span className="abook-out">{v != null ? money(v) : '-'}</span> },
    { title: '비고', dataIndex: 'memo', width: 140, ellipsis: true, render: (v: string) => v || '-' },
    { title: '직원', dataIndex: 'employee', width: 90 },
    {
      title: '관리',
      width: 64,
      fixed: 'right' as const,
      align: 'center' as const,
      render: (_: unknown, row: AbookRow) => (
        <Button size="small" type="primary" className="abook-manage-btn" icon={<EditOutlined />} onClick={() => openEdit(row)} />
      ) },
  ]

  const detailColumns = [
    {
      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: AbookRow) => (
        <Checkbox
          checked={selected.includes(row.id)}
          onChange={(e) => setSelected((prev) => (e.target.checked ? [...prev, row.id] : prev.filter((id) => id !== row.id)))}
        />
      ) },
    {
      title: '거래일',
      dataIndex: 'entryDate',
      width: 110,
      sorter: (a: AbookRow, b: AbookRow) => String(a.entryDate || '').localeCompare(String(b.entryDate || '')) },
    {
      title: '구분',
      dataIndex: 'entryType',
      width: 90,
      render: (v: string) => <span className={typeClass(v)}>{v}</span> },
    { title: '과목', dataIndex: 'category', width: 90 },
    { title: '품목', dataIndex: 'item', width: 140, ellipsis: true },
    {
      title: '금액',
      dataIndex: 'amount',
      width: 110,
      align: 'right' as const,
      sorter: (a: AbookRow, b: AbookRow) => Number(a.amount || 0) - Number(b.amount || 0),
      render: (v: number, row: AbookRow) => <span className={typeClass(row.entryType)}>{money(v)}</span> },
    { title: '비고', dataIndex: 'memo', width: 140, ellipsis: true, render: (v: string) => v || '-' },
    { title: '직원', dataIndex: 'employee', width: 90 },
    {
      title: '관리',
      width: 64,
      fixed: 'right' as const,
      align: 'center' as const,
      render: (_: unknown, row: AbookRow) => (
        <Button size="small" type="primary" className="abook-manage-btn" icon={<EditOutlined />} onClick={() => openEdit(row)} />
      ) },
  ]

  const modalOpen = creating || Boolean(editing)

  return (
    <div className="stock-page abook-manage-page">
      <div className="stock-title abook-title-row">
        <div>
          <h2>
            <BookOutlined className="product-title-icon" />
            간편장부
          </h2>
          <p>매장의 시제 및 관련 장부관리를 관리하실 수 있습니다.</p>
        </div>
        <div className="abook-view-toggle">
          <Button className={view === 'month' ? 'abook-view-active' : ''} onClick={() => setView('month')}>
            월별 간편장부
          </Button>
          <Button className={view === 'detail' ? 'abook-view-active' : ''} onClick={() => setView('detail')}>
            상세 간편장부
          </Button>
        </div>
        <Space className="stock-title-actions" wrap>
          {view === 'detail' && (
            <Button
              disabled={!selected.length}
              loading={deleteMut.isPending}
              onClick={() => {
                if (!selected.length) {
                  message.warning('삭제할 장부를 선택하세요.')
                  return
                }
                deleteMut.mutate(selected)
              }}
            >
              삭제
            </Button>
          )}
          <Button className="abook-register-btn" type="primary" icon={<PlusSquareOutlined />} onClick={openCreate}>
            간편장부 등록
          </Button>
        </Space>
      </div>

      {view === 'month' ? (
        <Card className="stock-table-card" size="small">
          <div className="abook-month-nav">
            <Button type="text" icon={<LeftOutlined />} onClick={() => { setMonth((m) => m.subtract(1, 'month')); setDay('ALL') }} />
            <span className="abook-month-label">{month.format('YYYY년 M월')}</span>
            <Button type="text" icon={<RightOutlined />} onClick={() => { setMonth((m) => m.add(1, 'month')); setDay('ALL') }} />
          </div>
          <div className="abook-day-row">
            <button
              type="button"
              className={`abook-day-btn${day === 'ALL' ? ' active' : ''}`}
              onClick={() => setDay('ALL')}
            >
              전체
            </button>
            {Array.from({ length: daysInMonth }, (_, i) => i + 1).map((d) => {
              const isToday = month.isSame(today, 'month') && d === today.date()
              return (
                <button
                  key={d}
                  type="button"
                  className={`abook-day-btn${day === d ? ' active' : ''}${isToday ? ' today' : ''}`}
                  onClick={() => setDay(d)}
                >
                  {d}
                </button>
              )
            })}
          </div>
          <div className="stock-table-actions">
            <Tabs
              activeKey={categoryTab}
              onChange={setCategoryTab}
              items={categoryTabs}
            />
            <Button type="link" icon={<SettingOutlined />} onClick={openCatSettings}>과목설정</Button>
          </div>
          <div className="abook-cash-summary">{summaryText}</div>
          <CareTable
            rowKey="id"
            size="small"
            loading={query.isLoading}
            dataSource={query.data?.list}
            columns={monthColumns}
            scroll={{ x: 1100 }}
            pagination={false}
            locale={{ emptyText: '등록되어 있는 간편장부가 없습니다.' }}
          />
        </Card>
      ) : (
        <>
          <Card className="stock-filter-card" size="small">
            <Form form={form} layout="inline" className="balance-filter" initialValues={{ size: 10 }} onFinish={onDetailSearch}>
              <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)} />
              </div>
              <div className="stock-filter-row">
                <Form.Item name="category">
                  <Select allowClear placeholder="과목" className="w-120" options={options(categories)} />
                </Form.Item>
                <Form.Item name="employee">
                  <Select allowClear showSearch placeholder="등록직원" className="w-120" options={staffOptions} optionFilterProp="label" />
                </Form.Item>
                <Form.Item name="item">
                  <Select
                    allowClear
                    showSearch
                    placeholder="품목"
                    className="w-140"
                    options={(query.data?.items || []).map((v) => ({ value: v, label: v }))}
                    optionFilterProp="label"
                  />
                </Form.Item>
                <Form.Item name="q">
                  <Input placeholder="검색" className="w-160" allowClear />
                </Form.Item>
                <Button type="primary" htmlType="submit" icon={<SearchOutlined />}>검색</Button>
                <Button icon={<ReloadOutlined />} onClick={resetDetail}>초기화</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)
                      setDetailFilters((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(detailFilters.tab)}
                onChange={(tab) => setDetailFilters((v) => ({ ...v, tab, page: 0 }))}
                items={detailTabs}
              />
              <Space>
                <Button type="link" icon={<SettingOutlined />} onClick={openCatSettings}>과목설정</Button>
                <Button type="link" icon={<DownloadOutlined />} onClick={download}>엑셀다운로드</Button>
              </Space>
            </div>
            <CareTable
              rowKey="id"
              size="small"
              loading={query.isLoading}
              dataSource={query.data?.list}
              columns={detailColumns}
              scroll={{ x: 1000 }}
              pagination={{
                current: Number(detailFilters.page) + 1,
                pageSize: Number(detailFilters.size),
                total: query.data?.total,
                showSizeChanger: false,
                onChange: (page) => setDetailFilters((v) => ({ ...v, page: page - 1 })) }}
              locale={{ emptyText: '등록되어 있는 간편장부가 없습니다.' }}
            />
          </Card>
        </>
      )}

      <Modal
        title={editing ? '간편장부 수정' : '간편장부 등록'}
        open={modalOpen}
        onCancel={() => { setCreating(false); setEditing(null) }}
        footer={null}
        destroyOnHidden
        width={560}
        className="abook-modal"
      >
        <Form
          form={editForm}
          layout="horizontal"
          labelCol={{ flex: '100px' }}
          wrapperCol={{ flex: 1 }}
          onFinish={(values) => save.mutate(values)}
          className="balance-edit-form"
        >
          <Form.Item name="employee" label="등록직원" rules={[{ required: true, message: '등록직원을 선택하세요' }]}>
            <Select options={staffOptions} showSearch optionFilterProp="label" />
          </Form.Item>
          <Form.Item name="entryDate" label="거래일" rules={[{ required: true, message: '거래일을 선택하세요' }]}>
            <DatePicker className="full-width" />
          </Form.Item>
          <Form.Item name="entryType" label="구분" rules={[{ required: true, message: '구분을 선택하세요' }]}>
            <Radio.Group options={ENTRY_TYPES.map((t) => ({ value: t, label: t }))} />
          </Form.Item>
          <Form.Item label="과목" required>
            <Space.Compact className="full-width">
              <Form.Item name="category" noStyle rules={[{ required: true, message: '과목을 선택하세요' }]}>
                <Select options={options(categories)} style={{ width: '100%' }} />
              </Form.Item>
              <Button icon={<SettingOutlined />} onClick={openCatSettings}>설정</Button>
            </Space.Compact>
          </Form.Item>
          <Form.Item name="item" label="품목" rules={[{ required: true, message: '품목을 입력하세요' }]}>
            <Input />
          </Form.Item>
          <Form.Item name="amount" label="금액" rules={[{ required: true, message: '금액을 입력하세요' }]}>
            <InputNumber className="full-width" min={0} addonAfter="원" controls={false} />
          </Form.Item>
          <Form.Item name="memo" label="비고" extra="최대 1,000자">
            <Input.TextArea rows={4} maxLength={1000} showCount />
          </Form.Item>
          <div className="balance-modal-footer">
            <Button className="abook-submit-btn" type="primary" htmlType="submit" loading={save.isPending}>
              {editing ? '수정합니다' : '등록'}
            </Button>
            <Button onClick={() => { setCreating(false); setEditing(null) }}>취소</Button>
          </div>
        </Form>
      </Modal>

      <SubjectSettingsModal
        open={catOpen}
        items={categories}
        saving={saveCategories.isPending}
        submitClassName="abook-submit-btn"
        onCancel={() => setCatOpen(false)}
        onSave={(cats) => saveCategories.mutate(cats)}
      />
    </div>
  )
}
