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

const { RangePicker } = DatePicker
const sortFields = ['종류', '모델명', '요금제', '개통일', '출고처', '지원방법', '고객명', '통신사']
const defaultSorts = ['종류', '모델명', '요금제', '개통일', '출고처', '지원방법', '고객명']
const options = (values: string[]) => values.map((value) => ({ value, label: value }))
const money = (v: unknown) => (v == null || v === '' ? '0' : Number(v).toLocaleString())

type AdjustRow = {
  id: number
  opendate?: string
  incompanyName?: string
  outcompanyName?: string
  name?: string
  openhow?: string
  pmodel?: string
  pserial?: string
  decltype?: string
  plan?: string
  sellprice?: number
  basicprice1?: number
  basicprice2?: number
  basicprice3?: number
}

export default function OpenAdjustPage() {
  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({ basicprice1: undefined as number | undefined, basicprice2: undefined as number | undefined, basicprice3: undefined as number | undefined })

  const companies = useQuery({ queryKey: ['adjust-companies'], queryFn: () => resourceApi.list('companies', { size: 200 }) })
  const inOptions = useMemo(
    () => (companies.data?.items ?? []).filter((c) => String(c.type) === 'IN').map((c) => ({ value: c.id, label: String(c.name) })),
    [companies.data],
  )
  const outOptions = useMemo(
    () => (companies.data?.items ?? []).filter((c) => ['SHOP', 'DEALER', 'OUT'].includes(String(c.type))).map((c) => ({ value: c.id, label: String(c.name) })),
    [companies.data],
  )

  const enabled = searched && !!filters.dateFrom && !!filters.dateTo
  const query = useQuery({
    queryKey: ['open-adjust', filters],
    queryFn: async () => {
      const { data } = await client.get<ApiResponse<{ total: number; list: AdjustRow[] }>>(`${apiPrefix()}/opens/adjust`, { params: filters })
      return unwrap(data)
    },
    enabled })

  useEffect(() => {
    if (query.data?.list) {
      setRows(query.data.list.map((row) => ({
        ...row,
        basicprice1: Number(row.basicprice1 ?? 0),
        basicprice2: Number(row.basicprice2 ?? 0),
        basicprice3: Number(row.basicprice3 ?? 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
    }
    const next: Record<string, unknown> = {
      dateFrom: dates[0].format('YYYY-MM-DD'),
      dateTo: dates[1].format('YYYY-MM-DD'),
      openhow: values.openhow,
      telecom: values.telecom,
      incompanyId: values.incompanyId,
      outcompanyId: values.outcompanyId,
      salesperson: values.salesperson,
      model: values.model,
      plan: values.plan }
    for (let i = 1; i <= 7; i++) next[`sort${i}`] = values[`sort${i}`]
    setSearched(true)
    setFilters(next)
  }

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

  const applyBatch = (field: 'basicprice1' | 'basicprice2' | 'basicprice3') => {
    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()}/opens/${row.id}`, {
        basicprice1: row.basicprice1,
        basicprice2: row.basicprice2,
        basicprice3: row.basicprice3 })
      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()}/opens/adjust/batch`, {
        items: rows.map((row) => ({
          id: row.id,
          basicprice1: row.basicprice1,
          basicprice2: row.basicprice2,
          basicprice3: row.basicprice3 })) })
      return unwrap(data as ApiResponse<{ updated: number }>)
    },
    onSuccess: (data) => message.success(`${data.updated}건을 변경했습니다.`),
    onError: (e: Error) => message.error(e.message) })

  const download = async () => {
    if (!filters.dateFrom || !filters.dateTo) {
      message.warning('개통일을 선택하세요.')
      return
    }
    const { data } = await client.get(`${apiPrefix()}/opens/adjust/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)
  }

  const columns = [
    { title: '개통일', dataIndex: 'opendate', width: 100 },
    { title: '입고처', dataIndex: 'incompanyName', width: 100, ellipsis: true },
    { title: '출고처', dataIndex: 'outcompanyName', width: 100, ellipsis: true },
    { title: '고객명', dataIndex: 'name', width: 80 },
    { title: '종류', dataIndex: 'openhow', width: 70 },
    { title: '모델명', dataIndex: 'pmodel', width: 140, ellipsis: true },
    { title: '일련번호', dataIndex: 'pserial', width: 110, ellipsis: true },
    { title: '지원방법', dataIndex: 'decltype', width: 90, render: (v: string) => v || '-' },
    { title: '요금제', dataIndex: 'plan', width: 110, ellipsis: true },
    { title: '정산금액', dataIndex: 'sellprice', width: 90, align: 'right' as const, render: money },
    {
      title: '기본정책',
      dataIndex: 'basicprice1',
      width: 110,
      render: (_: unknown, row: AdjustRow) => (
        <InputNumber
          className="adjust-cell-input"
          controls={false}
          value={row.basicprice1}
          onChange={(v) => updateRow(row.id, 'basicprice1', v)}
        />
      ) },
    {
      title: '구두정책',
      dataIndex: 'basicprice2',
      width: 110,
      render: (_: unknown, row: AdjustRow) => (
        <InputNumber
          className="adjust-cell-input"
          controls={false}
          value={row.basicprice2}
          onChange={(v) => updateRow(row.id, 'basicprice2', v)}
        />
      ) },
    {
      title: '추가정책',
      dataIndex: 'basicprice3',
      width: 110,
      render: (_: unknown, row: AdjustRow) => (
        <InputNumber
          className="adjust-cell-input"
          controls={false}
          value={row.basicprice3}
          onChange={(v) => updateRow(row.id, 'basicprice3', 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>일괄개통정산</h2>
          <p>등록된 개통정보에 일괄적으로 정책금액(정산)을 변경하실 수 있습니다. (유심개통 제외)</p>
        </div>
      </div>

      <Card className="stock-filter-card adjust-filter-card" size="small">
        <Form
          form={form}
          layout="horizontal"
          labelCol={{ flex: '80px' }}
          initialValues={{
            sort1: '종류', sort2: '모델명', sort3: '요금제', sort4: '개통일',
            sort5: '출고처', sort6: '지원방법', sort7: '고객명' }}
          onFinish={onSearch}
        >
          <div className="adjust-filter-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>
          </div>

          <div className="adjust-filter-row">
            <span className="adjust-label">검색조건</span>
            <Form.Item name="openhow" noStyle>
              <Select allowClear placeholder="-종류-" className="w-110" options={options(['신규', '번호이동', '보상', '기변', '메이징', '가개통', '선불개통'])} />
            </Form.Item>
            <Form.Item name="telecom" noStyle>
              <Select allowClear placeholder="-통신사-" className="w-110" options={options(['SKT', 'KT', 'LGU+'])} />
            </Form.Item>
            <Form.Item name="incompanyId" noStyle>
              <Select allowClear placeholder="-입고처-" className="w-130" options={inOptions} />
            </Form.Item>
            <Form.Item name="outcompanyId" noStyle>
              <Select allowClear placeholder="-출고처-" className="w-130" options={outOptions} />
            </Form.Item>
            <Form.Item name="salesperson" noStyle>
              <Select allowClear placeholder="-영업사원-" className="w-120" options={options(['김영업', '이영업'])} />
            </Form.Item>
            <Form.Item name="model" noStyle>
              <Input placeholder="-모델명-" className="w-130" allowClear />
            </Form.Item>
            <Form.Item name="plan" noStyle>
              <Input placeholder="-요금제-" className="w-130" allowClear />
            </Form.Item>
          </div>

          <div className="adjust-filter-row adjust-sort-row">
            <span className="adjust-label">정렬순서</span>
            {defaultSorts.map((_, index) => (
              <span key={index} className="adjust-sort-item">
                {index > 0 && <RightOutlined className="adjust-sort-arrow" />}
                <Form.Item name={`sort${index + 1}`} noStyle>
                  <Select className="w-110" options={sortFields.map((v) => ({ value: v, label: v }))} />
                </Form.Item>
              </span>
            ))}
          </div>

          <div className="adjust-search-action">
            <Button type="primary" htmlType="submit" icon={<SearchOutlined />} size="large">개통정보 검색</Button>
          </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>
            <Space>
              <Button type="link" icon={<DownloadOutlined />} onClick={download}>엑셀다운로드</Button>
              <Button type="link" disabled>엑셀대량처리</Button>
            </Space>
          </div>

          <div className="adjust-batch-bar">
            <span className="adjust-batch-guide">원하시는 금액을 입력 후 엔터키를 눌러주세요.</span>
            <Space>
              <InputNumber
                className="adjust-batch-input"
                controls={false}
                placeholder="기본정책"
                value={batch.basicprice1}
                onChange={(v) => setBatch((s) => ({ ...s, basicprice1: v ?? undefined }))}
                onPressEnter={() => applyBatch('basicprice1')}
                addonAfter={<Button size="small" type="link" onClick={() => applyBatch('basicprice1')}>일괄입력</Button>}
              />
              <InputNumber
                className="adjust-batch-input"
                controls={false}
                placeholder="구두정책"
                value={batch.basicprice2}
                onChange={(v) => setBatch((s) => ({ ...s, basicprice2: v ?? undefined }))}
                onPressEnter={() => applyBatch('basicprice2')}
                addonAfter={<Button size="small" type="link" onClick={() => applyBatch('basicprice2')}>일괄입력</Button>}
              />
              <InputNumber
                className="adjust-batch-input"
                controls={false}
                placeholder="추가정책"
                value={batch.basicprice3}
                onChange={(v) => setBatch((s) => ({ ...s, basicprice3: v ?? undefined }))}
                onPressEnter={() => applyBatch('basicprice3')}
                addonAfter={<Button size="small" type="link" onClick={() => applyBatch('basicprice3')}>일괄입력</Button>}
              />
            </Space>
          </div>

          <CareTable
            rowKey="id"
            size="small"
            loading={query.isLoading}
            dataSource={rows}
            columns={columns}
            pagination={false}
            scroll={{ x: 1500 }}
          />

          <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>
  )
}
