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

const { RangePicker } = DatePicker
const STATUS_TABS = [
  { key: 'ALL', label: '전체' },
  { key: '접수', label: '접수' },
  { key: '신청', label: '신청' },
  { key: '완료', label: '완료' },
  { key: '철회', label: '철회' },
]
const SEARCH_TYPES = ['고객명', '거래처', '직원', '연락처', '가입상품']

type ContractPage = {
  total: number
  list: Row[]
  counts?: Record<string, number>
  agencies?: string[]
  employees?: string[]
}

function maskName(v: unknown) {
  const s = String(v ?? '')
  if (s.length <= 1) return s
  if (s.length === 2) return `${s[0]}*`
  return `${s[0]}${'*'.repeat(s.length - 2)}${s[s.length - 1]}`
}

function maskPhone(v: unknown) {
  const digits = String(v ?? '').replace(/\D/g, '')
  if (digits.length < 7) return String(v ?? '')
  return `${digits.slice(0, 3)}-****-${digits.slice(-4)}`
}

function moneyMargin(v: unknown) {
  if (v == null || v === '') return '-'
  const n = Number(v)
  return <span className={n < 0 ? 'contract-margin-neg' : 'contract-margin'}>{n.toLocaleString()}</span>
}

function statusClass(v: string) {
  if (v === '철회') return 'contract-status-cancel'
  if (v === '신청') return 'contract-status-apply'
  if (v === '접수') return 'contract-status-recv'
  return undefined
}

type Props = {
  kind: 'INTERNET' | 'HOME'
  title: string
  description: string
  createLabel: string
  writeType: 'internet' | 'home'
}

export function ContractListPage({ kind, title, description, createLabel, writeType }: Props) {
  const navigate = useNavigate()
  const qc = useQueryClient()
  const [form] = Form.useForm()
  const [statusForm] = Form.useForm()
  const [selected, setSelected] = useState<number[]>([])
  const [statusOpen, setStatusOpen] = useState(false)
  const [sumOpen, setSumOpen] = useState(false)
  const [filters, setFilters] = useState<Record<string, unknown>>({
    kind,
    status: 'ALL',
    page: 0,
    size: 10 })

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

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

  const changeStatus = useMutation({
    mutationFn: async (values: { status: string }) => {
      const { data } = await client.post(`${apiPrefix()}/homes/contracts/status`, { ids: selected, status: values.status })
      return unwrap(data)
    },
    onSuccess: () => {
      message.success('상태를 변경했습니다.')
      setStatusOpen(false)
      setSelected([])
      qc.invalidateQueries({ queryKey: ['homes/contracts'] })
    },
    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({
      kind,
      status: filters.status || 'ALL',
      agency: values.agency || undefined,
      employee: values.employee || undefined,
      searchType: values.searchType || '고객명',
      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 })
  }

  const reset = () => {
    form.resetFields()
    form.setFieldsValue({ searchType: '고객명', size: 10 })
    setSelected([])
    setFilters({ kind, status: 'ALL', 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.status, r.contractDate, r.customerName, r.phone, r.products, r.policySum, r.settleAmount, r.margin, r.agency, r.employee]
        .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 list = query.data?.list || []
  const counts = query.data?.counts
  const agencyOptions = useMemo(
    () => (query.data?.agencies || []).map((v) => ({ value: v, label: v })),
    [query.data?.agencies],
  )
  const employeeOptions = useMemo(
    () => (query.data?.employees || []).map((v) => ({ value: v, label: v })),
    [query.data?.employees],
  )

  const selectedSums = useMemo(() => {
    const rows = selected.length ? list.filter((r) => selected.includes(r.id)) : list
    return {
      settle: rows.reduce((s, r) => s + Number(r.settleAmount || 0), 0),
      margin: rows.reduce((s, r) => s + Number(r.margin || 0), 0),
      count: rows.length }
  }, [list, selected])

  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: 'status',
      width: 70,
      render: (v: string) => <span className={statusClass(v)}>{v}</span> },
    { title: '계약일', dataIndex: 'contractDate', width: 100 },
    { title: '고객명', dataIndex: 'customerName', width: 90, render: maskName },
    { title: '연락처', dataIndex: 'phone', width: 130, render: maskPhone },
    { title: '가입상품', dataIndex: 'products', width: 180, ellipsis: true },
    { title: '정책합산', dataIndex: 'policySum', width: 110, align: 'right' as const, render: money },
    { title: '정산금액', dataIndex: 'settleAmount', width: 110, align: 'right' as const, render: money },
    { title: '판매마진', dataIndex: 'margin', width: 110, align: 'right' as const, render: moneyMargin },
    { title: '거래처', dataIndex: 'agency', width: 120, ellipsis: true },
    { title: '직원(하부점)', dataIndex: 'employee', width: 110 },
    {
      title: '관리',
      width: 64,
      align: 'center' as const,
      render: (_: unknown, row: Row) => (
        <Button
          type="primary"
          size="small"
          className="product-manage-btn"
          icon={<FormOutlined />}
          onClick={() => navigate(`/care/contract/write?type=${writeType}&id=${row.id}`)}
        />
      ) },
  ]

  return (
    <div className="stock-page contract-internet-page">
      <div className="stock-title">
        <div>
          <h2>
            <EditOutlined className="product-title-icon" />
            {title}
          </h2>
          <p>{description}</p>
        </div>
        <Space className="stock-title-actions" wrap>
          <Button
            disabled={!selected.length}
            onClick={() => {
              if (!selected.length) {
                message.warning('계약을 선택하세요.')
                return
              }
              statusForm.setFieldsValue({ status: '완료' })
              setStatusOpen(true)
            }}
          >
            상태
          </Button>
          <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>
          <Button icon={<SearchOutlined />} onClick={() => setSumOpen(true)}>정산/마진합계</Button>
          <Button type="primary" icon={<PlusSquareOutlined />} onClick={() => navigate(`/care/contract/write?type=${writeType}`)}>
            {createLabel}
          </Button>
        </Space>
      </div>

      <Card className="stock-filter-card" size="small">
        <Form form={form} layout="inline" className="home-filter" initialValues={{ searchType: '고객명', 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={clearDates} />
          </div>
          <div className="stock-filter-row">
            <Form.Item name="agency">
              <Select allowClear placeholder="거래처" className="w-130" options={agencyOptions} />
            </Form.Item>
            <Form.Item name="employee">
              <Select allowClear placeholder="직원" className="w-130" options={employeeOptions} />
            </Form.Item>
            <Form.Item name="searchType">
              <Select className="w-110" options={SEARCH_TYPES.map((v) => ({ value: v, label: v }))} />
            </Form.Item>
            <Form.Item name="q">
              <Input allowClear placeholder="검색어" className="w-150" />
            </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((prev) => ({ ...prev, size, page: 0 }))
                }}
              />
            </Form.Item>
          </div>
        </Form>
      </Card>

      <Card className="stock-table-card product-internet-card" size="small">
        <div className="product-internet-tabs">
          <Tabs
            activeKey={String(filters.status || 'ALL')}
            onChange={(key) => {
              setSelected([])
              setFilters((prev) => ({ ...prev, status: key, page: 0 }))
            }}
            items={STATUS_TABS.map((t) => ({
              key: t.key,
              label: counts?.[t.key] != null ? `${t.label} ${counts[t.key]}` : t.label }))}
          />
          <div className="product-internet-settings">
            <Button type="link" icon={<DownloadOutlined />} onClick={download}>엑셀다운로드</Button>
          </div>
        </div>

        <CareTable
          rowKey="id"
          size="small"
          loading={query.isLoading}
          dataSource={list}
          columns={columns}
          scroll={{ x: 1300 }}
          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>

      <Modal title="상태 변경" open={statusOpen} onCancel={() => setStatusOpen(false)} footer={null} destroyOnHidden width={360}>
        <Form form={statusForm} layout="vertical" onFinish={(v) => changeStatus.mutate(v)}>
          <Form.Item name="status" label="상태" rules={[{ required: true }]}>
            <Select options={['접수', '신청', '완료', '철회'].map((v) => ({ value: v, label: v }))} />
          </Form.Item>
          <div className="product-modal-footer-right">
            <Button type="primary" htmlType="submit" loading={changeStatus.isPending}>변경합니다</Button>
            <Button onClick={() => setStatusOpen(false)}>취소</Button>
          </div>
        </Form>
      </Modal>

      <Modal title="정산/마진합계" open={sumOpen} onCancel={() => setSumOpen(false)} footer={null} destroyOnHidden width={400}>
        <Typography.Paragraph type="secondary">
          {selected.length ? `선택 ${selectedSums.count}건` : `현재 목록 ${selectedSums.count}건`} 기준입니다.
        </Typography.Paragraph>
        <div className="contract-sum-box">
          <div><span>정산금액 합계</span><b>{selectedSums.settle.toLocaleString()}원</b></div>
          <div>
            <span>판매마진 합계</span>
            <b className={selectedSums.margin < 0 ? 'contract-margin-neg' : 'contract-margin'}>
              {selectedSums.margin.toLocaleString()}원
            </b>
          </div>
        </div>
        <div className="product-modal-footer-right" style={{ marginTop: 16 }}>
          <Button onClick={() => setSumOpen(false)}>닫기</Button>
        </div>
      </Modal>
    </div>
  )
}
