import { useMemo, useState } from 'react'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import dayjs, { type Dayjs } from 'dayjs'
import {
  Button,
  Card,
  DatePicker,
  Form,
  Input,
  Select,
  Space,
  Tooltip,
  message } from 'antd'
import { ClockCircleOutlined, LeftOutlined, RightOutlined, SettingOutlined } from '@ant-design/icons'
import Modal from '../../components/DraggableModal'
import SubjectSettingsModal from '../../components/SubjectSettingsModal'
import client, { apiPrefix, unwrap, type ApiResponse } from '../../api/client'
import type { Row } from './homesShared'

type PendingResult = {
  total: number
  list: Row[]
  types?: string[]
  statuses?: string[]
  receiveEmployees?: string[]
  processEmployees?: string[]
}

const WEEK_LABELS = [
  { key: 'sun', label: 'SUN', cls: 'sun' },
  { key: 'mon', label: 'MON', cls: '' },
  { key: 'tue', label: 'TUE', cls: '' },
  { key: 'wed', label: 'WED', cls: '' },
  { key: 'thu', label: 'THU', cls: '' },
  { key: 'fri', label: 'FRI', cls: '' },
  { key: 'sat', label: 'SAT', cls: 'sat' },
]

const VIEW_OPTIONS = [
  { value: 'simple', label: '간단하게 보기' },
  { value: 'detail', label: '자세히 보기' },
]

const DEFAULT_TYPES = ['일반', '약속1', '약속2']
const DEFAULT_STATUSES = ['예정', '완료', '보류', '취소']

function splitPhone(phone?: string) {
  const digits = String(phone || '').replace(/\D/g, '')
  if (digits.length >= 10) {
    return {
      phone1: digits.slice(0, 3),
      phone2: digits.slice(3, digits.length - 4),
      phone3: digits.slice(-4) }
  }
  return { phone1: '010', phone2: '', phone3: '' }
}

function startOfWeekSunday(date: Dayjs) {
  return date.subtract(date.day(), 'day').startOf('day')
}

function endOfWeekSaturday(date: Dayjs) {
  return date.add(6 - date.day(), 'day').endOf('day')
}

function buildMonthCells(cursor: Dayjs) {
  const start = startOfWeekSunday(cursor.startOf('month'))
  const end = endOfWeekSaturday(cursor.endOf('month'))
  const cells: Dayjs[] = []
  let d = start
  while (d.isBefore(end) || d.isSame(end, 'day')) {
    cells.push(d)
    d = d.add(1, 'day')
  }
  return cells
}

function eventLabel(row: Row, view: string) {
  if (view === 'detail') {
    const parts = [row.pendingTime, row.customerName, row.contents].filter(Boolean)
    return parts.join(' ')
  }
  return String(row.customerName || row.contents || row.pendingType || '')
}

export default function PendingCalendarPage() {
  const [cursor, setCursor] = useState(() => dayjs().startOf('month'))
  const [pendingType, setPendingType] = useState<string | undefined>()
  const [status, setStatus] = useState<string | undefined>()
  const [view, setView] = useState('simple')
  const [creating, setCreating] = useState(false)
  const [editing, setEditing] = useState<Row | null>(null)
  const [typeOpen, setTypeOpen] = useState(false)
  const [editForm] = Form.useForm()
  const qc = useQueryClient()
  const modalOpen = creating || Boolean(editing)

  const rangeStart = startOfWeekSunday(cursor.startOf('month'))
  const rangeEnd = endOfWeekSaturday(cursor.endOf('month'))

  const query = useQuery({
    queryKey: ['homes-pendings-cal', cursor.format('YYYY-MM'), pendingType, status],
    queryFn: async () => {
      const { data } = await client.get<ApiResponse<PendingResult>>(`${apiPrefix()}/homes/pendings`, {
        params: {
          page: 0,
          size: 500,
          dateFrom: rangeStart.format('YYYY-MM-DD'),
          dateTo: rangeEnd.format('YYYY-MM-DD'),
          pendingType: pendingType || undefined,
          status: status || undefined } })
      return unwrap(data)
    } })

  const members = useQuery({
    queryKey: ['homes/members-options'],
    queryFn: async () => {
      const { data } = await client.get<ApiResponse<{ list: { id: number; name?: string }[] }>>(`${apiPrefix()}/homes/members`, {
        params: { page: 0, size: 200 } })
      return unwrap(data)
    } })

  const byDate = useMemo(() => {
    const map: Record<string, Row[]> = {}
    for (const row of query.data?.list || []) {
      const d = String(row.pendingDate || '')
      if (!d) continue
      ;(map[d] ||= []).push(row)
    }
    return map
  }, [query.data])

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

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

  const staffOptions = useMemo(() => {
    const fromApi = [
      ...(query.data?.receiveEmployees || []),
      ...(query.data?.processEmployees || []),
    ]
    const fromMembers = (members.data?.list || []).map((m) => String(m.name || '')).filter(Boolean)
    return Array.from(new Set([...fromApi, ...fromMembers])).map((v) => ({ value: v, label: v }))
  }, [query.data, members.data])

  const cells = useMemo(() => buildMonthCells(cursor), [cursor])
  const todayKey = dayjs().format('YYYY-MM-DD')

  const refresh = () => {
    qc.invalidateQueries({ queryKey: ['homes-pendings-cal'] })
    qc.invalidateQueries({ queryKey: ['homes-pendings'] })
  }

  const save = useMutation({
    mutationFn: async (values: Record<string, unknown>) => {
      const phone = [values.phone1, values.phone2, values.phone3]
        .map((v) => String(v || '').replace(/\D/g, ''))
        .filter(Boolean)
        .join('-')
      const payload: Record<string, unknown> = {
        receiveEmployee: values.receiveEmployee,
        employee: values.receiveEmployee,
        pendingDate: values.pendingDate ? dayjs(values.pendingDate as Dayjs).format('YYYY-MM-DD') : undefined,
        pendingType: values.pendingType,
        contents: values.contents,
        customerName: values.customerName,
        phone: phone || undefined,
        memo: values.memo,
        status: values.status || (editing?.status ?? '접수') }
      if (editing) {
        const { data } = await client.put(`${apiPrefix()}/homes/pendings/${editing.id}`, payload)
        return unwrap(data as ApiResponse)
      }
      const { data } = await client.post(`${apiPrefix()}/homes/pendings`, payload)
      return unwrap(data as ApiResponse)
    },
    onSuccess: () => {
      message.success(editing ? '수정했습니다.' : '일정을 등록했습니다.')
      setCreating(false)
      setEditing(null)
      editForm.resetFields()
      refresh()
    },
    onError: (e: Error) => message.error(e.message) })

  const saveTypes = useMutation({
    mutationFn: async (types: string[]) => {
      const { data } = await client.put(`${apiPrefix()}/homes/pendings/types`, { types })
      return unwrap(data as ApiResponse<{ types: string[] }>)
    },
    onSuccess: () => {
      message.success('과목을 저장했습니다.')
      setTypeOpen(false)
      refresh()
    },
    onError: (e: Error) => message.error(e.message) })

  const closeModal = () => {
    setCreating(false)
    setEditing(null)
  }

  const openCreate = (date: Dayjs) => {
    setEditing(null)
    const defaultStaff = staffOptions[0]?.value || localStorage.getItem('userName') || '김대표'
    editForm.setFieldsValue({
      receiveEmployee: defaultStaff,
      pendingDate: date,
      pendingType: typeOptions[0]?.value || '일반',
      contents: undefined,
      customerName: undefined,
      phone1: '010',
      phone2: '',
      phone3: '',
      memo: undefined,
      status: '접수' })
    setCreating(true)
  }

  const openEdit = (row: Row) => {
    setCreating(false)
    setEditing(row)
    const phones = splitPhone(String(row.phone || ''))
    editForm.setFieldsValue({
      receiveEmployee: row.receiveEmployee,
      pendingDate: row.pendingDate ? dayjs(String(row.pendingDate)) : undefined,
      pendingType: row.pendingType,
      contents: row.contents,
      customerName: row.customerName,
      ...phones,
      memo: row.memo,
      status: row.status || '접수' })
  }

  const openTypeSettings = () => setTypeOpen(true)

  return (
    <div className="stock-page pending-calendar-page">
      <div className="stock-title">
        <div>
          <h2>
            <ClockCircleOutlined className="product-title-icon" />
            캘린더
          </h2>
          <p>미결 등록된 업무를 월별 캘린더로 관리하실 수 있습니다.</p>
        </div>
      </div>

      <Card className="pending-calendar-card" size="small">
        <div className="pending-calendar-toolbar">
          <div className="pending-calendar-nav">
            <button type="button" aria-label="이전 달" onClick={() => setCursor((c) => c.subtract(1, 'month'))}>
              <LeftOutlined />
            </button>
            <span>{cursor.format('YYYY년 M월')}</span>
            <button type="button" aria-label="다음 달" onClick={() => setCursor((c) => c.add(1, 'month'))}>
              <RightOutlined />
            </button>
          </div>
          <div className="pending-calendar-filters">
            <Select
              allowClear
              placeholder="과목"
              className="w-120"
              value={pendingType}
              options={typeOptions}
              onChange={(v) => setPendingType(v)}
            />
            <Select
              allowClear
              placeholder="상태"
              className="w-120"
              value={status}
              options={statusOptions}
              onChange={(v) => setStatus(v)}
            />
            <Select
              className="w-140"
              value={view}
              options={VIEW_OPTIONS}
              onChange={(v) => setView(v)}
            />
          </div>
        </div>

        <div className="pending-calendar-grid">
          <div className="pending-calendar-weekhead">
            {WEEK_LABELS.map((w) => (
              <div key={w.key} className={`pending-calendar-weekday ${w.cls}`}>{w.label}</div>
            ))}
          </div>
          <div className="pending-calendar-body">
            {cells.map((date) => {
              const key = date.format('YYYY-MM-DD')
              const inMonth = date.month() === cursor.month()
              const isToday = key === todayKey
              const isMonthStart = date.date() === 1
              const items = byDate[key] || []
              const dateLabel = isMonthStart ? `${date.month() + 1}월 ${date.date()}일` : String(date.date())
              return (
                <div
                  key={key}
                  role="button"
                  tabIndex={0}
                  className={[
                    'pending-calendar-cell',
                    'pending-calendar-cell-clickable',
                    inMonth ? 'in-month' : 'out-month',
                    isToday ? 'is-today' : '',
                  ].filter(Boolean).join(' ')}
                  onClick={() => openCreate(date)}
                  onKeyDown={(e) => {
                    if (e.key === 'Enter' || e.key === ' ') {
                      e.preventDefault()
                      openCreate(date)
                    }
                  }}
                >
                  <div className={`pending-calendar-date ${date.day() === 0 ? 'sun' : date.day() === 6 ? 'sat' : ''}`}>
                    {dateLabel}
                  </div>
                  <div className="pending-calendar-events">
                    {items.slice(0, view === 'simple' ? 3 : 6).map((row) => {
                      const text = eventLabel(row, view)
                      return (
                        <Tooltip
                          key={row.id}
                          title={`${row.pendingTime || ''} ${row.customerName || ''} / ${row.pendingType || ''} / ${row.status || ''}\n${row.contents || ''}`}
                        >
                          <div
                            role="button"
                            tabIndex={0}
                            className={`pending-calendar-event status-${row.status || '예정'}`}
                            onClick={(e) => {
                              e.stopPropagation()
                              openEdit(row)
                            }}
                            onKeyDown={(e) => {
                              if (e.key === 'Enter' || e.key === ' ') {
                                e.preventDefault()
                                e.stopPropagation()
                                openEdit(row)
                              }
                            }}
                          >
                            {text}
                          </div>
                        </Tooltip>
                      )
                    })}
                    {items.length > (view === 'simple' ? 3 : 6) && (
                      <div className="pending-calendar-more">+{items.length - (view === 'simple' ? 3 : 6)}</div>
                    )}
                  </div>
                </div>
              )
            })}
          </div>
        </div>
      </Card>

      <Modal
        title={editing ? '약속 수정' : '일정 등록'}
        open={modalOpen}
        onCancel={closeModal}
        footer={null}
        destroyOnHidden
        width={560}
        className="pending-modal"
      >
        <Form
          form={editForm}
          layout="horizontal"
          labelCol={{ flex: '100px' }}
          wrapperCol={{ flex: 1 }}
          onFinish={(values) => save.mutate(values)}
          className="balance-edit-form"
        >
          <Form.Item name="receiveEmployee" label="접수직원" rules={[{ required: true, message: '접수직원을 선택하세요' }]}>
            <Select options={staffOptions} showSearch optionFilterProp="label" />
          </Form.Item>
          <Form.Item name="pendingDate" label="일자" rules={[{ required: true, message: '예정일을 선택해주세요.' }]}>
            <DatePicker className="full-width" placeholder="예정일을 선택해주세요." />
          </Form.Item>
          <Form.Item label="과목" required>
            <Space.Compact className="full-width">
              <Form.Item name="pendingType" noStyle rules={[{ required: true, message: '과목을 선택하세요' }]}>
                <Select options={typeOptions} style={{ width: '100%' }} />
              </Form.Item>
              <Button icon={<SettingOutlined />} onClick={openTypeSettings}>설정</Button>
            </Space.Compact>
          </Form.Item>
          <Form.Item name="contents" label="내용" rules={[{ required: true, message: '내용을 입력하세요' }]}>
            <Input />
          </Form.Item>
          <Form.Item name="customerName" label="고객명">
            <Input />
          </Form.Item>
          <Form.Item label="연락처">
            <Space.Compact>
              <Form.Item name="phone1" noStyle><Input style={{ width: 70 }} maxLength={3} /></Form.Item>
              <Form.Item name="phone2" noStyle><Input style={{ width: 80 }} maxLength={4} /></Form.Item>
              <Form.Item name="phone3" noStyle><Input style={{ width: 80 }} maxLength={4} /></Form.Item>
            </Space.Compact>
          </Form.Item>
          <Form.Item name="memo" label="비고" extra="최대 1,000자">
            <Input.TextArea rows={4} maxLength={1000} showCount />
          </Form.Item>
          <div className="balance-modal-footer">
            <Button className="pending-submit-btn" type="primary" htmlType="submit" loading={save.isPending}>
              {editing ? '수정합니다' : '등록'}
            </Button>
            <Button onClick={closeModal}>취소</Button>
          </div>
        </Form>
      </Modal>

      <SubjectSettingsModal
        open={typeOpen}
        items={typeOptions.map((o) => o.value)}
        saving={saveTypes.isPending}
        submitClassName="pending-submit-btn"
        onCancel={() => setTypeOpen(false)}
        onSave={(types) => saveTypes.mutate(types)}
      />
    </div>
  )
}
