/* ============================================================
   save-popup.jsx — 저장 팝업 (전 에디터 공용 · window.BannerSavePopup)
   ------------------------------------------------------------
   · 550 / 1E / 앱푸시 에디터가 각자 갖던 SavePopup 을 하나로 통일.
   · 구성: 스키마 파일명 입력(필수) + "저장될 실제 이미지" 미리보기(실제 비율·실제 px 표기).
   · 폴더 지정 없음 — 확정 시 에디터의 onConfirm(values) 이 다운로드 저장 담당.
   · props:
       account      작업자명(자동)
       getBlob()    저장될 최종 합성 이미지를 Blob 으로 반환(에디터가 제공, async)
       onConfirm(v) 저장 확정 콜백 — 실제 저장/다운로드는 에디터가 수행
       fixedValues  카테고리 코드처럼 자동으로 파일명에 들어갈 값
       getValidation(values) 공식 가이드 검수 결과({status,percent,issues})
       onClose()    닫기
   ============================================================ */
(function () {
  const R = window.React;
  if (!R) return;

  function BannerSavePopup({ account, getBlob, getSources, getProject, getDraftId, onSaved, onConfirm, onClose, category, type, fileNameRule, fixedValues, getValidation }) {
    const { useState, useEffect, useRef } = R;
    const pad2 = (n) => String(n).padStart(2, '0');
    const today = new Date();
    const date = today.getFullYear() + pad2(today.getMonth() + 1) + pad2(today.getDate());
    const worker = account || '';
    const ruleFields = fileNameRule && Array.isArray(fileNameRule.fields) ? fileNameRule.fields : [];
    const primaryField = (fileNameRule && fileNameRule.primaryField && ruleFields.find((f) => f.key === fileNameRule.primaryField)) ||
      ruleFields.find((f) => f && f.input !== 'auto' && !/^(date|worker|type)$/i.test(f.key || '')) ||
      { key: 'event', label: '행사명', placeholder: '', required: true };
    const primaryKey = primaryField.key || 'event';
    const primaryLabel = primaryField.label || '행사명';
    const primaryPlaceholder = primaryField.placeholder || '';
    const primaryRequired = primaryField.required !== false;
    const prefixPreview = fileNameRule && fileNameRule.prefixPreview
      ? String(fileNameRule.prefixPreview).replace(/\{date\}/g, date)
      : '';

    const [event, setEvent] = useState('');
    const [manualReviewApproved, setManualReviewApproved] = useState(false);
    const [saving, setSaving] = useState(false);    // 완료 저장 중
    const [preview, setPreview] = useState('');
    const [dims, setDims] = useState(null);      // {w,h} = 실제 저장 px
    const [prevState, setPrevState] = useState('loading');  // loading | ok | fail

    // 저장될 실제 이미지(에디터 blob) → objectURL 미리보기
    useEffect(() => {
      let url = '';
      let alive = true;
      (async () => {
        try {
          const b = getBlob ? await getBlob() : null;
          if (!alive) return;
          if (b) { url = URL.createObjectURL(b); setPreview(url); setPrevState('ok'); }
          else setPrevState('fail');
        } catch (e) { if (alive) setPrevState('fail'); }
      })();
      return () => { alive = false; if (url) URL.revokeObjectURL(url); };
    }, []);

    const valuesFor = (primaryValue, manualApproved) => {
      const values = Object.assign({}, fixedValues || {}, {
        date: date.trim(), worker: worker, type: type || '',
        manualReviewApproved: !!manualApproved,
        outputCanvas: dims ? { w: dims.w, h: dims.h } : null,
      });
      values[primaryKey] = String(primaryValue || '').trim();
      if (!values.event && primaryKey === 'event') values.event = values[primaryKey];
      return values;
    };
    const runValidation = (values) => {
      if (!getValidation) return { status: 'APPROVED', percent: 100, issues: [] };
      try { return getValidation(values) || { status: 'FAIL', percent: 0, issues: [{ code: 'VALIDATION_EMPTY', message: '검수 결과를 만들 수 없습니다.' }] }; }
      catch (e) { return { status: 'FAIL', percent: 0, issues: [{ code: 'VALIDATION_ERROR', message: '가이드 검수 중 오류가 발생했습니다.' }] }; }
    };
    const liveValues = valuesFor(event, manualReviewApproved);
    const validation = runValidation(liveValues);
    const validationBlocked = validation.status === 'FAIL' || (validation.status === 'MANUAL_REVIEW' && !manualReviewApproved);
    const builtPreview = window.buildBannerFileName && fileNameRule ? window.buildBannerFileName(fileNameRule, liveValues) : null;

    // 완료(최종) 저장 — 가이드 승인 후 Supabase 저장 + 다운로드
    const submit = async () => {
      if ((primaryRequired && !event.trim()) || saving) return;
      const values = valuesFor(event, manualReviewApproved);
      const checked = runValidation(values);
      if (checked.status === 'FAIL' || (checked.status === 'MANUAL_REVIEW' && !manualReviewApproved)) return;
      setSaving(true);
      try {
        const built = window.buildBannerFileName && fileNameRule ? window.buildBannerFileName(fileNameRule, values) : null;
        // 로컬 개발 우회와 QA 로그인은 Supabase 세션을 만들지 않는다. 원격 프로젝트
        // 저장만 건너뛰고 아래 onConfirm의 실제 이미지 다운로드는 동일하게 실행한다.
        const localOnlySave = window.__BANNERLY_DEV_BYPASS === true || window.__bannerlyLocalQa === true || window.__bannerlyUserId === 'local-qa-user';
        if (window.__myBanners && !localOnlySave) {
          const blob = getBlob ? await getBlob() : null;
          // 이어서 편집 스냅샷+소스: getProject(있으면) 우선, 없으면 getSources(하위호환)
          let sources = []; let snapshot;
          if (getProject) {
            try { const p = (await getProject()) || {}; sources = p.sources || []; snapshot = p.snapshot; } catch (e) {}
          } else if (getSources) {
            try { sources = (await getSources()) || []; } catch (e) {}
          }
          // 작업중(draft) 항목이 있으면 그 id로 저장 → '완료'로 승격(중복 방지)
          let draftId = null;
          if (getDraftId) { try { draftId = getDraftId() || null; } catch (e) {} }
          if (snapshot && typeof snapshot === 'object') snapshot = Object.assign({}, snapshot, { guideApproval: checked });
          const r = await window.__myBanners.saveProject({
            status: 'saved', id: draftId, event: values.event || values.product || event.trim(), worker: worker,
            category: category || '', type: type || '', snapshot: snapshot,
            fileName: built && built.name ? built.name : '',
            width: dims ? dims.w : null, height: dims ? dims.h : null, finalBlob: blob, sources: sources,
          });
          if (r && !r.ok) { alert('내 배너 저장 실패: ' + (r.error || '오류')); setSaving(false); return; }
          if (r && r.ok && onSaved) { try { onSaved(r.id, r); } catch (e) { try { onSaved(r.id); } catch (e2) {} } }
        }
        if (onConfirm) await onConfirm(values);
        if (onClose) onClose();
      } finally { setSaving(false); }
    };

    const _in = { width: '100%', padding: '9px 11px', borderRadius: '9px', border: '1px solid #e7e7ee', font: 'inherit', fontSize: '13px', boxSizing: 'border-box' };
    const _lb = { fontSize: '11.5px', fontWeight: 700, color: '#43434e', margin: '0 0 5px', display: 'flex', alignItems: 'center', gap: '6px' };

    return R.createElement('div', {
      onClick: onClose,
      style: { position: 'fixed', inset: 0, background: 'rgba(20,20,26,.45)', display: 'grid', placeItems: 'center', zIndex: 10000 },
    },
      R.createElement('div', {
        onClick: (e) => e.stopPropagation(),
        style: { width: '420px', maxWidth: '92vw', maxHeight: '90vh', overflowY: 'auto', background: '#fff', borderRadius: '16px', padding: '22px', boxShadow: '0 12px 40px rgba(0,0,0,.22)', fontFamily: 'inherit' },
      },
        R.createElement('div', { style: { fontSize: '16px', fontWeight: 800, color: '#1c1c22', marginBottom: '3px' } }, '배너 저장'),
        R.createElement('div', { style: { fontSize: '12px', color: '#8a8a96', marginBottom: '16px' } }, '실제 저장 이미지와 공식 가이드 규칙을 함께 검사합니다.'),

        // 미리보기 (실제 비율 · 실제 px)
        R.createElement('div', { style: { marginBottom: '14px' } },
          R.createElement('div', { style: _lb },
            '미리보기',
            dims ? R.createElement('span', { style: { color: '#8a8a96', fontWeight: 500 } }, '· 실제 크기 ' + dims.w + ' × ' + dims.h + 'px') : null,
          ),
          R.createElement('div', {
            // 라운드 금지 — 저장 이미지는 사각. 미리보기 모서리도 각지게(borderRadius 0).
            style: { width: '100%', minHeight: '80px', background: '#f3f3f5', borderRadius: 0, border: '1px solid #e7e7ee', overflow: 'hidden', display: 'grid', placeItems: 'center' },
          },
            prevState === 'loading' ? R.createElement('span', { style: { fontSize: '12px', color: '#9a9aa6', padding: '24px 0' } }, '미리보기 생성 중…')
            : prevState === 'fail' ? R.createElement('span', { style: { fontSize: '12px', color: '#c0392b', padding: '24px 0' } }, '미리보기를 만들 수 없습니다')
            : R.createElement('img', {
                src: preview, alt: '',
                onLoad: (e) => setDims({ w: e.target.naturalWidth, h: e.target.naturalHeight }),
                style: { width: '100%', height: 'auto', display: 'block' },
              }),
          ),
        ),

        // 파일명 입력
        R.createElement('div', { style: { marginBottom: '16px' } },
          R.createElement('div', { style: _lb }, primaryLabel + ' ', primaryRequired ? R.createElement('span', { style: { color: '#4E4CDB' } }, '*') : null),
          prefixPreview ? R.createElement('div', { style: { fontSize: '11.5px', color: '#6b6b78', marginBottom: '6px' } }, '자동 파일명 형식을 적용합니다.') : null,
          R.createElement('input', {
            autoFocus: true, type: 'text', value: event, placeholder: primaryPlaceholder,
            onChange: (e) => setEvent(e.target.value),
            onKeyDown: (e) => { if (e.key === 'Enter') submit(); },
            style: { ..._in, borderColor: (primaryRequired && !event.trim()) ? '#f59e0b' : '' },
          }),
          (primaryRequired && !event.trim()) && R.createElement('div', { style: { fontSize: '11.5px', color: '#b45309', marginTop: '5px' } }, primaryLabel + '을 입력해야 저장할 수 있어요'),
          builtPreview ? R.createElement('div', { style: { fontSize: '11px', color: '#6b6b78', marginTop: '7px', wordBreak: 'break-all' } }, '파일명: ' + builtPreview.name) : null,
        ),

        R.createElement('div', {
          'data-guide-status': validation.status,
          style: { marginBottom: '16px', padding: '11px 12px', border: '1px solid ' + (validation.status === 'APPROVED' ? '#86c99a' : validation.status === 'MANUAL_REVIEW' ? '#f0b65b' : '#e59a91'), borderRadius: '8px', background: validation.status === 'APPROVED' ? '#f2fbf4' : validation.status === 'MANUAL_REVIEW' ? '#fff9ed' : '#fff5f4' },
        },
          R.createElement('div', { style: { display: 'flex', justifyContent: 'space-between', gap: '10px', fontSize: '12px', fontWeight: 800, color: '#303038' } },
            R.createElement('span', null, validation.status === 'APPROVED' ? '가이드 자동 검수 통과' : validation.status === 'MANUAL_REVIEW' ? '디자인 승인 확인 필요' : '가이드 위반'),
            R.createElement('span', null, String(validation.percent == null ? 0 : validation.percent) + '%'),
          ),
          (validation.issues || []).slice(0, 5).map((issue, index) => R.createElement('div', { key: (issue.code || 'issue') + index, style: { marginTop: '6px', fontSize: '11px', lineHeight: 1.45, color: issue.severity === 'review' ? '#8a5a00' : '#a23a30' } }, (issue.code ? '[' + issue.code + '] ' : '') + issue.message)),
          validation.status === 'MANUAL_REVIEW' ? R.createElement('label', { style: { display: 'flex', alignItems: 'flex-start', gap: '7px', marginTop: '9px', fontSize: '11.5px', fontWeight: 700, color: '#6f4b00', cursor: 'pointer' } },
            R.createElement('input', { type: 'checkbox', checked: manualReviewApproved, onChange: (e) => setManualReviewApproved(e.target.checked), style: { marginTop: '1px', accentColor: '#4E4CDB' } }),
            R.createElement('span', null, '디자인 승인자가 조합과 원본 보존 상태를 확인했습니다.'),
          ) : null,
        ),

        // 버튼: 취소 · 저장(최종)
        R.createElement('div', { style: { display: 'flex', gap: '8px' } },
          R.createElement('button', {
            onClick: onClose,
            style: { flex: '0 0 auto', padding: '10px 16px', borderRadius: '9px', border: '1px solid #e7e7ee', background: '#fff', color: '#6b6b78', font: 'inherit', fontWeight: 700, cursor: 'pointer' },
          }, '취소'),
          R.createElement('button', {
            onClick: submit, disabled: (primaryRequired && !event.trim()) || saving || validationBlocked,
            style: { flex: 1, padding: '10px', borderRadius: '9px', border: 'none', background: ((primaryRequired && !event.trim()) || saving || validationBlocked) ? '#c8c7f2' : '#4E4CDB', color: '#fff', font: 'inherit', fontWeight: 800, cursor: ((primaryRequired && !event.trim()) || saving || validationBlocked) ? 'default' : 'pointer' },
          }, saving ? '저장 중…' : validationBlocked ? '검수 확인 필요' : '저장'),
        ),
      ),
    );
  }

  window.BannerSavePopup = BannerSavePopup;
})();
