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

const { RangePicker } = DatePicker
const { TextArea } = Input

type SmsRow = {
  id: number
  sentAt?: string
  msgType?: string
  sendCount?: number
  deductCount?: number
  phone?: string
  message?: string
  senderNumber?: string
  senderName?: string
}

type SmsData = {
  total: number
  list: SmsRow[]
  balance?: number
}

const defaultRange = (): [Dayjs, Dayjs] => [dayjs().subtract(1, 'month').startOf('month'), dayjs()]

const smsBytes = (text: string) => {
  let bytes = 0
  for (let i = 0; i < text.length; i += 1) {
    bytes += text.charCodeAt(i) <= 0x7f ? 1 : 2
  }
  return bytes
}

export default function SmsHistoryPage() {
  const qc = useQueryClient()
  const [form] = Form.useForm()
  const [open, setOpen] = useState(false)
  const [selected, setSelected] = useState<number[]>([])
  const [phoneInput, setPhoneInput] = useState('')
  const [phones, setPhones] = useState<string[]>([])
  const [content, setContent] = useState('')
  const [filters, setFilters] = useState<Record<string, unknown>>(() => {
    const [from, to] = defaultRange()
    return {
      dateFrom: from.format('YYYY-MM-DD'),
      dateTo: to.format('YYYY-MM-DD'),
      searchType: '수신번호',
      page: 0,
      size: 15 }
  })

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

  const balanceQuery = useQuery({
    queryKey: ['sms-balance'],
    queryFn: async () => {
      const { data } = await client.get<ApiResponse<{ balance: number; senderNumber: string }>>(`${apiPrefix()}/sms/balance`)
      return unwrap(data)
    } })

  const balance = balanceQuery.data?.balance ?? query.data?.balance ?? 996
  const senderNumber = balanceQuery.data?.senderNumber ?? '1600-3903'
  const bytes = smsBytes(content)
  const msgType = bytes <= 90 ? '단문' : '장문'
  const perDeduct = bytes <= 90 ? 1 : Math.max(3, Math.ceil(bytes / 90))
  const deduct = phones.length === 0 ? 0 : perDeduct * phones.length

  const sendMut = useMutation({
    mutationFn: async () => {
      const { data } = await client.post(`${apiPrefix()}/sms/send`, {
        phones,
        message: content,
        senderNumber })
      return unwrap(data)
    },
    onSuccess: () => {
      message.success('문자를 발송했습니다.')
      setOpen(false)
      setPhones([])
      setPhoneInput('')
      setContent('')
      qc.invalidateQueries({ queryKey: ['sms-history'] })
      qc.invalidateQueries({ queryKey: ['sms-balance'] })
    },
    onError: (e: Error) => message.error(e.message || '발송에 실패했습니다.') })

  const deleteMut = useMutation({
    mutationFn: async (ids: number[]) => {
      const { data } = await client.post(`${apiPrefix()}/sms/history/delete`, { ids })
      return unwrap(data)
    },
    onSuccess: () => {
      message.success('삭제했습니다.')
      setSelected([])
      qc.invalidateQueries({ queryKey: ['sms-history'] })
    },
    onError: () => message.error('삭제에 실패했습니다.') })

  const chargeMut = useMutation({
    mutationFn: async () => {
      const { data } = await client.post(`${apiPrefix()}/sms/charge`, { amount: 100 })
      return unwrap(data) as { balance: number }
    },
    onSuccess: (data) => {
      message.success('SMS가 충전되었습니다.')
      qc.setQueryData(['sms-balance'], (prev: { balance: number; senderNumber: string } | undefined) => ({
        balance: data.balance,
        senderNumber: prev?.senderNumber ?? senderNumber }))
      qc.invalidateQueries({ queryKey: ['sms-balance'] })
    } })

  const onSearch = (values: Record<string, unknown>) => {
    const dates = values.dates as [Dayjs, Dayjs] | undefined
    if (!dates?.[0] || !dates?.[1]) {
      message.warning('날짜를 선택하세요.')
      return
    }
    setFilters((prev) => ({
      ...prev,
      dateFrom: dates[0].format('YYYY-MM-DD'),
      dateTo: dates[1].format('YYYY-MM-DD'),
      searchType: values.searchType || '수신번호',
      keyword: values.keyword,
      page: 0,
      size: Number(values.size ?? prev.size ?? 15) }))
  }

  const onReset = () => {
    const [from, to] = defaultRange()
    form.setFieldsValue({
      dates: [from, to],
      searchType: '수신번호',
      keyword: undefined,
      size: 15 })
    setFilters({
      dateFrom: from.format('YYYY-MM-DD'),
      dateTo: to.format('YYYY-MM-DD'),
      searchType: '수신번호',
      page: 0,
      size: 15 })
  }

  const addPhone = () => {
    const phone = phoneInput.replace(/[^\d]/g, '')
    if (!phone) {
      message.warning('연락처를 입력하세요.')
      return
    }
    if (phones.includes(phone)) {
      message.warning('이미 추가된 번호입니다.')
      return
    }
    setPhones((prev) => [...prev, phone])
    setPhoneInput('')
  }

  const openSend = () => {
    setPhones([])
    setPhoneInput('')
    setContent('')
    setOpen(true)
    balanceQuery.refetch()
  }

  const columns = useMemo(() => [
    { title: '발송일', dataIndex: 'sentAt', width: 140, align: 'center' as const, sorter: true },
    { title: '구분', dataIndex: 'msgType', width: 70, align: 'center' as const },
    { title: '발송', dataIndex: 'sendCount', width: 60, align: 'center' as const },
    { title: '차감', dataIndex: 'deductCount', width: 60, align: 'center' as const },
    { title: '발송명단', dataIndex: 'phone', width: 140, ellipsis: true },
    { title: '내용', dataIndex: 'message', ellipsis: true },
    { title: '발신번호', dataIndex: 'senderNumber', width: 110, align: 'center' as const },
    { title: '발송자', dataIndex: 'senderName', width: 90, align: 'center' as const },
  ], [])

  return (
    <div className="stock-page sms-history-page">
      <div className="stock-title">
        <div>
          <h2><SendOutlined style={{ marginRight: 8 }} />문자발송내역</h2>
          <p>발송하신 문자(SMS) 내역을 확인하실 수 있습니다.</p>
        </div>
        <Space className="stock-title-actions" wrap>
          <Button
            className="farebox-gray-btn"
            disabled={!selected.length}
            loading={deleteMut.isPending}
            onClick={() => {
              Modal.confirm({
                title: '삭제',
                content: `선택한 ${selected.length}건을 삭제하시겠습니까?`,
                onOk: () => deleteMut.mutateAsync(selected) })
            }}
          >
            삭제
          </Button>
          <Button type="primary" icon={<EditOutlined />} onClick={openSend}>문자발송</Button>
        </Space>
      </div>

      <Card className="stock-filter-card" size="small">
        <Form
          form={form}
          layout="inline"
          className="farebox-filter"
          initialValues={{ dates: defaultRange(), searchType: '수신번호', size: 15 }}
          onFinish={onSearch}
        >
          <div className="farebox-filter-row">
            <Form.Item name="dates">
              <RangePicker allowClear={false} />
            </Form.Item>
            <Form.Item name="searchType">
              <Select
                className="w-120"
                options={['수신번호', '내용', '발송자', '발신번호'].map((v) => ({ value: v, label: v }))}
              />
            </Form.Item>
            <Form.Item name="keyword">
              <Input className="w-180" allowClear placeholder="" />
            </Form.Item>
            <Form.Item>
              <Space>
                <Button type="primary" htmlType="submit" icon={<SearchOutlined />}>검색</Button>
                <Button onClick={onReset}>초기화</Button>
              </Space>
            </Form.Item>
            <Form.Item name="size" className="farebox-size">
              <Select
                className="w-150"
                options={[15, 30, 50, 100].map((n) => ({ value: n, label: `목록 ${n}개씩 보기` }))}
                onChange={(size) => setFilters((prev) => ({ ...prev, size, page: 0 }))}
              />
            </Form.Item>
          </div>
        </Form>
      </Card>

      <Card className="stock-table-card" size="small">
        <div className="farebox-table-toolbar">
          <Typography.Text>목록 {query.data?.total ?? 0}</Typography.Text>
        </div>
        <CareTable
          size="small"
          loading={query.isLoading}
          rowKey="id"
          dataSource={query.data?.list}
          columns={columns}
          bordered
          rowSelection={{
            selectedRowKeys: selected,
            onChange: (keys) => setSelected(keys.map(Number)) }}
          pagination={{
            current: Number(filters.page ?? 0) + 1,
            pageSize: Number(filters.size ?? 15),
            total: query.data?.total ?? 0,
            showSizeChanger: false,
            onChange: (page) => setFilters((prev) => ({ ...prev, page: page - 1 })) }}
          scroll={{ x: 1100 }}
          locale={{ emptyText: '문자발송 내역이 없습니다.' }}
        />
      </Card>

      <Modal
        title="문자발송"
        open={open}
        onCancel={() => setOpen(false)}
        footer={null}
        width={560}
        destroyOnHidden
        className="sms-send-modal"
        centered
      >
        <div className="sms-send-form">
          <div className="sms-send-row">
            <div className="sms-send-label">잔여SMS</div>
            <div className="sms-send-field sms-send-balance">
              <b>{balance.toLocaleString()}건</b>
              <Button size="small" onClick={() => chargeMut.mutate()} loading={chargeMut.isPending}>충전</Button>
            </div>
          </div>

          <div className="sms-send-row">
            <div className="sms-send-label">수신연락처 <span className="form-req">필수</span></div>
            <div className="sms-send-field">
              <Space.Compact style={{ width: '100%' }}>
                <Input
                  value={phoneInput}
                  onChange={(e) => setPhoneInput(e.target.value)}
                  onPressEnter={addPhone}
                  placeholder="연락처 입력"
                />
                <Button onClick={addPhone}>+ 추가</Button>
              </Space.Compact>
              <div className={`sms-phone-box ${phones.length ? '' : 'is-empty'}`}>
                {phones.length
                  ? phones.map((p) => (
                    <button
                      type="button"
                      key={p}
                      className="sms-phone-chip"
                      onClick={() => setPhones((prev) => prev.filter((x) => x !== p))}
                      title="클릭하여 삭제"
                    >
                      {p}
                    </button>
                  ))
                  : '받는 사람 연락처를 추가해주세요.'}
              </div>
              <div className="sms-phone-footer">
                <Button size="small" onClick={() => setPhones([])}>전체삭제</Button>
                <span>총 {phones.length} 건</span>
              </div>
            </div>
          </div>

          <div className="sms-send-row">
            <div className="sms-send-label">발송내용 <span className="form-req">필수</span></div>
            <div className="sms-send-field">
              <TextArea
                rows={6}
                value={content}
                onChange={(e) => setContent(e.target.value)}
                placeholder="발송할 내용을 입력하세요."
              />
              <div className="sms-content-meta">
                <span>{msgType}</span>
                <span>{bytes} / {bytes <= 90 ? 90 : 2000} bytes</span>
              </div>
            </div>
          </div>

          <div className="sms-send-row">
            <div className="sms-send-label">발신번호</div>
            <div className="sms-send-field">{senderNumber}</div>
          </div>

          <div className="sms-send-row">
            <div className="sms-send-label">차감</div>
            <div className="sms-send-field">{deduct > 0 ? deduct : '-'}</div>
          </div>

          <div className="sms-send-footer">
            <Button
              type="primary"
              loading={sendMut.isPending}
              onClick={() => {
                if (!phones.length) {
                  message.warning('받는 사람 연락처를 추가해주세요.')
                  return
                }
                if (!content.trim()) {
                  message.warning('발송내용을 입력하세요.')
                  return
                }
                sendMut.mutate()
              }}
            >
              발송합니다
            </Button>
            <Button onClick={() => setOpen(false)}>취소</Button>
          </div>
        </div>
      </Modal>
    </div>
  )
}
