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

type GroupRow = {
  id?: number | null
  name: string
  count: number
  all?: boolean
}

type ContactRow = {
  id: number
  addressGroupId?: number
  groupName?: string
  name?: string
  phone?: string
  phoneDisplay?: string
}

type ContactData = {
  total: number
  list: ContactRow[]
}

export default function SmsAddressPage() {
  const qc = useQueryClient()
  const navigate = useNavigate()
  const [form] = Form.useForm()
  const [contactForm] = Form.useForm()
  const [groupForm] = Form.useForm()
  const [changeForm] = Form.useForm()
  const [bulkForm] = Form.useForm()
  const [selectedGroupId, setSelectedGroupId] = useState<number | null | undefined>(undefined)
  const [selected, setSelected] = useState<number[]>([])
  const [contactOpen, setContactOpen] = useState(false)
  const [editingContact, setEditingContact] = useState<ContactRow | null>(null)
  const [groupOpen, setGroupOpen] = useState(false)
  const [editingGroup, setEditingGroup] = useState<GroupRow | null>(null)
  const [changeOpen, setChangeOpen] = useState(false)
  const [bulkOpen, setBulkOpen] = useState(false)
  const [filters, setFilters] = useState<Record<string, unknown>>({
    searchType: '이름',
    page: 0,
    size: 15 })

  const groupsQuery = useQuery({
    queryKey: ['sms-address-groups'],
    queryFn: async () => {
      const { data } = await client.get<ApiResponse<{ list: GroupRow[]; total: number }>>(`${apiPrefix()}/sms/address/groups`)
      return unwrap(data)
    } })

  const contactsQuery = useQuery({
    queryKey: ['sms-address-contacts', filters, selectedGroupId],
    queryFn: async () => {
      const { data } = await client.get<ApiResponse<ContactData>>(`${apiPrefix()}/sms/address/contacts`, {
        params: {
          ...filters,
          addressGroupId: selectedGroupId ?? undefined } })
      return unwrap(data)
    } })

  const groupOptions = useMemo(
    () => (groupsQuery.data?.list ?? [])
      .filter((g) => !g.all)
      .map((g) => ({ value: g.id as number, label: g.name })),
    [groupsQuery.data],
  )

  const refresh = () => {
    setSelected([])
    qc.invalidateQueries({ queryKey: ['sms-address-groups'] })
    qc.invalidateQueries({ queryKey: ['sms-address-contacts'] })
  }

  const saveGroup = useMutation({
    mutationFn: async (values: { name: string }) => {
      if (editingGroup?.id) {
        const { data } = await client.put(`${apiPrefix()}/sms/address/groups/${editingGroup.id}`, values)
        return unwrap(data)
      }
      const { data } = await client.post(`${apiPrefix()}/sms/address/groups`, values)
      return unwrap(data)
    },
    onSuccess: () => {
      message.success(editingGroup ? '그룹을 수정했습니다.' : '그룹을 등록했습니다.')
      setGroupOpen(false)
      setEditingGroup(null)
      groupForm.resetFields()
      refresh()
    },
    onError: (e: Error) => message.error(e.message) })

  const saveContact = useMutation({
    mutationFn: async (values: Record<string, unknown>) => {
      const phone = [values.phone1, values.phone2, values.phone3].filter(Boolean).join('')
      const body = {
        addressGroupId: values.addressGroupId,
        name: values.name,
        phone }
      if (editingContact?.id) {
        const { data } = await client.put(`${apiPrefix()}/sms/address/contacts/${editingContact.id}`, body)
        return unwrap(data)
      }
      const { data } = await client.post(`${apiPrefix()}/sms/address/contacts`, body)
      return unwrap(data)
    },
    onSuccess: () => {
      message.success(editingContact ? '연락처를 수정했습니다.' : '연락처를 등록했습니다.')
      setContactOpen(false)
      setEditingContact(null)
      contactForm.resetFields()
      refresh()
    },
    onError: (e: Error) => message.error(e.message) })

  const deleteContacts = useMutation({
    mutationFn: async (ids: number[]) => {
      const { data } = await client.post(`${apiPrefix()}/sms/address/contacts/delete`, { ids })
      return unwrap(data)
    },
    onSuccess: () => { message.success('삭제했습니다.'); refresh() },
    onError: () => message.error('삭제에 실패했습니다.') })

  const changeGroup = useMutation({
    mutationFn: async (addressGroupId: number) => {
      const { data } = await client.post(`${apiPrefix()}/sms/address/contacts/change-group`, {
        ids: selected,
        addressGroupId })
      return unwrap(data)
    },
    onSuccess: () => {
      message.success('그룹을 변경했습니다.')
      setChangeOpen(false)
      changeForm.resetFields()
      refresh()
    },
    onError: (e: Error) => message.error(e.message) })

  const bulkCreate = useMutation({
    mutationFn: async (values: Record<string, unknown>) => {
      const { data } = await client.post(`${apiPrefix()}/sms/address/contacts/bulk`, values)
      return unwrap(data)
    },
    onSuccess: () => {
      message.success('대량등록이 완료되었습니다.')
      setBulkOpen(false)
      bulkForm.resetFields()
      refresh()
    },
    onError: (e: Error) => message.error(e.message) })

  const cartAdd = useMutation({
    mutationFn: async (phones: string[]) => {
      const { data } = await client.post(`${apiPrefix()}/sms/cart`, { phones })
      return unwrap(data) as { count: number }
    },
    onSuccess: (data) => {
      message.success(`문자 장바구니에 담았습니다. (총 ${data.count}건)`)
      navigate('/care/sms/history')
    },
    onError: () => message.error('장바구니 담기에 실패했습니다.') })

  const onSearch = (values: Record<string, unknown>) => {
    setFilters((prev) => ({
      ...prev,
      searchType: values.searchType || '이름',
      keyword: values.keyword,
      page: 0,
      size: Number(values.size ?? prev.size ?? 15) }))
  }

  const onReset = () => {
    form.setFieldsValue({ searchType: '이름', keyword: undefined, size: 15 })
    setSelectedGroupId(undefined)
    setFilters({ searchType: '이름', page: 0, size: 15 })
  }

  const openContactCreate = () => {
    setEditingContact(null)
    contactForm.setFieldsValue({
      addressGroupId: selectedGroupId ?? undefined,
      name: undefined,
      phone1: '010',
      phone2: '',
      phone3: '' })
    setContactOpen(true)
  }

  const openContactEdit = (row: ContactRow) => {
    setEditingContact(row)
    const digits = (row.phone || '').replace(/\D/g, '')
    contactForm.setFieldsValue({
      addressGroupId: row.addressGroupId,
      name: row.name,
      phone1: digits.slice(0, 3) || '010',
      phone2: digits.slice(3, 7),
      phone3: digits.slice(7) })
    setContactOpen(true)
  }

  const openGroupCreate = () => {
    setEditingGroup(null)
    groupForm.setFieldsValue({ name: undefined })
    setGroupOpen(true)
  }

  const openGroupEdit = (row: GroupRow) => {
    setEditingGroup(row)
    groupForm.setFieldsValue({ name: row.name })
    setGroupOpen(true)
  }

  const download = async () => {
    const { data } = await client.get(`${apiPrefix()}/sms/address/contacts/export`, {
      params: { ...filters, addressGroupId: selectedGroupId ?? undefined },
      responseType: 'blob' })
    const url = URL.createObjectURL(data)
    const a = document.createElement('a')
    a.href = url
    a.download = '문자주소록.csv'
    a.click()
    URL.revokeObjectURL(url)
  }

  const requireSelected = (action: () => void) => {
    if (!selected.length) {
      message.warning('항목을 선택하세요.')
      return
    }
    action()
  }

  const groupColumns = [
    {
      title: '그룹명',
      dataIndex: 'name',
      render: (v: string, row: GroupRow) => (
        <Button
          type="link"
          className="abook-company-link"
          onClick={() => {
            setSelectedGroupId(row.all ? undefined : (row.id ?? undefined))
            setFilters((prev) => ({ ...prev, page: 0 }))
            setSelected([])
          }}
        >
          <span className={(row.all && selectedGroupId == null) || (!row.all && selectedGroupId === row.id) ? 'sms-group-active' : ''}>
            {v}
          </span>
        </Button>
      ) },
    { title: '연락처', dataIndex: 'count', width: 80, align: 'center' as const },
    {
      title: '관리',
      key: 'manage',
      width: 60,
      align: 'center' as const,
      render: (_: unknown, row: GroupRow) => (
        row.all ? null : <Button type="text" size="small" icon={<EditOutlined />} onClick={() => openGroupEdit(row)} />
      ) },
  ]

  const contactColumns = [
    { title: '그룹', dataIndex: 'groupName', width: 110, align: 'center' as const },
    { title: '이름', dataIndex: 'name', width: 100, align: 'center' as const },
    { title: '연락처', dataIndex: 'phoneDisplay', width: 140, align: 'center' as const },
    {
      title: '관리',
      key: 'manage',
      width: 60,
      align: 'center' as const,
      render: (_: unknown, row: ContactRow) => (
        <Button type="text" size="small" icon={<EditOutlined />} onClick={() => openContactEdit(row)} />
      ) },
  ]

  return (
    <div className="stock-page sms-address-page">
      <div className="stock-title">
        <div>
          <h2><SendOutlined style={{ marginRight: 8 }} />문자주소록</h2>
          <p>주소록을 만드시면 문자발송을 손쉽게하실 수 있습니다.</p>
        </div>
        <Space className="stock-title-actions" wrap>
          <Button
            className="farebox-gray-btn"
            disabled={!selected.length}
            loading={cartAdd.isPending}
            onClick={() => requireSelected(() => {
              const phones = (contactsQuery.data?.list ?? [])
                .filter((c) => selected.includes(c.id))
                .map((c) => c.phone || '')
                .filter(Boolean)
              cartAdd.mutate(phones)
            })}
          >
            문자담기
          </Button>
          <Button
            className="farebox-gray-btn"
            disabled={!selected.length}
            onClick={() => requireSelected(() => {
              changeForm.setFieldsValue({ addressGroupId: undefined })
              setChangeOpen(true)
            })}
          >
            그룹변경
          </Button>
          <Button
            className="farebox-gray-btn"
            disabled={!selected.length}
            loading={deleteContacts.isPending}
            onClick={() => requireSelected(() => {
              Modal.confirm({
                title: '삭제',
                content: `선택한 ${selected.length}건을 삭제하시겠습니까?`,
                onOk: () => deleteContacts.mutateAsync(selected) })
            })}
          >
            삭제
          </Button>
          <Button type="primary" icon={<PlusOutlined />} onClick={openContactCreate}>연락처 등록</Button>
        </Space>
      </div>

      <Card className="stock-filter-card" size="small">
        <Form
          form={form}
          layout="inline"
          className="farebox-filter"
          initialValues={{ searchType: '이름', size: 15 }}
          onFinish={onSearch}
        >
          <div className="farebox-filter-row">
            <Form.Item name="searchType">
              <Select className="w-110" options={['이름', '연락처', '그룹'].map((v) => ({ value: v, label: v }))} />
            </Form.Item>
            <Form.Item name="keyword">
              <Input className="w-180" allowClear />
            </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>

      <div className="sms-address-grid">
        <Card className="stock-table-card" size="small">
          <div className="recovery-table-head">
            <Typography.Text strong>내 그룹</Typography.Text>
            <Button type="link" size="small" icon={<EditOutlined />} onClick={openGroupCreate}>그룹 등록</Button>
          </div>
          <CareTable
            size="small"
            loading={groupsQuery.isLoading}
            rowKey={(row) => String(row.id ?? 'all')}
            dataSource={groupsQuery.data?.list}
            columns={groupColumns}
            pagination={false}
            bordered
            rowClassName={(row) => {
              if (row.all && selectedGroupId == null) return 'sms-group-row-active'
              if (!row.all && selectedGroupId === row.id) return 'sms-group-row-active'
              return ''
            }}
          />
        </Card>

        <Card className="stock-table-card" size="small">
          <div className="recovery-table-head">
            <Typography.Text>목록 {contactsQuery.data?.total ?? 0}</Typography.Text>
            <Button type="link" icon={<DownloadOutlined />} onClick={download}>다운로드</Button>
          </div>
          <CareTable
            size="small"
            loading={contactsQuery.isLoading}
            rowKey="id"
            dataSource={contactsQuery.data?.list}
            columns={contactColumns}
            bordered
            rowSelection={{
              selectedRowKeys: selected,
              onChange: (keys) => setSelected(keys.map(Number)) }}
            pagination={{
              current: Number(filters.page ?? 0) + 1,
              pageSize: Number(filters.size ?? 15),
              total: contactsQuery.data?.total ?? 0,
              showSizeChanger: false,
              onChange: (page) => setFilters((prev) => ({ ...prev, page: page - 1 })) }}
            locale={{ emptyText: '연락처가 없습니다.' }}
          />
        </Card>
      </div>

      <Modal
        title={editingContact ? '연락처 수정' : '연락처 등록'}
        open={contactOpen}
        onCancel={() => { setContactOpen(false); setEditingContact(null) }}
        footer={null}
        width={460}
        destroyOnHidden
        centered
        className="sms-contact-modal"
      >
        <Form
          form={contactForm}
          labelCol={{ flex: '72px' }}
          wrapperCol={{ flex: 1 }}
          labelAlign="left"
          colon={false}
          onFinish={(values) => saveContact.mutate(values)}
        >
          <Form.Item name="addressGroupId" label="그룹">
            <Select allowClear placeholder="-선택-" options={groupOptions} />
          </Form.Item>
          <Form.Item name="name" label="이름" rules={[{ required: true, message: '이름을 입력하세요.' }]}>
            <Input />
          </Form.Item>
          <Form.Item label="연락처" required>
            <Space.Compact>
              <Form.Item name="phone1" noStyle rules={[{ required: true, message: '연락처를 입력하세요.' }]}>
                <Input style={{ width: 70 }} maxLength={3} />
              </Form.Item>
              <Form.Item name="phone2" noStyle rules={[{ required: true, message: '연락처를 입력하세요.' }]}>
                <Input style={{ width: 80 }} maxLength={4} />
              </Form.Item>
              <Form.Item name="phone3" noStyle rules={[{ required: true, message: '연락처를 입력하세요.' }]}>
                <Input style={{ width: 80 }} maxLength={4} />
              </Form.Item>
            </Space.Compact>
          </Form.Item>
          <div className="sms-contact-footer">
            {!editingContact && (
              <Button type="link" onClick={() => { setContactOpen(false); setBulkOpen(true) }}>대량등록</Button>
            )}
            <div className="sms-contact-footer-right">
              <Button type="primary" htmlType="submit" loading={saveContact.isPending}>등록</Button>
              <Button onClick={() => { setContactOpen(false); setEditingContact(null) }}>취소</Button>
            </div>
          </div>
        </Form>
      </Modal>

      <Modal
        title={editingGroup ? '그룹 수정' : '그룹 등록'}
        open={groupOpen}
        onCancel={() => { setGroupOpen(false); setEditingGroup(null) }}
        footer={null}
        width={400}
        destroyOnHidden
        centered
      >
        <Form form={groupForm} layout="vertical" onFinish={(values) => saveGroup.mutate(values)}>
          <Form.Item name="name" label="그룹명" rules={[{ required: true, message: '그룹명을 입력하세요.' }]}>
            <Input placeholder="그룹명을 입력하세요" />
          </Form.Item>
          <div className="sms-send-footer">
            <Button type="primary" htmlType="submit" loading={saveGroup.isPending}>
              {editingGroup ? '수정합니다' : '등록'}
            </Button>
            <Button onClick={() => { setGroupOpen(false); setEditingGroup(null) }}>취소</Button>
          </div>
        </Form>
      </Modal>

      <Modal
        title="그룹변경"
        open={changeOpen}
        onCancel={() => setChangeOpen(false)}
        footer={null}
        width={400}
        destroyOnHidden
        centered
      >
        <Form
          form={changeForm}
          layout="vertical"
          onFinish={(values) => changeGroup.mutate(Number(values.addressGroupId))}
        >
          <Form.Item name="addressGroupId" label="그룹" rules={[{ required: true, message: '그룹을 선택하세요.' }]}>
            <Select placeholder="-선택-" options={groupOptions} />
          </Form.Item>
          <div className="sms-send-footer">
            <Button type="primary" htmlType="submit" loading={changeGroup.isPending}>변경합니다</Button>
            <Button onClick={() => setChangeOpen(false)}>취소</Button>
          </div>
        </Form>
      </Modal>

      <Modal
        title="대량등록"
        open={bulkOpen}
        onCancel={() => setBulkOpen(false)}
        footer={null}
        width={520}
        destroyOnHidden
        centered
      >
        <Form form={bulkForm} layout="vertical" onFinish={(values) => bulkCreate.mutate(values)}>
          <Form.Item name="addressGroupId" label="그룹">
            <Select allowClear placeholder="-선택-" options={groupOptions} />
          </Form.Item>
          <Form.Item
            name="text"
            label="연락처 목록"
            rules={[{ required: true, message: '연락처를 입력하세요.' }]}
            extra="한 줄에 이름,연락처 형식으로 입력하세요. (예: 홍길동,01012345678)"
          >
            <Input.TextArea rows={8} placeholder={'홍길동,01012345678\n김철수,01098765432'} />
          </Form.Item>
          <div className="sms-send-footer">
            <Button type="primary" htmlType="submit" loading={bulkCreate.isPending}>등록</Button>
            <Button onClick={() => setBulkOpen(false)}>취소</Button>
          </div>
        </Form>
      </Modal>
    </div>
  )
}
