// Table view — compact rows + expandable detail panel for editing data fields.
const { useState: useStateTbl, useRef: useRefTbl } = React;

function tblReadAsDataURL(file) {
  return new Promise((res, rej) => {
    const r = new FileReader();
    r.onload = () => res(r.result);
    r.onerror = rej;
    r.readAsDataURL(file);
  });
}

const TBL_FIELD_ICONS = {
  shot: 'IconShotType', camera: 'IconCameraBody',
  lens: 'IconAperture', move: 'IconArrows',
  duration: 'IconClock', location: 'IconLocation',
};

// Inline image cell with click/drop-to-upload, replace, remove.
function TableThumb({ shot, ar, onUpdate, projectId }) {
  const fileRef = useRefTbl(null);
  const [over, setOver] = useStateTbl(false);

  // Optimistic upload: render the data URL instantly, then if signed in
  // push to Supabase Storage and swap to the public URL. See ShotCard's
  // handleFile in cards.jsx — same pattern, kept in sync deliberately.
  const handleFile = async (file) => {
    if (!file || !file.type.startsWith('image/')) return;
    const previousImg = shot.img;
    const optimized = (typeof window.ppDownscaleImage === 'function')
      ? await window.ppDownscaleImage(file)
      : file;
    const dataUrl = await tblReadAsDataURL(optimized);
    onUpdate(shot.id, { img: dataUrl });
    if (typeof window.ppUploadImage === 'function' && projectId) {
      const uid = await window.ppGetUserIdAsync?.();
      if (uid) {
        const url = await window.ppUploadImage(projectId, shot.id, optimized);
        if (url) {
          onUpdate(shot.id, { img: url });
          if (previousImg && typeof window.ppDeleteImage === 'function') {
            window.ppDeleteImage(previousImg);
          }
        }
      }
    }
  };

  return (
    <div
      className={`tbl-thumb ar-${ar} ${over ? 'file-over' : ''}`}
      onDragOver={(e) => { e.preventDefault(); setOver(true); }}
      onDragLeave={() => setOver(false)}
      onDrop={(e) => {
        e.preventDefault(); setOver(false);
        const f = e.dataTransfer.files[0];
        if (f) handleFile(f);
      }}
      onClick={(e) => { e.stopPropagation(); fileRef.current?.click(); }}
      title={shot.img ? 'Click to replace' : 'Click or drop image'}
    >
      {shot.img ? (
        <div className="tbl-thumb-img" style={{ backgroundImage: `url(${shot.img})` }} />
      ) : (
        <div className="tbl-thumb-empty">
          <IconUpload />
        </div>
      )}
      {shot.img && (
        <button
          className="tbl-thumb-clear"
          title="Remove image"
          onClick={(e) => {
            e.stopPropagation();
            if (typeof window.ppDeleteImage === 'function') {
              window.ppDeleteImage(shot.img);
            }
            onUpdate(shot.id, { img: '' });
          }}
        >
          <IconTrash />
        </button>
      )}
      <input
        ref={fileRef}
        type="file"
        accept="image/*"
        style={{ display: 'none' }}
        onChange={(e) => handleFile(e.target.files[0])}
      />
    </div>
  );
}

function TblInput({ value, onChange, placeholder, mono, multiline, className }) {
  const cls = [
    'tbl-input',
    mono ? 'mono' : '',
    multiline ? 'multi' : '',
    !value ? 'is-empty' : '',
    className || '',
  ].filter(Boolean).join(' ');
  if (multiline) {
    return (
      <textarea
        className={cls}
        value={value || ''}
        rows={2}
        placeholder={placeholder || '—'}
        onChange={(e) => onChange(e.target.value)}
        onClick={(e) => e.stopPropagation()}
      />
    );
  }
  return (
    <input
      className={cls}
      value={value || ''}
      placeholder={placeholder || '—'}
      onChange={(e) => onChange(e.target.value)}
      onClick={(e) => e.stopPropagation()}
    />
  );
}

function TblShotType({ value, onChange }) {
  const SIZES = window.SHOT_SIZES || [
    'Extreme Close-Up','Close-Up','Medium Close-Up','Medium Shot','Medium Wide Shot',
    'Wide Shot','Extreme Wide Shot','Over the Shoulder','Point of View','Insert','Graphic','Custom…'
  ];
  const presets = SIZES.filter(s => s !== 'Custom…');
  const isPreset = presets.includes(value);
  const [mode, setMode] = useStateTbl(!value || isPreset ? 'preset' : 'custom');
  if (mode === 'custom') {
    return (
      <TblInput
        value={value}
        onChange={onChange}
        placeholder="Custom shot type"
      />
    );
  }
  return (
    <select
      className={`tbl-input tbl-select ${!value ? 'is-empty' : ''}`}
      value={value || ''}
      onChange={(e) => {
        if (e.target.value === 'Custom…') { setMode('custom'); onChange(''); }
        else onChange(e.target.value);
      }}
      onClick={(e) => e.stopPropagation()}
    >
      <option value="">—</option>
      {SIZES.map(s => <option key={s} value={s === 'Custom…' ? 'Custom…' : s}>{s}</option>)}
    </select>
  );
}

// Render a single field control given a field def and its current value
function renderFieldControl(field, shot, onUpdate) {
  if (field.kind === 'builtin') {
    if (field.key === 'shot') {
      return <TblShotType value={shot.shot} onChange={(v) => onUpdate(shot.id, { shot: v })} />;
    }
    const isMono = ['lens', 'duration', 'camera'].includes(field.key);
    return (
      <TblInput
        value={shot[field.key]}
        onChange={(v) => onUpdate(shot.id, { [field.key]: v })}
        placeholder={field.def.placeholder || '—'}
        mono={isMono}
      />
    );
  }
  return (
    <TblInput
      value={shot.custom?.[field.key] || ''}
      onChange={(v) => onUpdate(shot.id, { custom: { ...(shot.custom || {}), [field.key]: v } })}
      placeholder="—"
    />
  );
}

function ShotTable({ scenes, ar, dataConfig, onChangeStatus, onUpdate, onReorder, onDelete, onDuplicate, flat, projectId }) {
  const [drag, setDrag] = useStateTbl(null);
  const [menuAnchor, setMenuAnchor] = useStateTbl(null);
  const [menuShotId, setMenuShotId] = useStateTbl(null);
  const [expanded, setExpanded] = useStateTbl(() => new Set());

  const toggleExpanded = (id) => {
    setExpanded(prev => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id); else next.add(id);
      return next;
    });
  };

  // Compute the ordered list of data fields enabled in Data Input.
  const fieldOrder = (dataConfig.order && dataConfig.order.length)
    ? dataConfig.order
    : [
        ...window.BUILTIN_FIELDS.map(f => ({ key: f.key, kind: 'builtin' })),
        ...dataConfig.custom.map(c => ({ key: c.key, kind: 'custom' })),
      ];
  const activeFields = fieldOrder.map(o => {
    if (o.kind === 'builtin') {
      const def = window.BUILTIN_FIELDS.find(f => f.key === o.key);
      if (!def || !dataConfig.enabled[def.key]) return null;
      return { kind: 'builtin', key: def.key, label: def.label, def };
    }
    const cf = dataConfig.custom.find(c => c.key === o.key);
    if (!cf) return null;
    return { kind: 'custom', key: cf.key, label: cf.label, def: cf };
  }).filter(Boolean);

  // Total columns for scene-row colSpan: drag, #, thumb, title, summary, status, actions, expand
  const totalCols = 8;

  const dragHandlersFor = (sceneId, shotId) => ({
    draggable: true,
    onDragStart: (e) => {
      e.dataTransfer.effectAllowed = 'move';
      e.dataTransfer.setData('text/plain', shotId);
      setDrag({ fromShotId: shotId, fromSceneId: sceneId, overId: null, side: null });
    },
    onDragOver: (e) => {
      e.preventDefault();
      if (!drag || drag.fromShotId === shotId) return;
      const r = e.currentTarget.getBoundingClientRect();
      const side = (e.clientY - r.top) < r.height / 2 ? 'before' : 'after';
      setDrag(d => d && (d.overId !== shotId || d.side !== side) ? { ...d, overId: shotId, side } : d);
    },
    onDrop: (e) => {
      e.preventDefault();
      if (!drag || drag.fromShotId === shotId) { setDrag(null); return; }
      onReorder(drag.fromSceneId, drag.fromShotId, sceneId, shotId, drag.side);
      setDrag(null);
    },
    onDragEnd: () => setDrag(null),
  });

  // Build a compact one-line summary of the data fields for the collapsed row
  const buildSummary = (s) => {
    const parts = [];
    activeFields.forEach(f => {
      let v = f.kind === 'builtin' ? s[f.key] : s.custom?.[f.key];
      if (!v) return;
      parts.push(v);
    });
    return parts.join(' · ');
  };

  let runningNum = 0;

  return (
    <div className={`table-wrap tbl-ar-${ar}`}>
      <table className="table">
        <thead>
          <tr>
            <th className="col-drag-h"></th>
            <th className="col-num-h">#</th>
            <th className="col-thumb-h">Thumb</th>
            <th className="col-title-h">Title</th>
            <th className="col-summary-h">Details</th>
            <th className="col-status-h">Status</th>
            <th className="col-actions-h"></th>
            <th className="col-expand-h"></th>
          </tr>
        </thead>
        <tbody>
          {scenes.map(scene => (
            <React.Fragment key={scene.id}>
              {!flat && (
                <tr className="table-scene-row">
                  <td colSpan={totalCols}>
                    <span className="scene-num">SC {scene.number}</span>
                    {scene.title}
                    <span className="scene-row-meta">· {scene.shots.length} shots</span>
                  </td>
                </tr>
              )}
              {scene.shots.map((s) => {
                runningNum += 1;
                const dh = dragHandlersFor(scene.id, s.id);
                const isDragging = drag?.fromShotId === s.id;
                const isOver = drag?.overId === s.id;
                const isOpen = expanded.has(s.id);
                const cls = [
                  'tbl-row',
                  isDragging ? 'dragging' : '',
                  isOver && drag.side === 'before' ? 'drop-before' : '',
                  isOver && drag.side === 'after' ? 'drop-after' : '',
                  isOpen ? 'is-open' : '',
                ].filter(Boolean).join(' ');
                const summary = buildSummary(s);
                return (
                  <React.Fragment key={s.id}>
                    <tr className={cls}
                      onDragOver={dh.onDragOver}
                      onDrop={dh.onDrop}
                      onClick={() => toggleExpanded(s.id)}>
                      <td className="col-drag" draggable onDragStart={dh.onDragStart} onDragEnd={dh.onDragEnd} title="Drag to reorder" onClick={(e) => e.stopPropagation()}>
                        <IconGrip />
                      </td>
                      <td className="col-num">{runningNum}</td>
                      <td className="col-thumb" onClick={(e) => e.stopPropagation()}>
                        <TableThumb shot={s} ar={ar} onUpdate={onUpdate} projectId={projectId} />
                      </td>
                      <td className="col-title">
                        <TblInput
                          value={s.title}
                          onChange={(v) => onUpdate(s.id, { title: v })}
                          placeholder="Untitled shot"
                          className="title"
                        />
                      </td>
                      <td className="col-summary">
                        <span className={`tbl-summary ${summary ? '' : 'is-empty'}`}>
                          {summary || 'Click to add details'}
                        </span>
                      </td>
                      <td className="col-status" onClick={(e) => e.stopPropagation()}>
                        <StatusPill
                          status={s.status}
                          onClick={(e) => {
                            e.stopPropagation();
                            setMenuAnchor(e.currentTarget.getBoundingClientRect());
                            setMenuShotId(s.id);
                          }}
                        />
                      </td>
                      <td className="col-actions" onClick={(e) => e.stopPropagation()}>
                        <span className="col-actions-inner">
                          <button className="icon-btn" title="Duplicate" onClick={() => onDuplicate(s.id)}><IconDuplicate /></button>
                          <button className="icon-btn" title="Delete" onClick={() => onDelete(s.id)}><IconTrash /></button>
                        </span>
                      </td>
                      <td className="col-expand">
                        <span className={`tbl-chevron ${isOpen ? 'open' : ''}`} aria-hidden="true">
                          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
                            <polyline points="6 9 12 15 18 9"></polyline>
                          </svg>
                        </span>
                      </td>
                    </tr>
                    {isOpen && (
                      <tr className="tbl-detail-row">
                        <td colSpan={totalCols}>
                          <div className="tbl-detail">
                            <div className="tbl-detail-section">
                              <div className="tbl-detail-label">Description</div>
                              <TblInput
                                value={s.desc}
                                onChange={(v) => onUpdate(s.id, { desc: v })}
                                placeholder="Describe the action, blocking, key beats…"
                                multiline
                              />
                            </div>
                            {activeFields.length > 0 && (
                              <div className="tbl-detail-grid">
                                {activeFields.map(f => {
                                  const IconC = f.kind === 'builtin' ? window[TBL_FIELD_ICONS[f.key]] : null;
                                  return (
                                    <div key={f.key} className="tbl-detail-field">
                                      <div className="tbl-detail-label">
                                        {IconC ? <IconC className="tbl-detail-icon" /> : <span className="di-dot di-dot-grey tbl-detail-dot" />}
                                        {f.label}
                                      </div>
                                      {renderFieldControl(f, s, onUpdate)}
                                    </div>
                                  );
                                })}
                              </div>
                            )}
                          </div>
                        </td>
                      </tr>
                    )}
                  </React.Fragment>
                );
              })}
            </React.Fragment>
          ))}
        </tbody>
      </table>

      {menuShotId && menuAnchor && (
        <StatusMenu
          value={(() => {
            for (const sc of scenes) {
              const f = sc.shots.find(x => x.id === menuShotId);
              if (f) return f.status;
            }
            return 'draft';
          })()}
          anchor={menuAnchor}
          onPick={(k) => onChangeStatus(menuShotId, k)}
          onClose={() => { setMenuShotId(null); setMenuAnchor(null); }}
        />
      )}
    </div>
  );
}

window.ShotTable = ShotTable;
