import { useEffect, useMemo, useState } from 'react'
import { useMutation, useQuery } from '@tanstack/react-query'
import dayjs, { type Dayjs } from 'dayjs'
import { Table, Button, Card, DatePicker, Form, InputNumber, Select, Space, Typography, message } from 'antd'
import CareTable from '../../components/CareTable'
import { RadarChartOutlined, SearchOutlined } from '@ant-design/icons'
import client, { apiPrefix, unwrap, type ApiResponse } from '../../api/client'
import { money, options } from './homesShared'

const { RangePicker } = DatePicker

type AdjustRow = {
  id: number
  kind?: string
  status?: string
  contractDate?: string
  customerName?: string
  phone?: string
  products?: string
  months?: number
  agency?: string
  employee?: string
  policySum?: number
  settleAmount?: number
  margin?: number
}

type AdjustResult = {
  total: number
  list: AdjustRow[]
  employees?: string[]
  products?: string[]
}

const KIND_OPTIONS = [
  { value: 'INTERNET', label: '인터넷' },
  { value: 'HOME', label: '홈렌탈' },
]
const CATEGORY_OPTIONS = ['인터넷', 'TV', '전화', '와이파이', '스마트홈', '정수기', '공기청정기', '비데', '매트리스', '가전', '기타']
const MONTH_OPTIONS = [
  { value: '12', label: '12개월' },
  { value: '24', label: '24개월' },
  { value: '36', label: '36개월' },
  { value: '48', label: '48개월' },
  { value: '60', label: '60개월' },
]
const STATUS_OPTIONS = ['접수', '신청', '완료', '철회']

export default function ContractAdjustPage() {
  const [form] = Form.useForm()
  const [searched, setSearched] = useState(false)
  const [filters, setFilters] = useState<Record<string, unknown>>({})
  const [rows, setRows] = useState<AdjustRow[]>([])
  const [batch, setBatch] = useState({
    policySum: undefined as number | undefined,
    settleAmount: undefined as number | undefined,
    margin: undefined as number | undefined })

  const enabled = searched && !!filters.dateFrom && !!filters.dateTo
  const optionParams = useMemo(() => ({
    dateFrom: dayjs().startOf('month').format('YYYY-MM-DD'),
    dateTo: dayjs().format('YYYY-MM-DD') }), [])
  const optionsQuery = useQuery({
    queryKey: ['homes-contract-adjust-options', optionParams],
    queryFn: async () => {
      const { data } = await client.get<ApiResponse<AdjustResult>>(`${apiPrefix()}/homes/contracts/adjust`, { params: optionParams })
      return unwrap(data)
    } })
  const query = useQuery({
    queryKey: ['homes-contract-adjust', filters],
    queryFn: async () => {
      const { data } = await client.get<ApiResponse<AdjustResult>>(`${apiPrefix()}/homes/contracts/adjust`, { params: filters })
      return unwrap(data)
    },
    enabled })

  useEffect(() => {
    if (!query.data?.list) return
    setRows(query.data.list.map((row) => ({
      ...row,
      policySum: Number(row.policySum ?? 0),
      settleAmount: Number(row.settleAmount ?? 0),
      margin: Number(row.margin ?? 0) })))
  }, [query.data])

  const setPreset = (from: Dayjs, to: Dayjs) => {
    if (to.diff(from, 'day') > 30) {
      message.warning('최대 31일까지 조회할 수 있습니다.')
      return
    }
    form.setFieldsValue({ dates: [from, to] })
  }

  const onSearch = (values: Record<string, unknown>) => {
    const dates = values.dates as [Dayjs, Dayjs] | undefined
    if (!dates?.[0] || !dates?.[1]) {
      message.warning('계약일을 선택하세요.')
      return
    }
    if (dates[1].diff(dates[0], 'day') > 30) {
      message.warning('최대 31일까지 조회할 수 있습니다.')
      return
    }
    setSearched(true)
    setFilters({
      dateFrom: dates[0].format('YYYY-MM-DD'),
      dateTo: dates[1].format('YYYY-MM-DD'),
      kind: values.kind || undefined,
      category: values.category || undefined,
      product: values.product || undefined,
      months: values.months || undefined,
      status: values.status || undefined,
      employee: values.employee || undefined })
  }

  const updateRow = (id: number, field: 'policySum' | 'settleAmount' | 'margin', value: number | null) => {
    setRows((prev) => prev.map((row) => (row.id === id ? { ...row, [field]: value ?? 0 } : row)))
  }

  const applyBatch = (field: 'policySum' | 'settleAmount' | 'margin') => {
    const value = batch[field]
    if (value == null) {
      message.warning('금액을 입력하세요.')
      return
    }
    setRows((prev) => prev.map((row) => ({ ...row, [field]: value })))
    message.success('일괄 입력했습니다.')
  }

  const saveOne = useMutation({
    mutationFn: async (row: AdjustRow) => {
      const { data } = await client.put(`${apiPrefix()}/homes/contracts/${row.id}`, {
        policySum: row.policySum,
        settleAmount: row.settleAmount,
        margin: row.margin })
      return unwrap(data as ApiResponse)
    },
    onSuccess: () => message.success('변경했습니다.'),
    onError: (e: Error) => message.error(e.message) })

  const saveAll = useMutation({
    mutationFn: async () => {
      const { data } = await client.post(`${apiPrefix()}/homes/contracts/adjust/batch`, {
        items: rows.map((row) => ({
          id: row.id,
          policySum: row.policySum,
          settleAmount: row.settleAmount,
          margin: row.margin })) })
      return unwrap(data as ApiResponse<{ updated: number }>)
    },
    onSuccess: (data) => message.success(`${data.updated}건을 변경했습니다.`),
    onError: (e: Error) => message.error(e.message) })

  const employeeOptions = useMemo(() => {
    const fromApi = [...(optionsQuery.data?.employees || []), ...(query.data?.employees || [])]
    const fromRows = rows.map((r) => r.employee).filter(Boolean) as string[]
    return Array.from(new Set([...fromApi, ...fromRows]))
  }, [optionsQuery.data?.employees, query.data?.employees, rows])

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

  const columns = [
    {
      title: '종류',
      dataIndex: 'kind',
      width: 80,
      render: (v: string) => (v === 'HOME' ? '홈렌탈' : '인터넷') },
    { title: '상태', dataIndex: 'status', width: 70 },
    { title: '계약일', dataIndex: 'contractDate', width: 100 },
    { title: '고객명', dataIndex: 'customerName', width: 90 },
    { title: '가입상품', dataIndex: 'products', width: 180, ellipsis: true },
    {
      title: '약정',
      dataIndex: 'months',
      width: 80,
      render: (v: number) => (v ? `${v}개월` : '-') },
    { title: '거래처', dataIndex: 'agency', width: 110, ellipsis: true },
    { title: '직원', dataIndex: 'employee', width: 90 },
    {
      title: '정책합산',
      dataIndex: 'policySum',
      width: 120,
      render: (_: unknown, row: AdjustRow) => (
        <InputNumber
          className="adjust-cell-input"
          controls={false}
          value={row.policySum}
          onChange={(v) => updateRow(row.id, 'policySum', v)}
        />
      ) },
    {
      title: '정산금액',
      dataIndex: 'settleAmount',
      width: 120,
      render: (_: unknown, row: AdjustRow) => (
        <InputNumber
          className="adjust-cell-input"
          controls={false}
          value={row.settleAmount}
          onChange={(v) => updateRow(row.id, 'settleAmount', v)}
        />
      ) },
    {
      title: '판매마진',
      dataIndex: 'margin',
      width: 120,
      render: (_: unknown, row: AdjustRow) => (
        <InputNumber
          className="adjust-cell-input"
          controls={false}
          value={row.margin}
          onChange={(v) => updateRow(row.id, 'margin', v)}
        />
      ) },
    {
      title: '개별',
      width: 70,
      fixed: 'right' as const,
      render: (_: unknown, row: AdjustRow) => (
        <Button size="small" onClick={() => saveOne.mutate(row)} loading={saveOne.isPending}>변경</Button>
      ) },
  ]

  return (
    <div className="stock-page adjust-page">
      <div className="stock-title">
        <div>
          <h2>
            <RadarChartOutlined className="product-title-icon" />
            일괄정책변경
          </h2>
          <p>등록된 계약정보에 일괄적으로 기본정책금액을 변경하실 수 있습니다. (단일상품의 수량이 2개 이상인 경우 제외됩니다.)</p>
        </div>
      </div>

      <Card className="stock-filter-card adjust-filter-card" size="small">
        <Form
          form={form}
          layout="horizontal"
          initialValues={{
            dates: [dayjs().startOf('month'), dayjs()] }}
          onFinish={onSearch}
        >
          <div className="adjust-filter-row adjust-date-row">
            <span className="adjust-label">계약일</span>
            <Form.Item name="dates" noStyle>
              <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>
            <Typography.Text type="danger" className="adjust-hint">* 최대 31일 조회</Typography.Text>
            <Button className="adjust-search-btn" type="primary" htmlType="submit" icon={<SearchOutlined />}>
              계약정보 검색
            </Button>
          </div>

          <div className="adjust-filter-row">
            <span className="adjust-label">검색조건</span>
            <Form.Item name="kind" noStyle>
              <Select allowClear placeholder="-종류-" className="w-110" options={KIND_OPTIONS} />
            </Form.Item>
            <Form.Item name="category" noStyle>
              <Select allowClear placeholder="-구분-" className="w-110" options={options(CATEGORY_OPTIONS)} />
            </Form.Item>
            <Form.Item name="product" noStyle>
              <Select
                allowClear
                showSearch
                placeholder="-상품-"
                className="w-150"
                options={productOptions.length ? productOptions : undefined}
                optionFilterProp="label"
              />
            </Form.Item>
            <Form.Item name="months" noStyle>
              <Select allowClear placeholder="-약정-" className="w-110" options={MONTH_OPTIONS} />
            </Form.Item>
            <Form.Item name="status" noStyle>
              <Select allowClear placeholder="-상태-" className="w-110" options={options(STATUS_OPTIONS)} />
            </Form.Item>
            <Form.Item name="employee" noStyle>
              <Select allowClear placeholder="-직원-" className="w-120" options={options(employeeOptions)} />
            </Form.Item>
          </div>
        </Form>
      </Card>

      {enabled && (
        <Card className="stock-table-card adjust-result-card" size="small">
          <div className="adjust-result-head">
            <Typography.Text>검색된 계약 <b>{query.data?.total ?? rows.length}</b> 건</Typography.Text>
          </div>

          <div className="adjust-batch-bar">
            <span className="adjust-batch-guide">원하시는 금액을 입력 후 엔터키를 눌러주세요.</span>
            <Space wrap size={12}>
              <Space.Compact className="adjust-batch-compact">
                <InputNumber
                  className="adjust-batch-input"
                  controls={false}
                  placeholder="정책합산"
                  value={batch.policySum}
                  onChange={(v) => setBatch((s) => ({ ...s, policySum: v ?? undefined }))}
                  onPressEnter={() => applyBatch('policySum')}
                />
                <Button className="adjust-batch-btn" type="primary" onClick={() => applyBatch('policySum')}>
                  일괄입력
                </Button>
              </Space.Compact>
              <Space.Compact className="adjust-batch-compact">
                <InputNumber
                  className="adjust-batch-input"
                  controls={false}
                  placeholder="정산금액"
                  value={batch.settleAmount}
                  onChange={(v) => setBatch((s) => ({ ...s, settleAmount: v ?? undefined }))}
                  onPressEnter={() => applyBatch('settleAmount')}
                />
                <Button className="adjust-batch-btn" type="primary" onClick={() => applyBatch('settleAmount')}>
                  일괄입력
                </Button>
              </Space.Compact>
              <Space.Compact className="adjust-batch-compact">
                <InputNumber
                  className="adjust-batch-input"
                  controls={false}
                  placeholder="판매마진"
                  value={batch.margin}
                  onChange={(v) => setBatch((s) => ({ ...s, margin: v ?? undefined }))}
                  onPressEnter={() => applyBatch('margin')}
                />
                <Button className="adjust-batch-btn" type="primary" onClick={() => applyBatch('margin')}>
                  일괄입력
                </Button>
              </Space.Compact>
            </Space>
          </div>

          <CareTable
            rowKey="id"
            size="small"
            loading={query.isLoading}
            dataSource={rows}
            columns={columns}
            pagination={false}
            scroll={{ x: 1400 }}
            locale={{ emptyText: '검색된 계약이 없습니다.' }}
            summary={() => (
              <Table.Summary.Row>
                <Table.Summary.Cell index={0} colSpan={8}>합계</Table.Summary.Cell>
                <Table.Summary.Cell index={1} align="right">
                  {money(rows.reduce((s, r) => s + Number(r.policySum || 0), 0))}
                </Table.Summary.Cell>
                <Table.Summary.Cell index={2} align="right">
                  {money(rows.reduce((s, r) => s + Number(r.settleAmount || 0), 0))}
                </Table.Summary.Cell>
                <Table.Summary.Cell index={3} align="right">
                  {money(rows.reduce((s, r) => s + Number(r.margin || 0), 0))}
                </Table.Summary.Cell>
                <Table.Summary.Cell index={4} />
              </Table.Summary.Row>
            )}
          />

          <div className="adjust-submit">
            <Button
              className="adjust-submit-btn"
              type="primary"
              size="large"
              loading={saveAll.isPending}
              disabled={!rows.length}
              onClick={() => saveAll.mutate()}
            >
              상기 입력된 값으로 모두 변경합니다.
            </Button>
          </div>
        </Card>
      )}
    </div>
  )
}
