/* ============================================================
   案件詳細 — 添付タブ（AttachTab / RefLinksSection）。case-detail.jsx から分離（依存はグローバル＝render時解決）。
   ============================================================ */
const ATT_CATEGORIES = ['提案書', '見積書', '発注書', 'その他'];
const ATT_COLORS = { '提案書': '#4a5af0', '見積書': '#16a34a', 'プロトタイプ': '#0891b2', '発注書': '#d97706', 'その他': '#6b7280' };
function fmtSize(b) {
  if (b >= 1024 * 1024) return (b / 1024 / 1024).toFixed(1) + ' MB';
  if (b >= 1024) return Math.round(b / 1024) + ' KB';
  return b + ' B';
}

/* Canva 短縮リンク（canva.link）はサーバーで展開してから埋め込む。url → 埋め込みURL文字列 | null（不可） | Promise（解決中）をキャッシュ */
const __canvaEmbed = {};

/* リンク・参照（URL）を貼って保存する共通セクション。field=保存先（refLinks/proposalLinks/quoteLinks）。autoLinks=自動表示の固定リンク */
/* autoStatusField: 提出ステータスの自動前進用。リンクを追加したら「未着手」→「準備中」へ
   （提出済み判定はサーバのGmail同期＝顧客宛送信メールに登録リンクを検知したとき。2026-07-10 自動判断） */
function RefLinksSection({ caseData, field, autoLinks = [], hint, editable = true, autoStatusField = null }) {
  hint = hint == null ? t('cd.refLinksHintDefault') : hint;
  const { patchCase, showToast } = useStore();
  const stored = caseData[field] || [];
  const links = [...autoLinks, ...stored];
  const [title, setTitle] = React.useState('');
  const [url, setUrl] = React.useState('');
  const [note, setNote] = React.useState(''); // リンクごとのメモ（任意・2026-07-13）
  const [previewId, setPreviewId] = React.useState(null);
  const [, bumpCanva] = React.useReducer(x => x + 1, 0);
  // canva.link 短縮リンクはブラウザが転送先を読めない（CORS）ため、サーバーで展開して埋め込みURLを得る
  React.useEffect(() => {
    let alive = true;
    links.forEach(lk => {
      if (embedUrl(lk.url)) return;                       // 完全URLは即埋め込み可
      const code = canvaShortCode(lk.url);
      if (!code) return;
      const v = __canvaEmbed[lk.url];
      if (v !== undefined) return;                        // 解決済み or 解決中
      __canvaEmbed[lk.url] = API.canvaResolve(code)
        .then(res => { __canvaEmbed[lk.url] = (res && res.embed) || null; if (alive) bumpCanva(); })
        .catch(() => { __canvaEmbed[lk.url] = null; if (alive) bumpCanva(); });
    });
    return () => { alive = false; };
  }, [stored]);
  const add = () => {
    if (!url.trim()) return;
    let u = url.trim(); if (!/^https?:\/\//.test(u)) u = 'https://' + u;
    const link = { id: 'lk' + Date.now(), title: title.trim() || u.replace(/^https?:\/\//, '').split('/')[0], url: u, note: note.trim() || '' };
    const patch = { [field]: [link, ...stored] };
    // 提出ステータスの自動前進：リンクが付いたら少なくとも「準備中」（手動設定済みは触らない）
    if (autoStatusField && ['none', '', undefined, null].includes(caseData[autoStatusField])) patch[autoStatusField] = 'preparing';
    patchCase(caseData.id, patch);
    setTitle(''); setUrl(''); setNote(''); showToast(t('btn.linkAdded'));
  };
  const removeLink = (id) => {
    if (!window.confirm(t('common.confirmDelete'))) return;
    patchCase(caseData.id, { [field]: stored.filter(x => x.id !== id) });
    showToast(t('btn.linkDeleted'), 'x');
  };
  // 既存リンクのメモを後から追加・編集（空にすると削除）
  const editNote = (lk) => {
    const v = window.prompt(t('cd.refLink.memoPrompt'), lk.note || '');
    if (v == null) return;
    patchCase(caseData.id, { [field]: stored.map(x => x.id === lk.id ? { ...x, note: v.trim() } : x) });
    showToast(t('cd.refLink.memoSaved'));
  };
  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10 }}>
        <Icon name="link" size={15} stroke={2} style={{ color: '#7b828d', flex: '0 0 auto' }} />
        <span style={{ fontSize: 12.5, fontWeight: 700, color: '#1c1f26', whiteSpace: 'nowrap', flex: '0 0 auto' }}>{editable ? t('case-detail.addReferenceLink') : t('case-detail.referenceLinks')}</span>
        {editable && <span style={{ fontSize: 12, color: '#a8aeb8', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{hint}</span>}
      </div>
      {editable && <div style={{ display: 'flex', flexDirection: 'column', gap: 7 }}>
        <div style={{ display: 'flex', gap: 8, alignItems: 'stretch' }}>
          <TextInput value={title} onChange={(e) => setTitle(e.target.value)} placeholder={t('case-detail.labelOptional')} style={{ flex: '0 0 150px' }} />
          <TextInput value={url} onChange={(e) => setUrl(e.target.value)} onKeyDown={(e) => { if (enterSubmits(e)) add(); }} placeholder={t('case-detail.urlPlaceholder')} style={{ flex: 1 }} />
          <Button variant="primary" icon="plus" onClick={add} disabled={!url.trim()}>{t('btn.add')}</Button>
        </div>
        {/* メモ（任意）：パスワード・見方・共有時の注意など、リンクに添える備考 */}
        <TextInput value={note} onChange={(e) => setNote(e.target.value)} onKeyDown={(e) => { if (enterSubmits(e)) add(); }} placeholder={t('cd.refLink.memoPlaceholder')} style={{ fontSize: 12.5 }} />
      </div>}
      <div style={{ marginTop: 12, display: 'flex', flexDirection: 'column', gap: 8 }}>
        {links.map(lk => {
          const m = linkMeta(lk.url);
          const emb = embedUrl(lk.url) || (typeof __canvaEmbed[lk.url] === 'string' ? __canvaEmbed[lk.url] : null);
          const open = previewId === lk.id;
          return (
            <React.Fragment key={lk.id}>
            <div className="row-hover" style={{ display: 'flex', alignItems: 'center', gap: 11, padding: '10px 12px', border: '1px solid #f0f1f4', borderRadius: 9 }}>
              <div style={{ width: 32, height: 32, borderRadius: 7, background: m.color + '15', display: 'flex', alignItems: 'center', justifyContent: 'center', flex: '0 0 auto' }}>
                <Icon name={m.icon} size={15} stroke={2} fill={m.icon === 'spark' ? m.color : 'none'} style={{ color: m.color }} />
              </div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 13, fontWeight: 600, color: '#2b2f38', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{lk.title}</div>
                <a href={lk.url} target="_blank" rel="noreferrer" style={{ fontSize: 12, color: '#9aa1ab', fontFamily: 'var(--mono)', textDecoration: 'none', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', display: 'block' }}>{lk.url}</a>
                {lk.note && <div style={{ fontSize: 12, color: '#6b7280', marginTop: 3, lineHeight: 1.5, whiteSpace: 'pre-wrap' }}>📝 {lk.note}</div>}
              </div>
              {lk.auto && <span style={{ fontSize: 12, fontWeight: 600, color: '#7b828d', background: '#f0f1f4', padding: '2px 8px', borderRadius: 5, flex: '0 0 auto' }}>{t('case-detail.autoAdded')}</span>}
              <span style={{ fontSize: 12, fontWeight: 600, color: m.color, background: m.color + '14', padding: '2px 8px', borderRadius: 5, flex: '0 0 auto' }}>{m.label}</span>
              {emb && <IconButton name="eye" size={15} active={open} title={t('cd.preview')} onClick={() => setPreviewId(open ? null : lk.id)} />}
              {editable && !lk.auto && <IconButton name="edit" size={14} title={t('cd.refLink.editMemo')} onClick={() => editNote(lk)} />}
              <a href={lk.url} target="_blank" rel="noreferrer"><IconButton name="link" size={15} title={t('btn.open')} /></a>
              {editable && !lk.auto && <IconButton name="x" size={15} title={t('btn.delete')} onClick={() => removeLink(lk.id)} />}
            </div>
            {open && emb && <PreviewFrame kind="embed" src={emb} />}
            </React.Fragment>
          );
        })}
        {links.length === 0 && <div style={{ padding: '16px 0', textAlign: 'center', color: '#b4bac3', fontSize: 12.5 }}>{t('case-detail.noLinks')}</div>}
      </div>
    </div>
  );
}

function AttachTab({ caseData }) {
  const { showToast, patchCase, currentUser } = useStore();
  const D = window.APP_DATA;
  const isAdmin = currentUser.role === 'admin'; // 削除は管理者のみ（アップロードは全員可）
  // スクレイピング起票の案件は取得元（レディクル）、Fireflies記録がある商談はそのリンクを自動で追加
  const { meetingsOf } = useStore();

  /* ---- その他資料のファイル添付（提案書・見積書は専用タブへ。ここは発注書・その他）---- */
  const OTHER_CATS = ['その他', '発注書'];
  const allFiles = caseData.attachments || [];
  const files = allFiles.filter(a => a.category !== '提案書' && a.category !== '見積書' && a.category !== 'プロトタイプ');
  const [cat, setCat] = React.useState('その他');
  const [uploading, setUploading] = React.useState(false);
  const [dragOver, setDragOver] = React.useState(false);
  const [previewId, setPreviewId] = React.useState(null);
  const fileRef = React.useRef(null);
  // 発注書だけファイル名から自動判定（提案書・見積書は専用タブなのでここでは判定しない）
  const detectCat = (name) => {
    if (/発注|注文|purchase|order/i.test(name)) return '発注書';
    return null;
  };
  const onFiles = async (fileList) => {
    const f = fileList && fileList[0];
    if (!f || uploading) return;
    if (f.size > 15 * 1024 * 1024) { showToast(t('case-detail.fileSizeLimit15MBAttach'), 'x'); return; }
    setUploading(true);
    try {
      const detected = detectCat(f.name);
      const useCat = detected || cat;
      const b64 = await new Promise((resolve, reject) => {
        const r = new FileReader();
        r.onload = () => resolve(String(r.result).split(',')[1]);
        r.onerror = reject;
        r.readAsDataURL(f);
      });
      const r = await API.uploadAttachment({ caseId: caseData.id, name: f.name, mime: f.type || 'application/octet-stream', category: useCat, content: b64 });
      // アップロードと同時に提出ステータスを「待確認」へ（既に提出済み/待確認なら触らない）
      patchCase(caseData.id, { attachments: [r.att, ...allFiles] });
      showToast(detected ? t('cd.toast.fileAttachedDetected', { cat: useCat, name: f.name }) : t('cd.toast.fileAttachedCat', { cat: useCat, name: f.name }));
    } catch (e) { showToast(e.message, 'x'); }
    setUploading(false);
    if (fileRef.current) fileRef.current.value = '';
  };
  const removeFile = async (att) => {
    if (!window.confirm(t('common.confirmDelete'))) return;
    try {
      await API.deleteAttachment(att.id);
      patchCase(caseData.id, { attachments: allFiles.filter(x => x.id !== att.id) });
      showToast(t('btn.materialDeleted'), 'x');
    } catch (e) { showToast(e.message, 'x'); }
  };
  // ※ Fireflies の通話リンクは「会議記録」タブに移動した（ここは見積書・提案書とその他リンク）
  // 取得元（レディクル）リンクは自動表示（手動リンクは下部の RefLinksSection が case.refLinks に保存）
  const autoLinks = (caseData.source === 'scrape' && caseData.sourceUrl)
    ? [{ id: 'lk-src', title: t('cd.sourceCasePage', { no: caseData.sourceNo }), url: caseData.sourceUrl, auto: true }] : [];
  return (
    <div style={{ padding: 22 }}>
      {/* その他資料のファイル添付 */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10 }}>
        <Icon name="attach" size={15} stroke={2} style={{ color: '#7b828d', flex: '0 0 auto' }} />
        <span style={{ fontSize: 12.5, fontWeight: 700, color: '#1c1f26', whiteSpace: 'nowrap', flex: '0 0 auto' }}>{t('case-detail.attachOtherMaterials')}</span>
        <span style={{ fontSize: 12, color: '#a8aeb8' }}>{t('case-detail.selectCategoryAndAdd')}</span>
        <div style={{ marginLeft: 'auto', width: 130, flex: '0 0 auto' }}>
          <SelectInput value={cat} onChange={(e) => setCat(e.target.value)} options={OTHER_CATS} placeholder={t('cd.categoryPlaceholder')} />
        </div>
      </div>
      <input ref={fileRef} type="file" style={{ display: 'none' }} onChange={(e) => onFiles(e.target.files)} />
      <div onClick={() => !uploading && fileRef.current && fileRef.current.click()}
        onDragOver={(e) => { e.preventDefault(); setDragOver(true); }}
        onDragLeave={() => setDragOver(false)}
        onDrop={(e) => { e.preventDefault(); setDragOver(false); onFiles(e.dataTransfer.files); }}
        style={{ border: '1.5px dashed ' + (dragOver ? '#4a5af0' : '#d8dce2'), background: dragOver ? '#f4f4fd' : 'transparent',
          borderRadius: 12, padding: '26px 0', textAlign: 'center', cursor: uploading ? 'wait' : 'pointer', transition: 'all .15s' }}>
        <Icon name={uploading ? 'refresh' : 'attach'} size={24} stroke={1.8} style={{ color: dragOver ? '#4a5af0' : '#b4bac3' }} />
        <div style={{ fontSize: 13, color: '#7b828d', marginTop: 9, fontWeight: 600 }}>
          {uploading ? t('cd.uploading') : t('case-detail.dragDropCategory', { cat })}
        </div>
        {!uploading && <div style={{ fontSize: 12, color: '#a8aeb8', marginTop: 4 }}>{t('cd.orText')}<span style={{ color: '#4a5af0', fontWeight: 600 }}>{t('btn.selectFile')}</span></div>}
      </div>
      {/* ※ アップロード済みファイルの一覧はタブ最下部に表示 */}

      {/* リンク・参照を手動で追加（共通コンポーネント） */}
      <div style={{ marginTop: 22 }}>
        <RefLinksSection caseData={caseData} field="refLinks" autoLinks={autoLinks} />
      </div>

      {/* アップロード済みファイル（最下部） */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, margin: '22px 0 10px' }}>
        <Icon name="attach" size={15} stroke={2} style={{ color: '#7b828d', flex: '0 0 auto' }} />
        <span style={{ fontSize: 12.5, fontWeight: 700, color: '#1c1f26', whiteSpace: 'nowrap' }}>{t('case-detail.uploadedFiles', { count: files.length })}</span>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
        {files.map(att => {
          const color = ATT_COLORS[att.category] || ATT_COLORS['その他'];
          const by = D.user(att.uploadedBy);
          const pk = attPreviewKind(att);
          const open = previewId === att.id;
          return (
            <React.Fragment key={att.id}>
            <div className="row-hover" style={{ display: 'flex', alignItems: 'center', gap: 11, padding: '10px 12px', border: '1px solid #f0f1f4', borderRadius: 9 }}>
              <div style={{ width: 32, height: 32, borderRadius: 7, background: color + '15', display: 'flex', alignItems: 'center', justifyContent: 'center', flex: '0 0 auto' }}>
                <Icon name="attach" size={15} stroke={2} style={{ color }} />
              </div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <a href={API.attachmentUrl(att.id)} target="_blank" rel="noreferrer"
                  style={{ fontSize: 13, fontWeight: 600, color: '#2b2f38', textDecoration: 'none', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', display: 'block' }}>{att.name}</a>
                <div style={{ fontSize: 12, color: '#9aa1ab', marginTop: 2 }}>
                  {fmtSize(att.size)} · <span style={{ color: '#4a5af0' }}>{fmtDate(att.at, true)} {fmtTime(att.at)}</span>{by ? ` · ${by.short}` : ''}
                </div>
              </div>
              <span style={{ fontSize: 12, fontWeight: 700, color, background: color + '14', padding: '2px 8px', borderRadius: 5, flex: '0 0 auto' }}>{att.category}</span>
              {pk && <IconButton name="eye" size={15} active={open} title={t('cd.preview')} onClick={() => setPreviewId(open ? null : att.id)} />}
              <a href={API.attachmentUrl(att.id)} target="_blank" rel="noreferrer"><IconButton name="download" size={15} title={t('btn.download')} /></a>
              {isAdmin && <IconButton name="x" size={15} title={t('btn.deleteAdminOnly')} onClick={() => removeFile(att)} />}
            </div>
            {open && pk && <PreviewFrame kind={pk} src={API.attachmentUrl(att.id)} />}
            </React.Fragment>
          );
        })}
        {files.length === 0 && <div style={{ padding: '14px 0', textAlign: 'center', color: '#b4bac3', fontSize: 12.5 }}>{t('case-detail.noUploadedFiles')}</div>}
      </div>
    </div>
  );
}

/* クリックで編集できる日付行（期限・次回商談・提案書提出） */
Object.assign(window, { RefLinksSection, AttachTab });
