// RecordBook — 기록부 3개 화면
// main / detail / defectOnly

// Status helper
function getStatus(s, g, defects) {
  if (g && (g.isFreeform || g.id === 'g4' || g.short === '기타사항')) {
    const etcBad = defects ? defects.filter(d => d.group === g.name).length : (s ? s.bad : 0);
    if (etcBad > 0) return { key: 'bad', label: `⚠️특이사항 ${etcBad}건`, color: '#e74c3c', border: '#fadbd8' };
    return { key: 'ok', label: '✅이상없음', color: '#2ecc71', border: '#abebc6' };
  }

  if (!s || s.total === 0) return { key: 'scheduled', label: '점검예정', color: '#8a8880', border: '#e5e3dc' };

  const isComplete = s.done >= s.total;
  const valid = s.valid !== undefined ? s.valid : s.done; // RecordDetailScreen 등 valid 미전달 시 대비 호환성 유지

  if (!isComplete) return { key: 'incomplete', label: '점검 미완료', color: '#f06e00', border: '#f8c471' };
  if (s.bad > 0) return { key: 'bad', label: `⚠️불량 ${s.bad}개`, color: '#e74c3c', border: '#fadbd8' };
  if (valid === 0) return { key: 'scheduled', label: '점검예정', color: '#8a8880', border: '#e5e3dc' };
  return { key: 'ok', label: '✅이상없음', color: '#2ecc71', border: '#abebc6' };
}

const SUB_CATEGORY_MAP = {
  // 1. 소화기구 및 자동소화장치
    
  // 2. 옥내외 소화전설비
  '2-A': '수원',
  '2-C': '가압송수장치',
  '2-D': '송수구',
  '2-E': '배관',
  '2-F': '함 및 방수구 등',
  '2-H': '제어반',

  // 3. 스프링클러, 물분무 등소화설비
  '3-A': '수원',
  '3-B': '수원 (수조 표시)',
  '3-D': '유수검지장치',
  '3-E': '제어밸브 등',
  '3-F': '배관',
  '3-G': '기동장치',
  '3-H': '헤드',
  '3-K': '제어반',
  '6-I': '배수설비',
  '8-D': '가압송수장치',
  '8-G': '저장탱크',
  '8-J': '호스릴방식',

  // 4. 가스계 (이산화탄소, 할론, 분말 등)
  '9-A': '저장용기',
  '9-B': '저장용기',
  '9-C': '기동장치',
  '9-E': '배관 등',
  '9-G': '분사헤드 및 호스릴방식',
  '9-N': '안전시설 등',

  // 5. 자동화재탐지설비 등
  '15-B': '수신기',
  '15-D': '감지기',
  '15-E': '음향장치',
  '15-F': '시각경보장치',
  '15-G': '발신기',
  '15-H': '수신기 (전원)',
  '16-A': '비상방송설비',
  '17-A': '자동화재속보설비',

  // 6. 피난기구, 유도등 등
  '20-A': '피난기구',
  '21-A': '유도등',
  '21-B': '유도표지',
  '22-A': '비상조명등',
  '22-B': '휴대용비상조명등',

  // 7. 제연설비 등
  '24-A': '제연구역의 구획',
  '24-B': '배출구 및 유입구',
  '24-F': '기동장치',
  '25-E': '외기취입구',
  '25-F': '제연구역의 출입문',
  '25-G': '수동기동장치',

  // 8. 연결송수관, 연결살수설비
  '26-A': '연결송수관 송수구',
  '26-C': '방수구',
  '26-D': '방수기구함',
  '27-A': '연결살수설비 송수구',
  '27-D': '연결살수설비 헤드',

  // 9. 비상콘센트, 무선통신보조, 지하구
  '28-C': '비상콘센트',
  '28-D': '보호함',
  '29-B': '무선기기접속단자',
  '30-B': '지하구(연소방지설비)',
  '30-C': '지하구(연소방지설비)',
  '30-D': '방화벽',

  // 10. 기타사항 (방화시설, 방염)
  '31-A': '피난·방화시설',
  '31-B': '방염',
  '31-C': '방염',
  
  // 11. 화기취급감독
  '111-A': '위험물 저장·취급시설',
  '122-A': '화기시설',
  '133-A': '가연성 가스시설',
  '144-A': '전기시설',
  
  // 그 외 코드가 추가될 경우를 대비한 기본값
  'default': '일반 점검항목'
};

// ──────────────────────────────────────────────
// 화면 1 · 기록부 메인
// ──────────────────────────────────────────────
// ──────────────────────────────────────────────
// 관계인 서명 패드 (바텀 시트 모달)
// ──────────────────────────────────────────────
function SignaturePadModal({ onSave, onCancel, saving, err }) {
  const canvasRef  = React.useRef(null);
  const [drawing, setDrawing]   = React.useState(false);
  const [hasStroke, setHasStroke] = React.useState(false);

  const getPos = (e, canvas) => {
    const rect = canvas.getBoundingClientRect();
    const src  = e.touches ? e.touches[0] : e;
    return {
      x: (src.clientX - rect.left) * (canvas.width  / rect.width),
      y: (src.clientY - rect.top)  * (canvas.height / rect.height),
    };
  };

  const startDraw = (e) => {
    e.preventDefault();
    const canvas = canvasRef.current;
    const ctx = canvas.getContext('2d');
    const pos = getPos(e, canvas);
    ctx.beginPath();
    ctx.moveTo(pos.x, pos.y);
    setDrawing(true);
  };

  const draw = (e) => {
    if (!drawing) return;
    e.preventDefault();
    const canvas = canvasRef.current;
    const ctx = canvas.getContext('2d');
    const pos = getPos(e, canvas);
    ctx.lineTo(pos.x, pos.y);
    ctx.strokeStyle = '#1a1a18';
    ctx.lineWidth   = 2.5;
    ctx.lineCap     = 'round';
    ctx.lineJoin    = 'round';
    ctx.stroke();
    setHasStroke(true);
  };

  const endDraw = () => setDrawing(false);

  const clear = () => {
    canvasRef.current.getContext('2d')
      .clearRect(0, 0, canvasRef.current.width, canvasRef.current.height);
    setHasStroke(false);
  };

  const save = () => {
    onSave(canvasRef.current.toDataURL('image/png'));
  };

  return ReactDOM.createPortal(
    <div style={{
      position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, zIndex: 9999,
      background: 'rgba(0,0,0,0.55)',
      display: 'flex', alignItems: 'flex-end',
    }}>
      <div style={{
        width: '100%', background: '#fff',
        borderRadius: '20px 20px 0 0',
        padding: '20px 16px 36px',
        boxShadow: '0 -4px 24px rgba(0,0,0,.14)',
      }}>
        <div style={{ fontSize: 15, fontWeight: 800, color: '#1a1a18', marginBottom: 3 }}>
          관계인 서명
        </div>
        <div style={{ fontSize: 12, color: '#8a8880', marginBottom: 14 }}>
          아래 공간에 손가락으로 서명해 주세요
        </div>
        {/* 캔버스 */}
        <div style={{ position: 'relative', border: '1.5px solid #d4d1c7', borderRadius: 10, overflow: 'hidden', background: '#fbf9f3' }}>
          <canvas
            ref={canvasRef}
            width={600} height={180}
            onMouseDown={startDraw} onMouseMove={draw} onMouseUp={endDraw} onMouseLeave={endDraw}
            onTouchStart={startDraw} onTouchMove={draw} onTouchEnd={endDraw}
            style={{ width: '100%', height: 150, display: 'block', cursor: 'crosshair', touchAction: 'none' }}
          />
          {!hasStroke && (
            <div style={{
              position: 'absolute', inset: 0, pointerEvents: 'none',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              color: '#c8c4bc', fontSize: 13, fontWeight: 600,
            }}>
              여기에 서명하세요
            </div>
          )}
        </div>
        {/* 에러 */}
        {err && (
          <div style={{ fontSize: 12, color: '#cc2222', fontWeight: 600, marginTop: 8, textAlign: 'center' }}>
            ⚠️ {err}
          </div>
        )}
        {/* 버튼 */}
        <div style={{ display: 'flex', gap: 8, marginTop: 12 }}>
          <button onClick={clear} style={sigBtnSecondary}>지우기</button>
          <button onClick={onCancel} style={sigBtnSecondary}>취소</button>
          <button
            onClick={save}
            disabled={!hasStroke || saving}
            style={{
              ...sigBtnPrimary,
              background: (!hasStroke || saving) ? '#9db4ea' : '#2563EB',
              cursor: (!hasStroke || saving) ? 'not-allowed' : 'pointer',
            }}
          >
            {saving ? '저장 중…' : '서명 완료'}
          </button>
        </div>
      </div>
    </div>,
    document.body
  );
}

const sigBtnSecondary = {
  flex: 1, height: 46, border: '1px solid #d4d1c7', borderRadius: 10,
  background: '#fff', color: '#5a5a55', fontSize: 13, fontWeight: 700,
  fontFamily: 'inherit', cursor: 'pointer', WebkitTapHighlightColor: 'transparent',
};
const sigBtnPrimary = {
  flex: 2, height: 46, border: 'none', borderRadius: 10,
  color: '#fff', fontSize: 13, fontWeight: 800,
  fontFamily: 'inherit', WebkitTapHighlightColor: 'transparent',
  transition: 'background 200ms',
};

// ──────────────────────────────────────────────
// 관계인 서명 섹션 (RecordMainScreen 내 삽입)
// ──────────────────────────────────────────────
function OwnerSignatureSection({ monthly, year, month, onSignComplete }) {
  const [showPad, setShowPad]   = React.useState(false);
  const [saving,  setSaving]    = React.useState(false);
  const [saved,   setSaved]     = React.useState(false);
  const [err,     setErr]       = React.useState('');

  // completed_at 없으면 표시 안 함
  if (!monthly?.report?.completed_at) return null;

  const isSigned  = saved || !!monthly?.report?.signed_at;
  const signedDate = monthly?.report?.signed_at
    ? new Date(monthly.report.signed_at).toLocaleDateString('ko-KR', { year: 'numeric', month: 'long', day: 'numeric' })
    : '방금 서명';

  const handleSave = async (dataUrl) => {
    setSaving(true);
    setErr('');
    try {
      const token = localStorage.getItem('soritalk:token') || localStorage.getItem('token');
      const res = await fetch(`/api/monthly/${year}/${month}/sign`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${token}`,
        },
        credentials: 'include',
        body: JSON.stringify({ signatureImage: dataUrl }),
      });
      const d = await res.json();
      if (!d.success) throw new Error(d.error || '서명 저장 실패');
      setSaved(true);
      setShowPad(false);
      onSignComplete && onSignComplete();
    } catch (e) {
      setErr(e.message);
    } finally {
      setSaving(false);
    }
  };

  return (
    <div style={{ marginBottom: 8 }}>
      <div style={{
        background: isSigned ? '#1a3a1a' : '#fff',
        border: `1.5px solid ${isSigned ? '#4caf50' : '#f0a500'}`,
        borderRadius: 12, padding: '14px 16px',
        display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12,
      }}>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 13, fontWeight: 800, color: isSigned ? '#4caf50' : '#1a1a18' }}>
            {isSigned ? '✅ 관계인 서명 완료' : '✍️ 관계인 서명 요청'}
          </div>
          <div style={{ fontSize: 11.5, marginTop: 2, color: isSigned ? '#4caf5099' : '#8a8880' }}>
            {isSigned ? signedDate : '점검 완료를 확인하고 서명해 주세요'}
          </div>
        </div>
        {!isSigned && (
          <button
            onClick={() => { setErr(''); setShowPad(true); }}
            style={{
              background: '#f0a500', color: '#fff', border: 'none',
              borderRadius: 8, padding: '9px 16px', flexShrink: 0,
              fontSize: 12.5, fontWeight: 800, fontFamily: 'inherit',
              cursor: 'pointer', WebkitTapHighlightColor: 'transparent',
            }}
          >
            서명하기 클릭
          </button>
        )}
      </div>
      {err && (
        <div style={{ fontSize: 11.5, color: '#cc2222', fontWeight: 600, marginTop: 5, paddingLeft: 4 }}>
          {err}
        </div>
      )}
      {showPad && (
        <SignaturePadModal
          onSave={handleSave}
          onCancel={() => { setShowPad(false); setErr(''); }}
          saving={saving}
          err={err}
        />
      )}
    </div>
  );
}

// ──────────────────────────────────────────────
// 화면 1 · 기록부 메인
// ──────────────────────────────────────────────
function RecordMainScreen({ year, month, onMonthChange, onPick, onPdf, onFixDefect, onDeleteDefect, onSaveReport, onComplete, onSignComplete, theme, monthly, values = {}, statsData = [], reports = {}, onReportsChange, building, account }) {
  const t = theme || THEME;
  const months = Array.from({ length: 12 }, (_, i) => i + 1);
  const defectsData = monthly?.defects || [];
  const totalBad = defectsData.length;
  const isLocked = (() => {
    const now = new Date();
    return year < now.getFullYear() ||
      (year === now.getFullYear() && month < now.getMonth() + 1) ||
      !!monthly?.report?.is_locked;
  })();
  const [showSignReset, setShowSignReset] = React.useState(false);

  const handleSaveClick = () => {
    if (monthly?.report?.signed_at) {
      setShowSignReset(true);
    } else {
      onSaveReport && onSaveReport(reports);
    }
  };

  return (
    <div style={{ padding: '16px 16px 80px' }}>
      {/* 1. 월 선택 */}
      <div style={{
        background: '#fff', border: '1px solid #ece9e0',
        borderRadius: 14, padding: '14px 16px', marginBottom: 14,
      }}>
        <div style={{ fontSize: 15, fontWeight: 800, color: '#1a1a18', marginBottom: 10 }}>{building?.name || BUILDING?.name || ''}</div>
        <div style={{
          display: 'flex', gap: 8, alignItems: 'center',
          background: '#fbf9f3', border: '1px solid #ece9e0',
          borderRadius: 10, padding: '10px 12px',
        }}>
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none">
            <rect x="4" y="5" width="16" height="16" rx="2" stroke="#5a5a55" strokeWidth="1.8"/>
            <path d="M4 10h16M9 3v4M15 3v4" stroke="#5a5a55" strokeWidth="1.8" strokeLinecap="round"/>
          </svg>
          <select value={year} onChange={e => onMonthChange(+e.target.value, month)}
            style={{ border: 'none', background: 'transparent', fontSize: 13, fontWeight: 700, fontFamily: 'inherit', color: '#1a1a18', outline: 'none', cursor: 'pointer' }}>
            {Array.from({length:3},(_,i)=>new Date().getFullYear()-2+i).map(y => <option key={y} value={y}>{y}년</option>)}
          </select>
          <select value={month} onChange={e => onMonthChange(year, +e.target.value)}
            style={{ border: 'none', background: 'transparent', fontSize: 13, fontWeight: 700, fontFamily: 'inherit', color: '#1a1a18', outline: 'none', cursor: 'pointer', flex: 1 }}>
            {months.map(m => <option key={m} value={m}>{m}월</option>)}
          </select>
        </div>
      </div>

      {/* 2. 4개 대분류 카드 (홈화면과 동일) */}
      <div style={{ fontSize: 14, fontWeight: 800, color: '#1a1a18', marginBottom: 10 }}>{month}월 점검 현황</div>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10, marginBottom: 16 }}>
        {(Array.isArray(statsData) ? statsData : []).map((item, i) => {
          const colorMap = { '#cc2222': '#fadbd8', '#15803d': '#abebc6', '#f06e00': '#f8c471', '#2563eb': '#bfdbfe', '#8a8880': '#e5e3dc' };
          const border = colorMap[item.color] || '#e5e3dc';
          return (
            <div key={i} style={{
              background: '#fff', border: `1.5px solid ${border}`,
              borderRadius: 14, padding: '14px',
              display: 'flex', flexDirection: 'column', gap: 6, minHeight: 80,
            }}>
              <div style={{ fontSize: 13, fontWeight: 700, color: '#1a1a18' }}>{item.label}</div>
              <div style={{ fontSize: 13, fontWeight: 800, color: item.color }}>{item.sub}</div>
            </div>
          );
        })}
      </div>

      {/* 3. 불량 리스트 */}
      <div style={{ background: '#fff', border: '1px solid #ece9e0', borderRadius: 14, padding: '14px 16px', marginBottom: 12 }}>
        <div style={{ fontSize: 13, fontWeight: 800, color: '#1a1a18', marginBottom: 10 }}>
          불량 항목 {totalBad > 0 && <span style={{ color: '#cc2222' }}>({totalBad}건)</span>}
        </div>
        {defectsData.length === 0 ? (
          <EmptyState icon="✅" text="불량 항목이 없습니다" />
        ) : (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            {defectsData.map(d => (
              <DefectRow key={d.id} d={d}
                onFix={() => onFixDefect && onFixDefect(d.id)}
                onDelete={() => onDeleteDefect && onDeleteDefect(d.id)} />
            ))}
          </div>
        )}
      </div>

      {/* 4. 조치 사항 */}
      <div style={{ background: '#fff', border: '1px solid #ece9e0', borderRadius: 14, padding: '14px 16px', marginBottom: 12 }}>
        <div style={{ fontSize: 13, fontWeight: 800, color: '#1a1a18', marginBottom: 10 }}>조치 사항</div>
        <ActionDetailForm reports={reports} onChange={onReportsChange} />
      </div>

      {/* 5. 보고 입력 폼 */}
      <div style={{ background: '#fff', border: '1px solid #ece9e0', borderRadius: 14, padding: '14px 16px', marginBottom: 12 }}>
        <div style={{ fontSize: 13, fontWeight: 800, color: '#1a1a18', marginBottom: 10 }}>불량사항 개선 보고</div>
        <ReportForm reports={reports} onChange={onReportsChange} month={month} building={building} account={account} />
      </div>

      {/* 6. 저장/완료/서명 — 잠긴 월은 숨김 */}
      {isLocked ? (
        <div style={{
          background: '#f8f6f0', border: '1.5px solid #d4d1c7',
          borderRadius: 12, padding: '14px 16px', marginBottom: 8,
          display: 'flex', alignItems: 'center', gap: 10,
        }}>
          <span style={{ fontSize: 18 }}>🔒</span>
          <div>
            <div style={{ fontSize: 13, fontWeight: 800, color: '#5a5a55' }}>잠긴 월 — 읽기 전용</div>
            <div style={{ fontSize: 11.5, color: '#8a8880', marginTop: 2 }}>지난 월은 수정할 수 없습니다.</div>
          </div>
        </div>
      ) : (
        <>
          <div style={{ marginBottom: 8 }}>
            <button onClick={handleSaveClick} style={{
              width: '100%', padding: '14px', background: '#cc2222', color: '#fff',
              border: 'none', borderRadius: 12,
              fontSize: 14, fontWeight: 800, fontFamily: 'inherit',
              cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
              WebkitTapHighlightColor: 'transparent',
            }}>보고 내용 저장</button>
          </div>
          <div style={{ marginBottom: 8 }}>
            <button onClick={() => onComplete && onComplete()} style={{
              width: '100%', padding: '14px',
              background: monthly?.report?.completed_at ? '#1a3a1a' : '#1a2a3a',
              color: monthly?.report?.completed_at ? '#4caf50' : '#58a6ff',
              border: monthly?.report?.completed_at ? '1.5px solid #4caf50' : '1.5px solid #58a6ff',
              borderRadius: 12, fontSize: 14, fontWeight: 700, fontFamily: 'inherit',
              cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
              WebkitTapHighlightColor: 'transparent',
            }}>
              {monthly?.report?.completed_at ? '완료됨 · 재발송' : '안전관리 완료'}
            </button>
          </div>
          {showSignReset && ReactDOM.createPortal(
            <div style={{
              position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, zIndex: 9999,
              background: 'rgba(0,0,0,0.6)',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
            }}>
              <div style={{
                background: '#1c2130', border: '1px solid #30363d',
                borderRadius: 14, padding: '24px 20px', width: 300, maxWidth: '90vw',
              }}>
                <div style={{ fontSize: 15, fontWeight: 800, color: '#e6edf3', marginBottom: 10 }}>
                  ⚠️ 관계인 서명 초기화
                </div>
                <div style={{ fontSize: 13, color: '#8b949e', marginBottom: 20, lineHeight: 1.7 }}>
                  수정되면 관계인 서명이 초기화되고<br/>
                  재서명 요청 SMS가 발송됩니다.<br/>
                  진행하시겠습니까?
                </div>
                <div style={{ display: 'flex', gap: 8 }}>
                  <button onClick={() => setShowSignReset(false)} style={{
                    flex: 1, padding: '10px', border: '1px solid #30363d',
                    borderRadius: 8, background: '#21262d', color: '#8b949e',
                    fontSize: 14, cursor: 'pointer', fontFamily: 'inherit',
                  }}>아니오</button>
                  <button onClick={() => { setShowSignReset(false); onSaveReport && onSaveReport(reports, true); }} style={{
                    flex: 1, padding: '10px', border: 'none',
                    borderRadius: 8, background: '#1f6feb', color: '#fff',
                    fontSize: 14, fontWeight: 800, cursor: 'pointer', fontFamily: 'inherit',
                  }}>예</button>
                </div>
              </div>
            </div>,
            document.body
          )}
          <OwnerSignatureSection monthly={monthly} year={year} month={month} onSignComplete={onSignComplete} />
        </>
      )}
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginTop: 8 }}>
        <button onClick={() => onPdf('work')} disabled={!monthly?.report?.completed_at} style={{
          width: '100%', padding: '13px',
          background: monthly?.report?.completed_at ? '#fff' : '#f5f5f3',
          border: `1.5px solid ${monthly?.report?.completed_at ? '#d4d1c7' : '#e5e3dc'}`,
          borderRadius: 12, fontSize: 13.5, fontWeight: 700,
          color: monthly?.report?.completed_at ? '#1a1a18' : '#b0afa9',
          display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
          cursor: monthly?.report?.completed_at ? 'pointer' : 'not-allowed',
          fontFamily: 'inherit', WebkitTapHighlightColor: 'transparent',
        }}>업무수행기록표 출력 (별지 제12서식)</button>
        <button onClick={() => onPdf('inspect')} disabled={!monthly?.report?.completed_at} style={{
          width: '100%', padding: '13px',
          background: monthly?.report?.completed_at ? '#fff' : '#f5f5f3',
          border: `1.5px solid ${monthly?.report?.completed_at ? '#d4d1c7' : '#e5e3dc'}`,
          borderRadius: 12, fontSize: 13.5, fontWeight: 700,
          color: monthly?.report?.completed_at ? '#1a1a18' : '#b0afa9',
          display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
          cursor: monthly?.report?.completed_at ? 'pointer' : 'not-allowed',
          fontFamily: 'inherit', WebkitTapHighlightColor: 'transparent',
        }}>외관점검표 출력 (별지 제6호)</button>
      </div>
    </div>
  );
}


// ──────────────────────────────────────────────
// 화면 2 · 기록부 월간 상세
// ──────────────────────────────────────────────
function RecordDetailScreen({ groupId, year, month, reports, onReportsChange, onFixDefect, onDefectOnly, onPdf, theme, monthly }) {
  const t = theme || THEME;
  const group = INSPECTION_GROUPS.find(g => g.id === groupId);
  
  const statusData = monthly?.status || {};
  const defectsData = monthly?.defects || [];
  const defects = defectsData.filter(d => !group || d.group === group.name);
  const totalBad = Object.values(statusData).reduce((a, s) => a + (s.bad || 0), 0);

  return (
    <div style={{ padding: '14px 16px 24px' }}>
      {/* 섹션 1: 점검 현황 요약 */}
      <div style={{
        background: '#fff', border: '1px solid #ece9e0',
        borderRadius: 14, padding: '14px 16px', marginBottom: 12,
      }}>
        <SectionTitle>점검 현황 요약</SectionTitle>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 7 }}>
          {['g1', 'g2', 'g3', 'g4'].map(gid => {
            const g = INSPECTION_GROUPS.find(x => x.id === gid);
            const s = statusData[gid];
            const st = getStatus(s, g, defectsData);
            return (
              <div key={gid} style={{
                display: 'flex', alignItems: 'center', justifyContent: 'space-between',
                padding: '7px 0',
              }}>
                <span style={{ fontSize: 13, color: '#1a1a18', fontWeight: 600, whiteSpace: 'nowrap' }}>
                  {g.short}
                </span>
                <span style={{ fontSize: 13, color: st.color, fontWeight: 700, whiteSpace: 'nowrap' }}>
                  {st.label}
                </span>
              </div>
            );
          })}
        </div>
        <div style={{
          marginTop: 10, paddingTop: 12, borderTop: '1px solid #ece9e0',
          display: 'flex', justifyContent: 'space-between', alignItems: 'center',
        }}>
          <span style={{ fontSize: 13, fontWeight: 700, color: '#5a5a55' }}>총 불량건수</span>
          <span style={{
            fontSize: 18, fontWeight: 800,
            color: totalBad ? '#cc2222' : '#15803d',
            letterSpacing: '-0.02em',
          }}>
            {totalBad}건
          </span>
        </div>
      </div>

      {/* 섹션 2: 외관점검 불량 항목 */}
      <div style={{
        background: '#fff', border: '1px solid #ece9e0',
        borderRadius: 14, padding: '14px 16px', marginBottom: 12,
      }}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 10 }}>
          <SectionTitle noMargin>외관점검 불량 항목</SectionTitle>
          <button
            onClick={onDefectOnly}
            style={{
              background: 'transparent', border: 'none', padding: 0,
              fontSize: 11.5, fontWeight: 700, color: '#cc2222', cursor: 'pointer',
              fontFamily: 'inherit', display: 'inline-flex', alignItems: 'center', gap: 3,
            }}
          >
            불량만 모아보기 →
          </button>
        </div>
        {defects.length === 0 ? (
          <EmptyState icon="✅" text="불량 항목이 없습니다" />
        ) : (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            {defects.map(d => (
              <DefectRow key={d.id} d={d} onFix={() => onFixDefect(d.id)} onDelete={() => onDeleteDefect && onDeleteDefect(d.id)} />
            ))}
          </div>
        )}
      </div>

      {/* 섹션 3: 불량 기록 상세 */}
      <div style={{
        background: '#fff', border: '1px solid #ece9e0',
        borderRadius: 14, padding: '14px 16px', marginBottom: 12,
      }}>
        <SectionTitle>불량 기록 상세</SectionTitle>
        {defects.length === 0 ? (
          <EmptyState icon="📭" text="이번 달 불량 기록 없음" />
        ) : (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
            {defects.map(d => <DefectDetailCard key={d.id} d={d} />)}
          </div>
        )}
      </div>

      {/* 섹션 4: 불량사항 개선 보고 */}
      <div style={{
        background: '#fff', border: '1px solid #ece9e0',
        borderRadius: 14, padding: '14px 16px', marginBottom: 12,
      }}>
        <SectionTitle>불량사항 개선 보고</SectionTitle>
        <ReportForm reports={reports} onChange={onReportsChange} month={month} />
      </div>

      {/* 섹션 5: 사진 기록 */}
      <div style={{
        background: '#fff', border: '1px solid #ece9e0',
        borderRadius: 14, padding: '14px 16px', marginBottom: 12,
      }}>
        <SectionTitle>사진 기록 <span style={{ fontSize: 10.5, color: '#8a8880', fontWeight: 600 }}>· 월 5장 제한</span></SectionTitle>
        <PhotoGrid photos={reports.photos || []} />
      </div>

      {/* 하단 액션 */}
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginTop: 16 }}>
        <button style={{
          width: '100%', height: 50, background: t.brand, color: '#fff',
          border: 'none', borderRadius: 12,
          fontSize: 14, fontWeight: 800, fontFamily: 'inherit',
          cursor: 'pointer', letterSpacing: '-0.01em',
          display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
          boxShadow: `0 4px 12px ${t.brand}55`,
          WebkitTapHighlightColor: 'transparent',
        }}>
          💾 저장
        </button>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
          <button onClick={() => onPdf('work')} style={pdfBtnStyle}>📄 업무수행기록표</button>
          <button onClick={() => onPdf('inspect')} style={pdfBtnStyle}>📋 외관점검표</button>
        </div>
      </div>
    </div>
  );
}

const pdfBtnStyle = {
  padding: '12px 6px', background: '#fff',
  border: '1.5px solid #d4d1c7', borderRadius: 12,
  fontSize: 12.5, fontWeight: 700, color: '#1a1a18',
  display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 5,
  cursor: 'pointer', fontFamily: 'inherit',
  WebkitTapHighlightColor: 'transparent',
};

// ──────────────────────────────────────────────
// 화면 3 · 불량 모아보기
// ──────────────────────────────────────────────
function DefectOnlyScreen({ onFix, theme, monthly }) {
  const t = theme || THEME;
  const source = monthly?.defects || [];
  const [list, setList] = React.useState(source);
  
  React.useEffect(() => { setList(source); }, [monthly]);

  const handleFix = (id) => {
    setList(prev => prev.filter(d => d.id !== id));
    onFix && onFix(id);
  };
  return (
    <div style={{ padding: '14px 16px 24px' }}>
      <div style={{
        background: '#fef2f2', border: '1px solid #f4b4b4',
        borderRadius: 12, padding: '12px 14px', marginBottom: 14,
        display: 'flex', alignItems: 'center', gap: 10,
      }}>
        <div style={{
          width: 32, height: 32, borderRadius: '50%',
          background: '#cc2222', color: '#fff',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          fontWeight: 800, fontSize: 13, flexShrink: 0,
        }}>
          {list.length}
        </div>
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 13, fontWeight: 800, color: '#cc2222', letterSpacing: '-0.01em' }}>
            외관점검 불량 {list.length}건
          </div>
          <div style={{ fontSize: 11.5, color: '#b44848', fontWeight: 500, marginTop: 2 }}>
            조치 후 [양호로 변경]을 눌러주세요
          </div>
        </div>
      </div>

      {list.length === 0 ? (
        <div style={{
          background: '#fff', border: '1px solid #ece9e0',
          borderRadius: 14, padding: 32,
        }}>
          <EmptyState icon="✅" text="이번 달 불량 항목 없음" />
        </div>
      ) : (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
          {list.map((d, i) => {
            const isEtc = d.itemNo && String(d.itemNo).endsWith('-etc');
            const title = isEtc ? '기타 특이사항' : d.itemText;
            const subKey = d.itemNo ? String(d.itemNo).split('-').slice(0, 2).join('-') : '';
            const subTitle = SUB_CATEGORY_MAP[subKey] || SUB_CATEGORY_MAP['default'];
            return (
              <div key={d.id} style={{
                background: '#fff', border: '1.5px solid #f4b4b4',
                borderRadius: 14, padding: '14px',
                animation: `fadeUp 280ms ${i * 40}ms cubic-bezier(.4,1.2,.4,1) both`,
              }}>
                <div style={{
                  fontSize: 11, color: '#8a8880', fontWeight: 600,
                  marginBottom: 4, letterSpacing: '-0.01em',
                }}>
                  {d.group} <span style={{ color: '#d4d1c7' }}>›</span> {d.category}
                  {!isEtc && subTitle && (
                    <> <span style={{ color: '#d4d1c7' }}>›</span> {subTitle}</>
                  )}
                </div>
                <div style={{
                  fontSize: 13.5, fontWeight: 700, color: '#1a1a18',
                  lineHeight: 1.4, marginBottom: 4,
                  display: 'flex', alignItems: 'flex-start', gap: 6,
                }}>
                  {!isEtc && (
                    <span style={{
                      background: '#f1efea', color: '#5a5a55',
                      fontSize: 11, fontWeight: 800,
                      padding: '3px 7px', borderRadius: 5,
                      whiteSpace: 'nowrap', flexShrink: 0,
                      marginTop: 1,
                    }}>
                      {d.itemNo}
                    </span>
                  )}
                  <span style={{ flex: 1, minWidth: 0 }}>{title}</span>
                </div>

                {d.location && !isEtc && (
                  <div style={{ fontSize: 11.5, color: '#8a8880', fontWeight: 500, marginBottom: 10 }}>
                    📍 {d.location}
                  </div>
                )}
              <button
                onClick={() => handleFix(d.id)}
                style={{
                  width: '100%', padding: '10px',
                  background: '#fff', border: '1.5px solid #15803d',
                  borderRadius: 10, color: '#15803d',
                  fontSize: 12.5, fontWeight: 800, fontFamily: 'inherit',
                  cursor: 'pointer',
                  display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 5,
                  WebkitTapHighlightColor: 'transparent',
                  transition: 'background 180ms',
                }}
                onMouseEnter={e => e.currentTarget.style.background = '#f0faf4'}
                onMouseLeave={e => e.currentTarget.style.background = '#fff'}
              >
                <svg width="13" height="13" viewBox="0 0 24 24" fill="none">
                  <path d="M5 12.5l5 5 9-10" stroke="#15803d" strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round"/>
                </svg>
                양호로 변경
              </button>
            </div>
            );
          })}
        </div>
      )}
    </div>
  );
}

// ──────────────────────────────────────────────
// Sub-components
// ──────────────────────────────────────────────
function SectionTitle({ children, noMargin }) {
  return (
    <div style={{
      fontSize: 12, fontWeight: 800, color: '#1a1a18',
      letterSpacing: '-0.01em',
      marginBottom: noMargin ? 0 : 10,
      textTransform: 'none',
    }}>
      {children}
    </div>
  );
}

function EmptyState({ icon, text }) {
  return (
    <div style={{
      textAlign: 'center', padding: '18px 0',
      color: '#8a8880', fontSize: 13, fontWeight: 600,
    }}>
      <div className="category-icon" style={{ fontSize: 24, marginBottom: 6 }}>{icon}</div>
      {text}
    </div>
  );
}

function DefectRow({ d, onFix, onDelete }) {
  const isDirect = d.type === 'direct';
  const isEtc = d.itemNo && String(d.itemNo).endsWith('-etc');
  const title = isDirect ? d.itemText : (isEtc ? '기타 특이사항' : d.itemText);
  const subKey = d.itemNo ? String(d.itemNo).split('-').slice(0, 2).join('-') : '';
  const subTitle = SUB_CATEGORY_MAP[subKey] || SUB_CATEGORY_MAP['default'];
  return (
    <div style={{
      background: '#fef7f7', border: '1px solid #f4cccc',
      borderRadius: 10, padding: '10px 12px',
      display: 'flex', alignItems: 'center', gap: 10,
    }}>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 10.5, color: '#b44848', fontWeight: 600, marginBottom: 2 }}>
          {d.group} › {isDirect ? '직접 입력' : d.category}
          {!isDirect && !isEtc && subTitle && ` › ${subTitle}`}
        </div>
        <div style={{ fontSize: 12.5, color: '#1a1a18', fontWeight: 600, lineHeight: 1.35 }}>
          {!isDirect && !isEtc && <span style={{ color: '#8a8880', fontWeight: 700 }}>{d.itemNo}</span>} {title}
        </div>

      </div>
      {isDirect ? (
        <button onClick={onDelete} style={{
          background: '#fff', border: '1px solid #cc2222',
          borderRadius: 8, padding: '7px 10px',
          fontSize: 11, fontWeight: 800, color: '#cc2222',
          fontFamily: 'inherit', cursor: 'pointer', flexShrink: 0,
          whiteSpace: 'nowrap', WebkitTapHighlightColor: 'transparent',
        }}>삭제</button>
      ) : (
        <button onClick={onFix} style={{
          background: '#fff', border: '1px solid #15803d',
          borderRadius: 8, padding: '7px 10px',
          fontSize: 11, fontWeight: 800, color: '#15803d',
          fontFamily: 'inherit', cursor: 'pointer', flexShrink: 0,
          whiteSpace: 'nowrap', WebkitTapHighlightColor: 'transparent',
        }}>양호로</button>
      )}
    </div>
  );
}

function DefectDetailCard({ d }) {
  const isEtc = d.itemNo && String(d.itemNo).endsWith('-etc');
  const title = isEtc ? '기타 특이사항' : d.itemText;
  const subKey = d.itemNo ? String(d.itemNo).split('-').slice(0, 2).join('-') : '';
  const subTitle = SUB_CATEGORY_MAP[subKey] || SUB_CATEGORY_MAP['default'];
  return (
    <div style={{
      border: '1px solid #ece9e0', borderRadius: 10, padding: 12,
      background: '#fbf9f3',
    }}>
      <div style={{ fontSize: 11, color: '#8a8880', fontWeight: 600, marginBottom: 3 }}>
        {d.group} › {d.category}
        {!isEtc && subTitle && ` › ${subTitle}`}
      </div>
      <div style={{ fontSize: 13, color: '#1a1a18', fontWeight: 700, lineHeight: 1.4, marginBottom: 8 }}>
        {title}
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'auto 1fr', gap: '4px 10px', fontSize: 12 }}>
        {!isEtc && <span style={{ color: '#8a8880', fontWeight: 600 }}>위치</span>}
        {!isEtc && <span style={{ color: '#1a1a18', fontWeight: 500 }}>{d.location || '-'}</span>}
        <span style={{ color: '#8a8880', fontWeight: 600 }}>발견</span>
        <span style={{ color: '#1a1a18', fontWeight: 500 }}>{d.foundAt}</span>

        {d.actionNote && <>
          <span style={{ color: '#8a8880', fontWeight: 600 }}>조치</span>
          <span style={{ color: '#1a1a18', fontWeight: 500 }}>{d.actionNote}</span>
        </>}
      </div>
      {d.photos > 0 && (
        <div style={{ marginTop: 8, display: 'flex', gap: 6 }}>
          {Array.from({ length: d.photos }).map((_, i) => (
            <div key={i} style={{
              width: 52, height: 52, borderRadius: 6,
              background: 'linear-gradient(135deg, #d4d1c7, #b8b4a8)',
              border: '1px solid #ece9e0',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              fontSize: 18,
            }}>📷</div>
          ))}
        </div>
      )}
    </div>
  );
}

function ActionDetailForm({ reports, onChange }) {
  const CATS = [
    { label: '소방시설',     key: 'actionDetailFire' },
    { label: '피난방화시설', key: 'actionDetailEvac' },
    { label: '화기취급감독', key: 'actionDetailFireSup' },
    { label: '기타사항',     key: 'actionDetailEtc' },
  ];
  const [selCat, setSelCat] = React.useState('');
  const selectedKey = CATS.find(c => c.label === selCat)?.key || null;

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
      <select
        value={selCat}
        onChange={e => setSelCat(e.target.value)}
        style={{ ...recInputStyle, cursor: 'pointer' }}
      >
        <option value="">- 선택 -</option>
        {CATS.map(c => <option key={c.key} value={c.label}>{c.label}</option>)}
      </select>
      {selectedKey && (
        <textarea
          value={reports[selectedKey] || ''}
          onChange={e => onChange({ ...reports, [selectedKey]: e.target.value })}
          placeholder={`${selCat} 조치 내용을 입력하세요`}
          rows={3}
          style={{ ...recInputStyle, resize: 'vertical', lineHeight: 1.6 }}
        />
      )}
    </div>
  );
}

function ReportForm({ reports, onChange, month, building, account }) {
  const fields = [
    { k: 'inspectionDate', label: '점검일', type: 'date' },
    { k: 'performedAt',    label: '보고일시', type: 'date' },
    { k: 'reportMethod',   label: '보고방법', type: 'select', options: ['-- 선택 --', '대면', '서면', '정보통신'] },
    { k: 'reportTo',       label: '보고받은 사람', type: 'text', placeholder: '예) 김관리 소장' },
    { k: 'actionMethod',   label: '조치방법', type: 'select', options: ['-- 선택 --', '이전', '제거', '수리교체', '기타'] },
    { k: 'writtenBy',      label: '작성자', type: 'text', placeholder: '소방안전관리자명' },
    { k: 'inspectorConfirmer', label: '확인자', type: 'text', placeholder: '확인자 이름' },
  ];
  const setF = (k, v) => onChange({ ...reports, [k]: v });
  // 자동 기본값 설정
  React.useEffect(() => {
    const updates = {};
    if (!reports.reportTo && account?.name) updates.reportTo = account.name;
    if (!reports.writtenBy && (building?.fireManagerName || building?.manager_name)) updates.writtenBy = building.fireManagerName || building.manager_name;
    if (Object.keys(updates).length > 0) onChange({ ...reports, ...updates });
  }, [building, account]);

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
      {fields.map(f => (
        <div key={f.k}>
          <div style={{
            fontSize: 11, fontWeight: 700, color: '#5a5a55',
            marginBottom: 4, letterSpacing: '-0.01em',
          }}>
            {f.label}
          </div>
          {f.type === 'text' && (
            <input
              type="text"
              value={reports[f.k] || ''}
              onChange={e => setF(f.k, e.target.value)}
              placeholder={f.placeholder}
              style={recInputStyle}
            />
          )}
          {f.type === 'date' && (
            <input
              type="date"
              value={reports[f.k] || ''}
              onChange={e => setF(f.k, e.target.value)}
              style={recInputStyle}
            />
          )}
          {f.type === 'select' && (
            <select
              value={reports[f.k] || ''}
              onChange={e => setF(f.k, e.target.value)}
              style={{ ...recInputStyle, cursor: 'pointer' }}
            >
              {f.options.map(o => (
                <option key={o} value={o === '-- 선택 --' ? '' : o}>{o}</option>
              ))}
            </select>
          )}
        </div>
      ))}
    </div>
  );
}

const recInputStyle = {
  width: '100%', padding: '10px 12px',
  border: '1px solid #e5e3dc', borderRadius: 10,
  fontSize: 13, fontFamily: 'inherit',
  background: '#fbf9f3', color: '#1a1a18',
  outline: 'none', boxSizing: 'border-box',
};

function PhotoGrid({ photos }) {
  const maxSlots = 5;
  const filled = photos.length;
  return (
    <div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(5, 1fr)', gap: 6 }}>
        {Array.from({ length: maxSlots }).map((_, i) => {
          const p = photos[i];
          if (p) {
            return (
              <div key={i} style={{
                aspectRatio: '1', borderRadius: 8,
                background: 'linear-gradient(135deg, #d4d1c7, #b8b4a8)',
                border: '1px solid #ece9e0',
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                fontSize: 18,
              }}>📷</div>
            );
          }
          return (
            <div key={i} style={{
              aspectRatio: '1', borderRadius: 8,
              background: '#fbf9f3', border: '1px dashed #d4d1c7',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              color: '#d4d1c7', fontSize: 18, fontWeight: 700,
            }}>＋</div>
          );
        })}
      </div>
      <button
        disabled={filled >= maxSlots}
        style={{
          marginTop: 10, width: '100%', padding: '10px',
          background: '#fff', border: '1.5px solid #d4d1c7',
          borderRadius: 10, color: filled >= maxSlots ? '#d4d1c7' : '#1a1a18',
          fontSize: 12.5, fontWeight: 700, fontFamily: 'inherit',
          cursor: filled >= maxSlots ? 'not-allowed' : 'pointer',
          display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6,
          WebkitTapHighlightColor: 'transparent',
        }}
      >
        📷 사진 추가 ({filled}/{maxSlots})
      </button>
    </div>
  );
}

window.RecordMainScreen = RecordMainScreen;
window.RecordDetailScreen = RecordDetailScreen;
window.DefectOnlyScreen = DefectOnlyScreen;
