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

type MemberRow = {
  id: number
  status?: string
  active?: boolean
  staffPermission?: string
  userid?: string
  name?: string
  phone?: string
  address?: string
  accessLimit?: string
  loginCount?: number
  lastLoginAt?: string
  registeredDate?: string
  memo?: string
  menuFlags?: string
  isOwner?: boolean
}

type MemberResult = {
  total: number
  list: MemberRow[]
  counts?: Record<string, number>
}

const PERMISSIONS = ['대표', '총괄', '팀장', '사원', '영업', '딜러', '개발자']

const MENU_EXPOSURE = [
  { key: 'home', label: '대시보드' },
  { key: 'product', label: '상품관리' },
  { key: 'contract', label: '계약관리' },
  { key: 'reception', label: '접수관리' },
  { key: 'invoice', label: '정산관리' },
  { key: 'pending', label: '일정관리' },
  { key: 'booking', label: '예약관리' },
  { key: 'customer', label: '고객관리' },
  { key: 'abooks', label: '장부관리' },
  { key: 'report', label: '통계관리' },
  { key: 'cs', label: '고객센터' },
  { key: 'bbs', label: '사내게시판' },
  { key: 'setting', label: '환경설정' },
]

const defaultMenuFlags = () =>
  Object.fromEntries(MENU_EXPOSURE.map((m) => [m.key, true])) as Record<string, boolean>

const parseMenuFlags = (raw?: string) => {
  if (!raw) return defaultMenuFlags()
  try {
    const parsed = JSON.parse(raw) as Record<string, boolean>
    return { ...defaultMenuFlags(), ...parsed }
  } catch {
    return defaultMenuFlags()
  }
}

const initial = { page: 0, size: 10, sort: 'id,asc' } as Record<string, unknown>

export default function SettingMemberPage() {
  const qc = useQueryClient()
  const [form] = Form.useForm()
  const [editForm] = Form.useForm()
  const [memoForm] = Form.useForm()
  const [expoForm] = Form.useForm()
  const [filters, setFilters] = useState<Record<string, unknown>>(initial)
  const [selected, setSelected] = useState<number[]>([])
  const [open, setOpen] = useState(false)
  const [editing, setEditing] = useState<MemberRow | null>(null)
  const [memoOpen, setMemoOpen] = useState(false)
  const [memoTarget, setMemoTarget] = useState<MemberRow | null>(null)
  const [expoOpen, setExpoOpen] = useState(false)
  const [expoTarget, setExpoTarget] = useState<MemberRow | null>(null)

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

  const refresh = () => {
    setSelected([])
    qc.invalidateQueries({ queryKey: ['homes-members'] })
    qc.invalidateQueries({ queryKey: ['homes/members-options'] })
  }

  const saveMut = useMutation({
    mutationFn: async (values: Record<string, unknown>) => {
      const payload = {
        userid: values.userid,
        password: values.password,
        name: values.name,
        phone: values.phone,
        address: values.address,
        accessLimit: values.accessLimit,
        staffPermission: values.staffPermission,
        status: values.status || '사용',
        memo: values.memo }
      if (editing?.id) {
        const { data } = await client.put(`${apiPrefix()}/homes/members/${editing.id}`, payload)
        return unwrap(data as ApiResponse)
      }
      const { data } = await client.post(`${apiPrefix()}/homes/members`, payload)
      return unwrap(data as ApiResponse)
    },
    onSuccess: () => {
      message.success(editing ? '수정했습니다.' : '직원을 등록했습니다.')
      setOpen(false)
      setEditing(null)
      editForm.resetFields()
      refresh()
    },
    onError: (e: Error) => message.error(e.message) })

  const statusMut = useMutation({
    mutationFn: async (status: '사용' | '중지') => {
      const { data } = await client.post(`${apiPrefix()}/homes/members/status`, { ids: selected, status })
      return unwrap(data as ApiResponse<{ updated: number }>)
    },
    onSuccess: (data, status) => {
      message.success(`${data.updated}건을 ${status} 처리했습니다.`)
      refresh()
    },
    onError: (e: Error) => message.error(e.message) })

  const memoMut = useMutation({
    mutationFn: async (memo: string) => {
      const { data } = await client.put(`${apiPrefix()}/homes/members/${memoTarget!.id}`, { memo })
      return unwrap(data as ApiResponse)
    },
    onSuccess: () => {
      message.success('비고를 저장했습니다.')
      setMemoOpen(false)
      setMemoTarget(null)
      memoForm.resetFields()
      refresh()
    },
    onError: (e: Error) => message.error(e.message) })

  const expoMut = useMutation({
    mutationFn: async (flags: Record<string, boolean>) => {
      const { data } = await client.put(`${apiPrefix()}/homes/members/${expoTarget!.id}`, {
        menuFlags: JSON.stringify(flags) })
      return unwrap(data as ApiResponse)
    },
    onSuccess: () => {
      message.success('노출설정을 저장했습니다.')
      setExpoOpen(false)
      setExpoTarget(null)
      refresh()
    },
    onError: (e: Error) => message.error(e.message) })

  const onSearch = (values: Record<string, unknown>) => {
    setFilters({
      ...initial,
      status: values.status || undefined,
      q: values.q || undefined,
      page: 0,
      size: Number(values.size ?? filters.size ?? 10),
      sort: filters.sort })
  }

  const onReset = () => {
    form.resetFields()
    form.setFieldsValue({ size: 10 })
    setFilters(initial)
  }

  const openCreate = () => {
    setEditing(null)
    editForm.setFieldsValue({
      userid: undefined,
      password: undefined,
      name: undefined,
      phone: undefined,
      address: undefined,
      accessLimit: undefined,
      staffPermission: '사원',
      status: '사용',
      memo: undefined })
    setOpen(true)
  }

  const openEdit = (row: MemberRow) => {
    setEditing(row)
    editForm.setFieldsValue({
      userid: row.userid,
      password: undefined,
      name: row.name,
      phone: row.phone,
      address: row.address,
      accessLimit: row.accessLimit,
      staffPermission: row.staffPermission || '사원',
      status: row.status || '사용',
      memo: row.memo })
    setOpen(true)
  }

  const openMemo = (row: MemberRow) => {
    setMemoTarget(row)
    memoForm.setFieldsValue({ memo: row.memo })
    setMemoOpen(true)
  }

  const openExpo = (row: MemberRow) => {
    setExpoTarget(row)
    expoForm.setFieldsValue(parseMenuFlags(row.menuFlags))
    setExpoOpen(true)
  }

  const download = async () => {
    try {
      const { data } = await client.get(`${apiPrefix()}/homes/members/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)
    } catch {
      message.error('엑셀 다운로드에 실패했습니다.')
    }
  }

  const requireSelected = (status: '사용' | '중지') => {
    if (!selected.length) {
      message.warning('직원을 선택하세요.')
      return
    }
    statusMut.mutate(status)
  }

  const columns = useMemo(
    () => [
      {
        title: '상태',
        dataIndex: 'status',
        width: 64,
        align: 'center' as const,
        render: (v: string) => <span className={v === '중지' ? 'farebox-cancelled' : ''}>{v || '사용'}</span> },
      {
        title: '권한',
        dataIndex: 'staffPermission',
        width: 70,
        align: 'center' as const,
        sorter: true },
      {
        title: '아이디',
        dataIndex: 'userid',
        width: 90,
        align: 'center' as const,
        sorter: true },
      {
        title: '이름',
        dataIndex: 'name',
        width: 90,
        align: 'center' as const,
        sorter: true },
      {
        title: '휴대폰',
        dataIndex: 'phone',
        width: 120,
        align: 'center' as const,
        render: (v?: string) => v || '' },
      {
        title: '주소',
        dataIndex: 'address',
        width: 160,
        ellipsis: true,
        render: (v?: string) => v || '' },
      {
        title: '접속제한',
        dataIndex: 'accessLimit',
        width: 90,
        align: 'center' as const,
        render: (v?: string) => v || '' },
      {
        title: '접속수',
        dataIndex: 'loginCount',
        width: 80,
        align: 'center' as const,
        sorter: true,
        render: (v?: number) => (v == null ? '0' : Number(v).toLocaleString()) },
      {
        title: '최종접속',
        dataIndex: 'lastLoginAt',
        width: 110,
        align: 'center' as const,
        sorter: true,
        render: (v?: string) => v || '' },
      {
        title: '등록일',
        dataIndex: 'registeredDate',
        width: 110,
        align: 'center' as const,
        sorter: true },
      {
        title: '비고',
        key: 'memo',
        width: 56,
        align: 'center' as const,
        render: (_: unknown, row: MemberRow) => (
          <Button
            type="text"
            size="small"
            icon={<MailOutlined style={{ color: row.memo ? 'var(--primary)' : '#94a3b8' }} />}
            onClick={() => openMemo(row)}
          />
        ) },
      {
        title: '관리',
        key: 'manage',
        width: 56,
        align: 'center' as const,
        render: (_: unknown, row: MemberRow) => (
          <Button
            type="primary"
            size="small"
            className="member-manage-btn"
            icon={<EditOutlined />}
            onClick={() => openEdit(row)}
          />
        ) },
      {
        title: '설정',
        key: 'exposure',
        width: 100,
        align: 'center' as const,
        render: (_: unknown, row: MemberRow) =>
          row.isOwner ? null : (
            <Button type="primary" size="small" className="member-expo-btn" onClick={() => openExpo(row)}>
              노출설정
            </Button>
          ) },
    ],
    [],
  )

  return (
    <div className="stock-page member-manage-page">
      <div className="stock-title">
        <div>
          <h2>
            <SettingOutlined className="product-title-icon" />
            직원관리
          </h2>
          <p>직원의 계정을 추가로 등록 혹은 관리하실 수 있습니다.</p>
        </div>
        <Space className="stock-title-actions" wrap>
          <Button
            className="farebox-gray-btn"
            disabled={!selected.length}
            loading={statusMut.isPending}
            onClick={() => requireSelected('사용')}
          >
            사용
          </Button>
          <Button
            className="farebox-gray-btn"
            disabled={!selected.length}
            loading={statusMut.isPending}
            onClick={() => requireSelected('중지')}
          >
            중지
          </Button>
          <Button className="member-register-btn" type="primary" icon={<PlusSquareOutlined />} onClick={openCreate}>
            직원 등록
          </Button>
        </Space>
      </div>

      <Card className="stock-filter-card" size="small">
        <Form
          form={form}
          layout="inline"
          className="farebox-filter"
          initialValues={{ size: 10 }}
          onFinish={onSearch}
        >
          <div className="farebox-filter-row">
            <Form.Item name="status">
              <Select
                allowClear
                placeholder="상태"
                className="w-110"
                options={['사용', '중지'].map((v) => ({ value: v, label: v }))}
              />
            </Form.Item>
            <Form.Item name="q">
              <Input className="w-180" allowClear placeholder="이름/아이디" />
            </Form.Item>
            <Form.Item>
              <Space>
                <Button type="primary" htmlType="submit" icon={<SearchOutlined />}>
                  검색
                </Button>
                <Button icon={<ReloadOutlined />} onClick={onReset}>
                  초기화
                </Button>
              </Space>
            </Form.Item>
            <Form.Item name="size" className="farebox-size">
              <Select
                className="w-150"
                options={[10, 15, 30, 50, 100].map((n) => ({ value: n, label: `목록 ${n}개씩 보기` }))}
                onChange={(size) => {
                  form.setFieldValue('size', 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>
            목록 <b>{query.data?.total ?? 0}</b>
          </Typography.Text>
          <Button type="link" icon={<DownloadOutlined />} onClick={download}>
            엑셀다운로드
          </Button>
        </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)),
            getCheckboxProps: (row) => ({
              disabled: !!row.isOwner }) }}
          pagination={{
            current: Number(filters.page ?? 0) + 1,
            pageSize: Number(filters.size ?? 10),
            total: query.data?.total ?? 0,
            showSizeChanger: false,
            onChange: (page) => setFilters((prev) => ({ ...prev, page: page - 1 })) }}
          onChange={(_p, _f, sorter) => {
            const s = Array.isArray(sorter) ? sorter[0] : sorter
            if (!s?.field || !s.order) return
            setFilters((prev) => ({
              ...prev,
              sort: `${String(s.field)},${s.order === 'ascend' ? 'asc' : 'desc'}` }))
          }}
          scroll={{ x: 1400 }}
          locale={{ emptyText: '등록된 직원이 없습니다.' }}
        />
      </Card>

      <Modal
        title={editing ? '직원 수정' : '직원 등록'}
        open={open}
        onCancel={() => {
          setOpen(false)
          setEditing(null)
        }}
        footer={null}
        width={520}
        destroyOnHidden
        centered
      >
        <Form
          form={editForm}
          labelCol={{ flex: '100px' }}
          wrapperCol={{ flex: 1 }}
          labelAlign="left"
          colon={false}
          onFinish={(values) => saveMut.mutate(values)}
        >
          <Form.Item name="userid" label="아이디" rules={[{ required: true, message: '아이디를 입력하세요.' }]}>
            <Input disabled={!!editing} />
          </Form.Item>
          <Form.Item
            name="password"
            label="비밀번호"
            rules={editing ? [] : [{ required: true, message: '비밀번호를 입력하세요.' }]}
          >
            <Input.Password placeholder={editing ? '변경 시에만 입력' : undefined} />
          </Form.Item>
          <Form.Item name="name" label="이름" rules={[{ required: true, message: '이름을 입력하세요.' }]}>
            <Input />
          </Form.Item>
          <Form.Item name="phone" label="휴대폰">
            <Input placeholder="010-0000-0000" />
          </Form.Item>
          <Form.Item name="address" label="주소">
            <Input />
          </Form.Item>
          <Form.Item name="accessLimit" label="접속제한">
            <Input placeholder="IP 또는 제한 메모" />
          </Form.Item>
          <Form.Item name="staffPermission" label="권한" rules={[{ required: true, message: '권한을 선택하세요.' }]}>
            <Select
              options={PERMISSIONS.map((v) => ({ value: v, label: v }))}
              disabled={!!editing?.isOwner}
            />
          </Form.Item>
          <Form.Item name="status" label="상태">
            <Select options={['사용', '중지'].map((v) => ({ value: v, label: v }))} disabled={!!editing?.isOwner} />
          </Form.Item>
          <Form.Item name="memo" label="비고">
            <Input.TextArea rows={2} />
          </Form.Item>
          <div className="sms-send-footer">
            <Button
              className="member-submit-btn"
              type="primary"
              htmlType="submit"
              loading={saveMut.isPending}
              icon={<EditOutlined />}
            >
              {editing ? '수정합니다' : '등록'}
            </Button>
            <Button
              onClick={() => {
                setOpen(false)
                setEditing(null)
              }}
            >
              취소
            </Button>
          </div>
        </Form>
      </Modal>

      <Modal
        title="비고"
        open={memoOpen}
        onCancel={() => {
          setMemoOpen(false)
          setMemoTarget(null)
        }}
        footer={null}
        width={420}
        destroyOnHidden
        centered
      >
        <Form form={memoForm} onFinish={(v) => memoMut.mutate(String(v.memo || ''))}>
          <Form.Item name="memo" style={{ marginBottom: 16 }}>
            <Input.TextArea rows={4} placeholder="비고를 입력하세요" />
          </Form.Item>
          <div className="sms-send-footer">
            <Button className="member-submit-btn" type="primary" htmlType="submit" loading={memoMut.isPending}>
              저장
            </Button>
            <Button
              onClick={() => {
                setMemoOpen(false)
                setMemoTarget(null)
              }}
            >
              취소
            </Button>
          </div>
        </Form>
      </Modal>

      <Modal
        title={`노출설정${expoTarget?.name ? ` - ${expoTarget.name}` : ''}`}
        open={expoOpen}
        onCancel={() => {
          setExpoOpen(false)
          setExpoTarget(null)
        }}
        footer={null}
        width={480}
        destroyOnHidden
        centered
      >
        <p className="member-expo-hint">메뉴 노출 여부를 설정합니다. 체크된 메뉴만 해당 직원에게 표시됩니다.</p>
        <Form
          form={expoForm}
          onFinish={(values) => expoMut.mutate(values as Record<string, boolean>)}
        >
          <div className="member-expo-grid">
            {MENU_EXPOSURE.map((m) => (
              <Form.Item key={m.key} name={m.key} valuePropName="checked" style={{ marginBottom: 8 }}>
                <Checkbox>{m.label}</Checkbox>
              </Form.Item>
            ))}
          </div>
          <div className="sms-send-footer">
            <Button className="member-submit-btn" type="primary" htmlType="submit" loading={expoMut.isPending}>
              저장
            </Button>
            <Button
              onClick={() => {
                setExpoOpen(false)
                setExpoTarget(null)
              }}
            >
              취소
            </Button>
          </div>
        </Form>
      </Modal>
    </div>
  )
}
