import { useEffect, useMemo, useState } from 'react'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { Button, Card, Checkbox, Radio, Space, Tabs, message } from 'antd'
import CareTable from '../../components/CareTable'
import { CheckOutlined, SettingOutlined } from '@ant-design/icons'
import client, { apiPrefix, unwrap, type ApiResponse } from '../../api/client'

type RoleMatrix = Record<string, Record<string, boolean>>
type LevelsData = {
  roles: string[]
  tabs: { key: string; label: string }[]
  rows: Record<string, string[]>
  modes: Record<string, string>
  custom: Record<string, RoleMatrix>
  defaults: Record<string, RoleMatrix>
}

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

const FALLBACK_ROWS: Record<string, string[]> = {
  menu: ['상품관리', '계약관리', '접수관리', '정산관리', '일정관리', '예약관리', '고객관리', '장부관리', '통계관리', '환경설정'],
  product: ['목록조회', '상품등록', '상품수정', '상품삭제', '정책관리', '엑셀다운로드'],
  contract: ['목록조회', '계약등록', '계약수정', '상태변경', '엑셀다운로드'],
  reception: ['목록조회', '접수등록', '접수수정', '진행변경', '엑셀다운로드'],
  invoice: ['목록조회', '정산서발행', '정산서수정', '엑셀다운로드'],
  pending: ['목록조회', '일정등록', '약속수정', '약속삭제', '캘린더조회'],
  booking: ['목록조회', '예약등록', '예약수정', '예약삭제'],
  customer: ['목록조회', '고객등록', '고객수정', '고객삭제', '분류설정'],
  abooks: ['목록조회', '장부등록', '장부수정', '장부삭제', '엑셀다운로드'],
  report: ['일일리포트', '월간리포트', '상품통계', '직원통계', '거래처통계', '인센티브'],
}

const FALLBACK_TABS = [
  { key: 'menu', 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: '통계설정' },
]

const TAB_DESC: Record<string, string> = {
  menu: '각 권한별로 노출될 메뉴를 설정합니다.',
  product: '상품관리에서 사용할 권한을 설정합니다.',
  contract: '계약관리에서 사용할 권한을 설정합니다.',
  reception: '접수관리에서 사용할 권한을 설정합니다.',
  invoice: '정산관리에서 사용할 권한을 설정합니다.',
  pending: '일정관리에서 사용할 권한을 설정합니다.',
  booking: '예약관리에서 사용할 권한을 설정합니다.',
  customer: '고객관리에서 사용할 권한을 설정합니다.',
  abooks: '장부관리에서 사용할 권한을 설정합니다.',
  report: '통계관리에서 사용할 권한을 설정합니다.',
}

function buildMenuDefaults(): RoleMatrix {
  const menus = FALLBACK_ROWS.menu
  const out: RoleMatrix = {}
  for (const role of FALLBACK_ROLES) {
    const flags: Record<string, boolean> = {}
    for (const menu of menus) {
      flags[menu] = (() => {
        if (role === '총괄' || role === '팀장' || role === '개발자') return true
        if (role === '사원') {
          return ['계약관리', '접수관리', '정산관리', '일정관리', '예약관리', '고객관리', '장부관리'].includes(menu)
        }
        if (role === '영업' || role === '딜러') {
          return ['계약관리', '접수관리', '정산관리', '일정관리', '예약관리'].includes(menu)
        }
        return false
      })()
    }
    out[role] = flags
  }
  return out
}

function buildActionDefaults(
  actions: string[],
  allow: Record<string, boolean>,
): RoleMatrix {
  const out: RoleMatrix = {}
  for (const role of FALLBACK_ROLES) {
    const base = !!allow[role]
    const flags: Record<string, boolean> = {}
    for (const action of actions) {
      let on = base
      if (base && role === '사원' && action.includes('삭제')) on = false
      if (base && (role === '영업' || role === '딜러')
        && (action.includes('삭제') || action.includes('발행') || action.includes('정책'))) on = false
      flags[action] = on
    }
    out[role] = flags
  }
  return out
}

/** API 실패·미로드 시에도 기본값 매트릭스가 보이도록 서버와 동일한 폴백 */
const FALLBACK_DEFAULTS: Record<string, RoleMatrix> = {
  menu: buildMenuDefaults(),
  product: buildActionDefaults(FALLBACK_ROWS.product, {
    총괄: true, 팀장: true, 사원: true, 영업: false, 딜러: false, 개발자: true,
  }),
  contract: buildActionDefaults(FALLBACK_ROWS.contract, {
    총괄: true, 팀장: true, 사원: true, 영업: true, 딜러: true, 개발자: true,
  }),
  reception: buildActionDefaults(FALLBACK_ROWS.reception, {
    총괄: true, 팀장: true, 사원: true, 영업: true, 딜러: true, 개발자: true,
  }),
  invoice: buildActionDefaults(FALLBACK_ROWS.invoice, {
    총괄: true, 팀장: true, 사원: true, 영업: true, 딜러: true, 개발자: true,
  }),
  pending: buildActionDefaults(FALLBACK_ROWS.pending, {
    총괄: true, 팀장: true, 사원: true, 영업: true, 딜러: true, 개발자: true,
  }),
  booking: buildActionDefaults(FALLBACK_ROWS.booking, {
    총괄: true, 팀장: true, 사원: true, 영업: true, 딜러: true, 개발자: true,
  }),
  customer: buildActionDefaults(FALLBACK_ROWS.customer, {
    총괄: true, 팀장: true, 사원: true, 영업: false, 딜러: false, 개발자: true,
  }),
  abooks: buildActionDefaults(FALLBACK_ROWS.abooks, {
    총괄: true, 팀장: true, 사원: true, 영업: false, 딜러: false, 개발자: true,
  }),
  report: buildActionDefaults(FALLBACK_ROWS.report, {
    총괄: true, 팀장: true, 사원: false, 영업: false, 딜러: false, 개발자: true,
  }),
}

const cloneMatrix = (src?: RoleMatrix): RoleMatrix => {
  const out: RoleMatrix = {}
  if (!src) return out
  for (const [role, flags] of Object.entries(src)) {
    out[role] = { ...(flags || {}) }
  }
  return out
}

function matrixHasFlags(mat?: RoleMatrix): boolean {
  if (!mat) return false
  return Object.values(mat).some((flags) => flags && Object.keys(flags).length > 0)
}

function mergeMatrix(primary?: RoleMatrix, fallback?: RoleMatrix): RoleMatrix {
  const base = cloneMatrix(fallback)
  if (!primary) return base
  for (const [role, flags] of Object.entries(primary)) {
    base[role] = { ...(base[role] || {}), ...(flags || {}) }
  }
  // 폴백 역할이 primary에 없으면 유지
  for (const role of FALLBACK_ROLES) {
    if (!base[role]) base[role] = { ...(fallback?.[role] || {}) }
  }
  return base
}

export default function SettingLevelPage() {
  const qc = useQueryClient()
  const [tab, setTab] = useState('menu')
  const [modes, setModes] = useState<Record<string, string>>({})
  const [custom, setCustom] = useState<Record<string, RoleMatrix>>({})

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

  useEffect(() => {
    if (!query.data) return
    setModes({ ...(query.data.modes || {}) })
    setCustom(
      Object.fromEntries(
        Object.entries(query.data.custom || {}).map(([k, v]) => [k, cloneMatrix(v)]),
      ),
    )
  }, [query.data])

  const roles = (query.data?.roles?.length ? query.data.roles : FALLBACK_ROLES)
  const tabMeta = (query.data?.tabs?.length ? query.data.tabs : FALLBACK_TABS)
  const rowLabels = useMemo(() => {
    const fromApi = query.data?.rows?.[tab]
    if (Array.isArray(fromApi) && fromApi.length > 0) return fromApi
    return FALLBACK_ROWS[tab] || []
  }, [query.data, tab])
  const mode = modes[tab] || 'default'
  const isDefault = mode === 'default'

  const displayMatrix = useMemo(() => {
    const fallback = FALLBACK_DEFAULTS[tab] || {}
    if (isDefault) {
      return mergeMatrix(query.data?.defaults?.[tab], fallback)
    }
    if (matrixHasFlags(custom[tab])) {
      return mergeMatrix(custom[tab], fallback)
    }
    return mergeMatrix(query.data?.defaults?.[tab], fallback)
  }, [isDefault, query.data, custom, tab])

  const tableData = useMemo(
    () => rowLabels.map((label) => ({ label })),
    [rowLabels],
  )

  const save = useMutation({
    mutationFn: async () => {
      const { data } = await client.put<ApiResponse<LevelsData>>(`${apiPrefix()}/homes/levels`, {
        modes,
        custom,
      })
      return unwrap(data)
    },
    onSuccess: (data) => {
      qc.setQueryData(['homes-levels'], data)
      message.success('적용했습니다.')
    },
    onError: (e: unknown) => {
      const err = e as { response?: { status?: number }; message?: string }
      if (err?.response?.status === 401 || err?.response?.status === 403) {
        message.error('로그인이 만료되었거나 권한이 없습니다. 다시 로그인해 주세요.')
        return
      }
      message.error(err?.message || '적용에 실패했습니다.')
    },
  })

  const setMode = (next: string) => {
    setModes((prev) => ({ ...prev, [tab]: next }))
    if (next === 'custom' && !matrixHasFlags(custom[tab])) {
      const seed = mergeMatrix(query.data?.defaults?.[tab], FALLBACK_DEFAULTS[tab])
      setCustom((prev) => ({
        ...prev,
        [tab]: cloneMatrix(seed),
      }))
    }
  }

  const toggle = (role: string, row: string, checked: boolean) => {
    if (isDefault) return
    setCustom((prev) => ({
      ...prev,
      [tab]: {
        ...(prev[tab] || {}),
        [role]: {
          ...(prev[tab]?.[role] || {}),
          [row]: checked,
        },
      },
    }))
  }

  const columns = [
    {
      title: '권한',
      dataIndex: 'label',
      width: 160,
      align: 'center' as const,
      className: 'level-row-label',
    },
    ...roles.map((role) => ({
      title: role,
      dataIndex: role,
      align: 'center' as const,
      width: 100,
      render: (_: unknown, row: { label: string }) => {
        const checked = !!displayMatrix[role]?.[row.label]
        if (isDefault) {
          return checked ? <CheckOutlined className="level-check-icon" /> : <span className="level-check-empty" />
        }
        return (
          <Checkbox checked={checked} onChange={(e) => toggle(role, row.label, e.target.checked)} />
        )
      },
    })),
  ]

  const sectionTitle = tabMeta.find((t) => t.key === tab)?.label || '메뉴설정'

  return (
    <div className="stock-page level-page">
      <div className="stock-title">
        <div>
          <h2>
            <SettingOutlined className="product-title-icon" />
            환경설정 - 권한설정
          </h2>
          <p>직원에게 부여되는 권한을 세부적으로 설정하실 수 있습니다.</p>
        </div>
      </div>

      <Card className="stock-table-card level-card" size="small" loading={query.isLoading}>
        <Tabs
          className="pref-tabs homes-pref-tabs level-tabs"
          activeKey={tab}
          onChange={setTab}
          items={tabMeta.map((t) => ({ key: t.key, label: t.label }))}
        />

        <div className="level-section">
          <div className="level-section-head">
            <div>
              <h3>{sectionTitle}</h3>
              <p>{TAB_DESC[tab] || '권한을 설정합니다.'}</p>
            </div>
            <Radio.Group
              value={mode}
              onChange={(e) => setMode(e.target.value)}
              options={[
                { value: 'default', label: '기본값 사용' },
                { value: 'custom', label: '직접 설정' },
              ]}
            />
          </div>

          <CareTable
            className="level-matrix-table"
            size="small"
            bordered
            pagination={false}
            rowKey="label"
            columns={columns}
            dataSource={tableData}
            locale={{ emptyText: query.isError ? '권한 목록을 불러오지 못했습니다.' : '설정 항목이 없습니다.' }}
          />

          <div className="pref-actions">
            <Space>
              <Button
                className="homes-pref-apply"
                type="primary"
                loading={save.isPending}
                onClick={() => save.mutate()}
              >
                적용
              </Button>
            </Space>
          </div>
        </div>
      </Card>
    </div>
  )
}
