import { useMemo, useState, type ReactNode } from 'react'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import dayjs, { type Dayjs } from 'dayjs'
import {
  Button, Card, Checkbox, DatePicker, Form, Select, Space, Typography, message } from 'antd'
import CareTable from '../../components/CareTable'
import {
  CloseOutlined, DownloadOutlined, EditOutlined, ReloadOutlined, SearchOutlined } from '@ant-design/icons'
import Modal from '../../components/DraggableModal'
import client, { apiPrefix, unwrap, type ApiResponse } from '../../api/client'
import type { Row } from './homesShared'

const { RangePicker } = DatePicker

type LogPageResult = {
  total: number
  list: Row[]
  actions?: string[]
  staffs?: string[]
}

type Props = {
  domain: string
  title: string
  description: string
  defaultActions?: string[]
  titleIcon?: ReactNode
}

export function HomesLogListPage({ domain, title, description, defaultActions = [], titleIcon }: Props) {
  const [form] = Form.useForm()
  const qc = useQueryClient()
  const [selected, setSelected] = useState<number[]>([])
  const [filters, setFilters] = useState<Record<string, unknown>>({
    domain,
    page: 0,
    size: 10 })

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

  const remove = useMutation({
    mutationFn: async (ids: number[]) => {
      const { data } = await client.post(`${apiPrefix()}/homes/logs/delete`, { ids })
      return unwrap(data)
    },
    onSuccess: () => {
      message.success('삭제했습니다.')
      setSelected([])
      qc.invalidateQueries({ queryKey: ['homes/logs'] })
    },
    onError: (e: Error) => message.error(e.message) })

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

  const onSearch = (values: Record<string, unknown>) => {
    const dates = values.dates as [Dayjs, Dayjs] | undefined
    setSelected([])
    setFilters({
      domain,
      action: values.action || undefined,
      staff: values.staff || undefined,
      dateFrom: dates?.[0]?.format('YYYY-MM-DD'),
      dateTo: dates?.[1]?.format('YYYY-MM-DD'),
      page: 0,
      size: values.size ?? filters.size ?? 10 })
  }

  const reset = () => {
    form.resetFields()
    form.setFieldsValue({ size: 10 })
    setSelected([])
    setFilters({ domain, page: 0, size: 10 })
  }

  const download = () => {
    const rows = query.data?.list || []
    if (!rows.length) {
      message.warning('다운로드할 목록이 없습니다.')
      return
    }
    const header = ['구분', '내용', '직원', '처리일']
    const lines = rows.map((r) =>
      [r.action, r.content, r.staff, r.processedAt]
        .map((v) => `"${String(v ?? '').replace(/"/g, '""')}"`)
        .join(','),
    )
    const blob = new Blob(['\uFEFF' + [header.join(','), ...lines].join('\n')], { type: 'text/csv;charset=utf-8;' })
    const url = URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url
    a.download = `${title}_${dayjs().format('YYYYMMDD')}.csv`
    a.click()
    URL.revokeObjectURL(url)
  }

  const actionOptions = useMemo(() => {
    const fromApi = query.data?.actions || []
    return Array.from(new Set([...defaultActions, ...fromApi])).map((v) => ({ value: v, label: v }))
  }, [query.data?.actions, defaultActions])

  const staffOptions = useMemo(
    () => (query.data?.staffs || []).map((v) => ({ value: v, label: v })),
    [query.data?.staffs],
  )

  const list = query.data?.list || []

  const columns = [
    {
      title: (
        <Checkbox
          checked={list.length > 0 && selected.length === list.length}
          indeterminate={selected.length > 0 && selected.length < list.length}
          onChange={(e) => setSelected(e.target.checked ? list.map((r) => r.id) : [])}
        />
      ),
      width: 48,
      align: 'center' as const,
      render: (_: unknown, row: Row) => (
        <Checkbox
          checked={selected.includes(row.id)}
          onChange={(e) => {
            setSelected((prev) => (e.target.checked ? [...prev, row.id] : prev.filter((id) => id !== row.id)))
          }}
        />
      ) },
    { title: '구분', dataIndex: 'action', width: 180 },
    { title: '내용', dataIndex: 'content', ellipsis: true },
    { title: '직원', dataIndex: 'staff', width: 100 },
    { title: '처리일', dataIndex: 'processedAt', width: 160 },
  ]

  return (
    <div className={`stock-page product-log-page${domain === 'PENDING' ? ' pending-log-page' : ''}`}>
      <div className="stock-title">
        <div>
          <h2>
            {titleIcon ?? <EditOutlined className="product-title-icon" />}
            {title}
          </h2>
          <p>{description}</p>
        </div>
        <Space className="stock-title-actions" wrap>
          <Button
            disabled={!selected.length}
            loading={remove.isPending}
            onClick={() => {
              if (!selected.length) {
                message.warning('삭제할 이력을 선택하세요.')
                return
              }
              Modal.confirm({
                title: '이력 삭제',
                content: `선택한 ${selected.length}건의 이력을 삭제하시겠습니까?`,
                onOk: () => remove.mutateAsync(selected) })
            }}
          >
            삭제
          </Button>
        </Space>
      </div>

      <Card className="stock-filter-card" size="small">
        <Form form={form} layout="inline" className="home-filter" initialValues={{ size: 10 }} onFinish={onSearch}>
          <div className="stock-filter-row">
            <Form.Item name="action">
              <Select allowClear placeholder="구분" className="w-170" options={actionOptions} />
            </Form.Item>
            <Form.Item name="staff">
              <Select allowClear placeholder="직원" className="w-130" options={staffOptions} />
            </Form.Item>
            <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={clearDates} />
            <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((prev) => ({ ...prev, size, page: 0 }))
                }}
              />
            </Form.Item>
          </div>
        </Form>
      </Card>

      <Card className="stock-table-card" size="small">
        <div className="recovery-table-head">
          <Typography.Text>목록 <b>{query.data?.total ?? 0}</b></Typography.Text>
          <Button type="link" icon={<DownloadOutlined />} onClick={download}>엑셀다운로드</Button>
        </div>
        <CareTable
          rowKey="id"
          size="small"
          loading={query.isLoading}
          dataSource={list}
          columns={columns}
          scroll={{ x: 900 }}
          pagination={{
            current: Number(filters.page || 0) + 1,
            pageSize: Number(filters.size || 10),
            total: query.data?.total || 0,
            showSizeChanger: false,
            onChange: (page) => {
              setSelected([])
              setFilters((prev) => ({ ...prev, page: page - 1 }))
            } }}
          locale={{ emptyText: '등록되어 있는 자료가 없습니다.' }}
        />
      </Card>
    </div>
  )
}
