import { useEffect, useState } from 'react'
import {
  codeGroupList, codeGroupDetail, createCodeGroup, updateCodeGroup, deleteCodeGroup,
} from '../../../api/uiws'
import {
  PageHeader, Panel, SearchBar, Input, Button, DataGrid, Modal, FormField, Spinner, YnBadge, type Column,
} from '../../../components/uiws/ui'

/*
 * 공통코드 관리 — PMS 백엔드(com.zioinfo.pms.uiws.system CodeController) 계약 정합.
 * 코드는 "그룹 단위"로 관리: 그룹 상세(CodeGrpDetailDto)에 values[]가 내장되며, 그룹 저장 시 values를 통째로 전송한다.
 * (별도 per-codeVal CRUD 엔드포인트 없음 → 코드값 추가/수정/삭제는 detail 편집 후 그룹 PUT으로 반영)
 */

interface CodeGrp extends Record<string, unknown> { grpCd: string; grpNm: string; useYn: string }
interface Code extends Record<string, unknown> { grpCd: string; codeVal: string; codeNm: string; sortOrd: number; useYn: string }

function friendlyError(e: any): string {
  if (e?.response?.status === 403) return '권한이 없습니다 (관리자 전용).'
  if (e?.response?.status === 409) return '이미 존재하는 코드입니다.'
  return e?.response?.data?.message || '요청을 처리하지 못했습니다.'
}

export default function CodeManagement() {
  const [groups, setGroups] = useState<CodeGrp[]>([])
  const [activeGrp, setActiveGrp] = useState<string>('')
  const [grpInfo, setGrpInfo] = useState<{ grpNm: string; useYn: string }>({ grpNm: '', useYn: 'Y' })
  const [codes, setCodes] = useState<Code[]>([])
  const [keyword, setKeyword] = useState('')
  const [loadingGrp, setLoadingGrp] = useState(false)
  const [loadingCode, setLoadingCode] = useState(false)
  const [err, setErr] = useState('')
  const [grpForm, setGrpForm] = useState<{ open: boolean; edit: CodeGrp | null }>({ open: false, edit: null })
  const [codeForm, setCodeForm] = useState<{ open: boolean; edit: Code | null }>({ open: false, edit: null })

  const loadGroups = async (kw = '') => {
    setLoadingGrp(true); setErr('')
    try {
      const res = await codeGroupList(kw || undefined)
      const list: CodeGrp[] = res.data.data?.content ?? []
      setGroups(list)
      if (!activeGrp && list.length > 0) setActiveGrp(list[0].grpCd)
    } catch (e) { setErr(friendlyError(e)) }
    finally { setLoadingGrp(false) }
  }
  useEffect(() => { loadGroups('') }, [])

  const loadDetail = async (grp = activeGrp) => {
    if (!grp) { setCodes([]); return }
    setLoadingCode(true)
    try {
      const res = await codeGroupDetail(grp)
      const d = res.data.data
      setGrpInfo({ grpNm: d?.grpNm ?? '', useYn: d?.useYn ?? 'Y' })
      setCodes((d?.values ?? []).map((v: Code) => ({ ...v, grpCd: grp })))
    } catch (e) { setErr(friendlyError(e)) }
    finally { setLoadingCode(false) }
  }
  useEffect(() => { loadDetail() }, [activeGrp])

  const removeGroup = async (grpCd: string) => {
    if (!window.confirm(`코드그룹 '${grpCd}' 와 하위 코드를 삭제하시겠습니까?`)) return
    try {
      await deleteCodeGroup(grpCd)
      if (activeGrp === grpCd) { setActiveGrp(''); setCodes([]) }
      await loadGroups()
    } catch (e) { setErr(friendlyError(e)) }
  }

  // 코드값 추가/수정: 현재 values 배열에 머지 후 그룹 PUT.
  const saveCodeValue = async (val: Code, originalCodeVal: string | null) => {
    const next = originalCodeVal
      ? codes.map(c => (c.codeVal === originalCodeVal ? val : c))
      : [...codes, val]
    await updateCodeGroup(activeGrp, { grpCd: activeGrp, grpNm: grpInfo.grpNm, useYn: grpInfo.useYn, values: next })
    await loadDetail()
  }

  const removeCode = async (c: Code) => {
    if (!window.confirm(`코드 '${c.codeNm}' 를 삭제하시겠습니까?`)) return
    try {
      const next = codes.filter(x => x.codeVal !== c.codeVal)
      await updateCodeGroup(activeGrp, { grpCd: activeGrp, grpNm: grpInfo.grpNm, useYn: grpInfo.useYn, values: next })
      await loadDetail()
    } catch (e) { setErr(friendlyError(e)) }
  }

  const codeColumns: Column<Code>[] = [
    { key: 'codeVal', header: '코드값', width: 150 },
    { key: 'codeNm', header: '코드명' },
    { key: 'sortOrd', header: '정렬', width: 70, align: 'center' },
    { key: 'useYn', header: '사용', width: 80, align: 'center', render: r => <YnBadge yn={r.useYn} yes="사용" no="미사용" /> },
    {
      key: 'act', header: '', width: 60, align: 'center',
      render: r => (
        <Button variant="ghost" onClick={() => removeCode(r)}>삭제</Button>
      ),
    },
  ]

  return (
    <div className="uiws-scope">
      <PageHeader title="공통코드 관리" subtitle="시스템관리(권한) · 코드그룹/코드값 CRUD"
        actions={<Button onClick={() => setGrpForm({ open: true, edit: null })}>+ 코드그룹 등록</Button>} />

      {err && <div style={{ color: 'var(--uiws-danger)', fontSize: 13, marginBottom: 12 }}>{err}</div>}

      <SearchBar>
        <Input value={keyword} onChange={setKeyword} placeholder="코드그룹 검색" style={{ minWidth: 220 }} />
        <Button variant="ghost" onClick={() => loadGroups(keyword)}>검색</Button>
      </SearchBar>

      <div style={{ display: 'grid', gridTemplateColumns: '300px 1fr', gap: 16, alignItems: 'start' }}>
        <Panel style={{ padding: 0 }}>
          <div style={{ padding: '12px 16px', fontSize: 12, fontWeight: 600, color: 'var(--uiws-text-muted)', borderBottom: '1px solid var(--uiws-border)' }}>
            코드그룹
          </div>
          {loadingGrp ? <Spinner /> : (
            <div>
              {groups.length === 0 && <div style={{ padding: 20, fontSize: 13, color: 'var(--uiws-text-faint)' }}>코드그룹이 없습니다.</div>}
              {groups.map(g => (
                <div key={g.grpCd} onClick={() => setActiveGrp(g.grpCd)}
                  style={{
                    padding: '11px 16px', cursor: 'pointer', fontSize: 13, display: 'flex', justifyContent: 'space-between', alignItems: 'center',
                    borderLeft: `3px solid ${activeGrp === g.grpCd ? 'var(--uiws-primary)' : 'transparent'}`,
                    background: activeGrp === g.grpCd ? 'var(--uiws-primary-soft)' : 'transparent',
                  }}>
                  <div>
                    <div style={{ fontWeight: 600, color: activeGrp === g.grpCd ? 'var(--uiws-primary)' : 'var(--uiws-text)' }}>{g.grpNm}</div>
                    <div style={{ fontSize: 11, color: 'var(--uiws-text-muted)' }}>{g.grpCd}</div>
                  </div>
                  <div style={{ display: 'flex', gap: 6 }} onClick={e => e.stopPropagation()}>
                    <Button variant="ghost" onClick={() => setGrpForm({ open: true, edit: g })}>수정</Button>
                    <Button variant="ghost" onClick={() => removeGroup(g.grpCd)}>삭제</Button>
                  </div>
                </div>
              ))}
            </div>
          )}
        </Panel>

        <div>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
            <div style={{ fontSize: 14, fontWeight: 600, color: 'var(--uiws-text)' }}>
              코드값 {activeGrp && <span style={{ color: 'var(--uiws-text-muted)', fontWeight: 400 }}>({activeGrp})</span>}
            </div>
            <Button onClick={() => setCodeForm({ open: true, edit: null })} disabled={!activeGrp}>+ 코드값 등록</Button>
          </div>
          {loadingCode ? <Spinner /> : (
            <DataGrid columns={codeColumns} rows={codes} rowKey={r => `${r.grpCd}:${r.codeVal}`}
              onRowClick={r => setCodeForm({ open: true, edit: r })} empty={activeGrp ? '코드값이 없습니다.' : '코드그룹을 선택하세요.'} />
          )}
        </div>
      </div>

      {grpForm.open && (
        <CodeGroupForm grp={grpForm.edit} onClose={() => setGrpForm({ open: false, edit: null })}
          onSaved={() => { setGrpForm({ open: false, edit: null }); loadGroups(keyword) }} />
      )}
      {codeForm.open && activeGrp && (
        <CodeForm grpCd={activeGrp} code={codeForm.edit} existing={codes}
          onSave={saveCodeValue}
          onClose={() => setCodeForm({ open: false, edit: null })}
          onSaved={() => setCodeForm({ open: false, edit: null })} />
      )}
    </div>
  )
}

function SelectYn({ value, onChange }: { value: string; onChange: (v: string) => void }) {
  return (
    <select value={value} onChange={e => onChange(e.target.value)}
      style={{ width: '100%', padding: '9px 12px', borderRadius: 8, fontSize: 13,
        background: 'var(--uiws-input-bg)', border: '1px solid var(--uiws-border)', color: 'var(--uiws-text)' }}>
      <option value="Y">사용</option>
      <option value="N">미사용</option>
    </select>
  )
}

function CodeGroupForm({ grp, onClose, onSaved }: { grp: CodeGrp | null; onClose: () => void; onSaved: () => void }) {
  const editing = !!grp
  const [grpCd, setGrpCd] = useState(grp?.grpCd ?? '')
  const [grpNm, setGrpNm] = useState(grp?.grpNm ?? '')
  const [useYn, setUseYn] = useState(grp?.useYn ?? 'Y')
  const [err, setErr] = useState('')

  const save = async () => {
    setErr('')
    if (!editing && !grpCd.trim()) { setErr('그룹코드는 필수입니다.'); return }
    if (!grpNm.trim()) { setErr('그룹명은 필수입니다.'); return }
    try {
      // 신규 그룹은 values 빈배열, 수정은 그룹 메타만 변경(코드값은 코드값 화면에서 관리).
      const body = { grpCd, grpNm, useYn, values: [] as Code[] }
      editing ? await updateCodeGroup(grpCd, { ...body, values: undefined as any }) : await createCodeGroup(body)
      onSaved()
    } catch (e) { setErr(friendlyError(e)) }
  }

  return (
    <Modal title={editing ? '코드그룹 수정' : '코드그룹 등록'} onClose={onClose}
      footer={<><Button variant="ghost" onClick={onClose}>취소</Button><Button onClick={save}>저장</Button></>}>
      <FormField label="그룹코드"><Input value={grpCd} onChange={setGrpCd} style={{ width: '100%', opacity: editing ? 0.6 : 1 }} /></FormField>
      <FormField label="그룹명"><Input value={grpNm} onChange={setGrpNm} style={{ width: '100%' }} /></FormField>
      <FormField label="사용 여부"><SelectYn value={useYn} onChange={setUseYn} /></FormField>
      {err && <div style={{ color: 'var(--uiws-danger)', fontSize: 13 }}>{err}</div>}
    </Modal>
  )
}

function CodeForm({ grpCd, code, existing, onSave, onClose, onSaved }: {
  grpCd: string; code: Code | null; existing: Code[]
  onSave: (val: Code, originalCodeVal: string | null) => Promise<void>
  onClose: () => void; onSaved: () => void
}) {
  const editing = !!code
  const [codeVal, setCodeVal] = useState(code?.codeVal ?? '')
  const [codeNm, setCodeNm] = useState(code?.codeNm ?? '')
  const [sortOrd, setSortOrd] = useState(String(code?.sortOrd ?? 0))
  const [useYn, setUseYn] = useState(code?.useYn ?? 'Y')
  const [err, setErr] = useState('')

  const save = async () => {
    setErr('')
    if (!editing && !codeVal.trim()) { setErr('코드값은 필수입니다.'); return }
    if (!codeNm.trim()) { setErr('코드명은 필수입니다.'); return }
    if (!editing && existing.some(c => c.codeVal === codeVal.trim())) { setErr('이미 존재하는 코드값입니다.'); return }
    try {
      const val: Code = { grpCd, codeVal, codeNm, sortOrd: Number(sortOrd) || 0, useYn }
      await onSave(val, editing ? (code as Code).codeVal : null)
      onSaved()
    } catch (e) { setErr(friendlyError(e)) }
  }

  return (
    <Modal title={editing ? '코드값 수정' : '코드값 등록'} onClose={onClose}
      footer={<><Button variant="ghost" onClick={onClose}>취소</Button><Button onClick={save}>저장</Button></>}>
      <FormField label="그룹코드"><Input value={grpCd} onChange={() => {}} style={{ width: '100%', opacity: 0.6 }} /></FormField>
      <FormField label="코드값"><Input value={codeVal} onChange={setCodeVal} style={{ width: '100%', opacity: editing ? 0.6 : 1 }} /></FormField>
      <FormField label="코드명"><Input value={codeNm} onChange={setCodeNm} style={{ width: '100%' }} /></FormField>
      <FormField label="정렬순서"><Input type="number" value={sortOrd} onChange={setSortOrd} style={{ width: '100%' }} /></FormField>
      <FormField label="사용 여부"><SelectYn value={useYn} onChange={setUseYn} /></FormField>
      {err && <div style={{ color: 'var(--uiws-danger)', fontSize: 13 }}>{err}</div>}
    </Modal>
  )
}
