const STATUTS = {
  wait: { label: 'En attente', icon: '\u25CB', color: 'var(--text-muted)' },
  active: { label: 'En cours', icon: '\u25CF', color: 'var(--accent)' },
  done: { label: 'Terminé', icon: '\u2713', color: 'var(--green)' },
  blocked: { label: 'Bloqué', icon: '!', color: 'var(--red)' },
  quote: { label: 'Chiffrage', icon: '\u20AC', color: 'var(--yellow)' },
  validation: { label: 'Valid. client', icon: '?', color: 'var(--purple)' }
};

function formatSize(bytes) {
  if (bytes < 1024) return bytes + ' o';
  if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' Ko';
  return (bytes / (1024 * 1024)).toFixed(1) + ' Mo';
}

function GrafcetTransition({ color }) {
  return React.createElement('div', {
    className: 'grafcet-transition',
    style: { backgroundColor: color || 'var(--border)' }
  });
}

function AttachmentItem({ att, projectId, onDelete, onPreview }) {
  const isImage = att.mime_type && att.mime_type.startsWith('image/');
  const isPdf = att.mime_type && att.mime_type.includes('pdf');
  const icon = isImage ? '\uD83D\uDDBC' : isPdf ? '\uD83D\uDCC4' : '\uD83D\uDCCE';

  const handleDownload = async () => {
    try {
      const res = await API.fetch(`/api/attachments/${att.id}/download`);
      const blob = await res.blob();
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = att.name;
      a.click();
      URL.revokeObjectURL(url);
    } catch (err) {
      Toasts.error('Erreur de téléchargement');
    }
  };

  const handlePreview = async () => {
    try {
      const res = await API.fetch(`/api/attachments/${att.id}/download`);
      const blob = await res.blob();
      const url = URL.createObjectURL(blob);
      onPreview({ name: att.name, url, type: att.mime_type });
    } catch (err) {
      Toasts.error('Erreur de prévisualisation');
    }
  };

  return React.createElement('div', { className: 'attachment-item' },
    React.createElement('span', { className: 'attachment-icon' }, icon),
    React.createElement('div', { className: 'attachment-info' },
      React.createElement('div', { className: 'attachment-name' }, att.name),
      React.createElement('div', { className: 'attachment-size' }, formatSize(att.size || 0))
    ),
    React.createElement('div', { className: 'attachment-actions' },
      (isImage || isPdf) && React.createElement('button', { onClick: handlePreview, title: 'Prévisualiser' }, '\uD83D\uDC41'),
      React.createElement('button', { onClick: handleDownload, title: 'Télécharger' }, '\u2B07'),
      React.createElement('button', { onClick: () => onDelete(att.id), title: 'Supprimer' }, '\u2715')
    )
  );
}

function GrafcetEtape({ step, projectId, phaseColor, onUpdate, onDelete, onAddComment, onDeleteComment, onUpload, onDeleteAttachment, onPreview }) {
  const [expanded, setExpanded] = React.useState(false);
  const [editing, setEditing] = React.useState(false);
  const [editData, setEditData] = React.useState({});
  const [commentText, setCommentText] = React.useState('');
  const [submitting, setSubmitting] = React.useState(false);
  const [uploadProgress, setUploadProgress] = React.useState(null); // { name, pct, loaded, total } or null
  const fileRef = React.useRef(null);

  const status = STATUTS[step.status] || STATUTS.wait;

  const handleStatusChange = async (newStatus) => {
    try {
      await onUpdate(step.id, { status: newStatus });
      Toasts.success(`Statut: ${STATUTS[newStatus].label}`);
    } catch (err) {
      Toasts.error(err.message);
    }
  };

  const handleSaveEdit = async () => {
    try {
      await onUpdate(step.id, editData);
      setEditing(false);
      Toasts.success('Étape mise à jour');
    } catch (err) {
      Toasts.error(err.message);
    }
  };

  const handleAddComment = async () => {
    if (!commentText.trim()) return;
    setSubmitting(true);
    try {
      await onAddComment(step.id, commentText);
      setCommentText('');
      Toasts.success('Commentaire ajouté');
    } catch (err) {
      Toasts.error(err.message);
    } finally {
      setSubmitting(false);
    }
  };

  const [dragging, setDragging] = React.useState(false);

  const processFiles = async (files) => {
    for (const file of files) {
      try {
        setUploadProgress({ name: file.name, pct: 0, loaded: 0, total: file.size });
        await onUpload(step.id, file, (pct, loaded, total) => {
          setUploadProgress({ name: file.name, pct, loaded, total });
        });
        setUploadProgress(null);
        Toasts.success(`${file.name} uploadé`);
      } catch (err) {
        setUploadProgress(null);
        Toasts.error(`Erreur: ${file.name}`);
      }
    }
  };

  const handleFileUpload = async (e) => {
    const files = e.target.files;
    if (!files.length) return;
    await processFiles(files);
    if (fileRef.current) fileRef.current.value = '';
  };

  const handleDrop = async (e) => {
    e.preventDefault();
    e.stopPropagation();
    setDragging(false);
    const files = e.dataTransfer.files;
    if (files.length) await processFiles(files);
  };

  const handleDragOver = (e) => { e.preventDefault(); e.stopPropagation(); setDragging(true); };
  const handleDragLeave = (e) => { e.preventDefault(); e.stopPropagation(); setDragging(false); };

  const comments = step.comments || [];
  const attachments = step.attachments || [];

  return React.createElement('div', { className: 'grafcet-etape' },
    React.createElement('div', {
      className: `etape-bloc status-${step.status}`,
      onClick: () => setExpanded(!expanded)
    },
      React.createElement('div', { className: 'etape-drag', onClick: e => e.stopPropagation() }, '\u2630'),
      React.createElement('div', { className: 'etape-status-icon' }, status.icon),
      React.createElement('div', { className: 'etape-info' },
        React.createElement('div', { className: 'etape-abbr' }, step.abbr || step.name),
        React.createElement('div', { className: 'etape-name', title: step.tooltip }, step.name)
      ),
      React.createElement('div', { className: 'etape-badges' },
        comments.length > 0 && React.createElement('span', {
          className: 'etape-badge',
          style: { background: 'rgba(232,164,74,0.13)', color: 'var(--accent)' }
        }, '\uD83D\uDCAC ', comments.length),
        attachments.length > 0 && React.createElement('span', {
          className: 'etape-badge',
          style: { background: 'var(--purple-bg)', color: 'var(--purple)' }
        }, '\uD83D\uDCCE ', attachments.length)
      ),
      React.createElement('div', { className: `etape-expand-icon ${expanded ? 'open' : ''}` }, '\u25BC')
    ),

    expanded && React.createElement('div', { className: 'etape-details' },
      // Info grid
      React.createElement('div', { className: 'etape-details-grid' },
        React.createElement('div', { className: 'detail-field' },
          React.createElement('label', null, 'Responsable'),
          editing
            ? React.createElement('input', { className: 'edit-input', value: editData.responsible || '',
                onChange: e => setEditData({...editData, responsible: e.target.value}) })
            : React.createElement('div', { className: 'value' }, step.responsible || '—')
        ),
        React.createElement('div', { className: 'detail-field' },
          React.createElement('label', null, 'Livrable'),
          editing
            ? React.createElement('input', { className: 'edit-input', value: editData.deliverable || '',
                onChange: e => setEditData({...editData, deliverable: e.target.value}) })
            : React.createElement('div', { className: 'value' }, step.deliverable || '—')
        ),
        React.createElement('div', { className: 'detail-field' },
          React.createElement('label', null, 'Statut'),
          React.createElement('select', {
            className: 'status-select',
            value: step.status,
            onChange: e => handleStatusChange(e.target.value),
            onClick: e => e.stopPropagation()
          },
            Object.entries(STATUTS).map(([k, v]) =>
              React.createElement('option', { key: k, value: k }, `${v.icon} ${v.label}`)
            )
          )
        ),
        React.createElement('div', { className: 'detail-field' },
          React.createElement('label', null, 'Tooltip'),
          editing
            ? React.createElement('input', { className: 'edit-input', value: editData.tooltip || '',
                onChange: e => setEditData({...editData, tooltip: e.target.value}) })
            : React.createElement('div', { className: 'value', style: { fontSize: '12px', color: 'var(--text-muted)' } },
                step.tooltip || '—')
        )
      ),

      // Edit actions
      React.createElement('div', { style: { display: 'flex', gap: '8px', marginBottom: '12px' } },
        editing
          ? React.createElement(React.Fragment, null,
              React.createElement('button', { className: 'btn btn-success btn-sm', onClick: handleSaveEdit }, 'Sauvegarder'),
              React.createElement('button', { className: 'btn btn-ghost btn-sm', onClick: () => setEditing(false) }, 'Annuler')
            )
          : React.createElement(React.Fragment, null,
              React.createElement('button', { className: 'btn btn-ghost btn-sm',
                onClick: () => { setEditing(true); setEditData({ name: step.name, abbr: step.abbr, tooltip: step.tooltip, responsible: step.responsible, deliverable: step.deliverable }); }
              }, '\u270E Modifier'),
              React.createElement('button', { className: 'btn btn-ghost btn-sm',
                style: { color: 'var(--red)' },
                onClick: () => { if (confirm('Supprimer cette étape ?')) onDelete(step.id); }
              }, '\u2715 Supprimer')
            )
      ),

      // Editing name/abbr
      editing && React.createElement('div', {
        style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '12px', marginBottom: '12px' }
      },
        React.createElement('div', { className: 'detail-field' },
          React.createElement('label', null, 'Nom'),
          React.createElement('input', { className: 'edit-input', value: editData.name || '',
            onChange: e => setEditData({...editData, name: e.target.value}) })
        ),
        React.createElement('div', { className: 'detail-field' },
          React.createElement('label', null, 'Abréviation'),
          React.createElement('input', { className: 'edit-input', value: editData.abbr || '',
            onChange: e => setEditData({...editData, abbr: e.target.value}) })
        )
      ),

      // Attachments
      React.createElement('div', { className: 'attachments-section' },
        React.createElement('div', { className: 'section-title' },
          React.createElement('h4', null, '\uD83D\uDCCE Pièces jointes ',
            React.createElement('span', { className: 'count' }, attachments.length)
          )
        ),
        attachments.map(att =>
          React.createElement(AttachmentItem, {
            key: att.id, att, projectId,
            onDelete: (id) => onDeleteAttachment(id),
            onPreview: onPreview
          })
        ),
        uploadProgress
          ? React.createElement('div', { className: 'upload-progress' },
              React.createElement('div', { className: 'upload-progress-info' },
                React.createElement('span', { className: 'upload-progress-name' }, uploadProgress.name),
                React.createElement('span', { className: 'upload-progress-pct' }, uploadProgress.pct + '%')
              ),
              React.createElement('div', { className: 'upload-progress-bar' },
                React.createElement('div', {
                  className: 'upload-progress-fill',
                  style: { width: uploadProgress.pct + '%' }
                })
              ),
              React.createElement('div', { className: 'upload-progress-size' },
                formatSize(uploadProgress.loaded) + ' / ' + formatSize(uploadProgress.total)
              )
            )
          : React.createElement('label', {
              className: `upload-zone ${dragging ? 'drag-over' : ''}`,
              style: { display: 'block' },
              onDrop: handleDrop,
              onDragOver: handleDragOver,
              onDragEnter: handleDragOver,
              onDragLeave: handleDragLeave
            },
              React.createElement('p', null, dragging ? '\uD83D\uDCE5 Déposez vos fichiers ici' : '\u2795 Cliquez ou glissez des fichiers ici'),
              React.createElement('input', {
                ref: fileRef, type: 'file', multiple: true,
                style: { display: 'none' },
                onChange: handleFileUpload
              })
            )
      ),

      // Comments
      React.createElement('div', { className: 'comments-section' },
        React.createElement('div', { className: 'section-title' },
          React.createElement('h4', null, '\uD83D\uDCAC Commentaires ',
            React.createElement('span', { className: 'count' }, comments.length)
          )
        ),
        comments.map(c =>
          React.createElement('div', { key: c.id, className: 'comment-item' },
            React.createElement('div', { className: 'comment-header' },
              React.createElement('span', { className: 'comment-author' }, c.author_name),
              React.createElement('span', null,
                React.createElement('span', { className: 'comment-date' }, c.date),
                React.createElement('button', {
                  className: 'comment-delete',
                  onClick: () => { if (confirm('Supprimer ce commentaire ?')) onDeleteComment(c.id); }
                }, ' \u2715')
              )
            ),
            React.createElement('div', { className: 'comment-text' }, c.text)
          )
        ),
        React.createElement('div', { className: 'comment-form' },
          React.createElement('textarea', {
            value: commentText, placeholder: 'Ajouter un commentaire...',
            onChange: e => setCommentText(e.target.value),
            onKeyDown: e => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleAddComment(); } }
          }),
          React.createElement('button', {
            className: 'btn btn-primary btn-sm',
            disabled: !commentText.trim() || submitting,
            onClick: handleAddComment
          }, '\u27A4')
        )
      )
    )
  );
}

function PhaseGrafcet({ phase, projectId, onUpdateStep, onDeleteStep, onAddStep, onAddComment, onDeleteComment, onUpload, onDeleteAttachment, onUpdatePhase, onDeletePhase, onPreview }) {
  const [collapsed, setCollapsed] = React.useState(false);
  const [editingPhase, setEditingPhase] = React.useState(false);
  const [phaseName, setPhaseName] = React.useState(phase.name);
  const [phaseFullName, setPhaseFullName] = React.useState(phase.full_name);

  const steps = phase.steps || [];
  const doneCount = steps.filter(s => s.status === 'done').length;
  const activeCount = steps.filter(s => s.status === 'active').length;

  const handleSavePhase = async () => {
    try {
      await onUpdatePhase(phase.id, { name: phaseName, full_name: phaseFullName });
      setEditingPhase(false);
      Toasts.success('Phase mise à jour');
    } catch (err) {
      Toasts.error(err.message);
    }
  };

  return React.createElement('div', { className: 'phase-container', id: `phase-${phase.id}` },
    React.createElement('div', {
      className: 'phase-header',
      style: { background: `linear-gradient(135deg, ${phase.color}, ${phase.color}88)` },
      onClick: () => setCollapsed(!collapsed)
    },
      React.createElement('div', { className: 'phase-header-left' },
        React.createElement('span', { className: `phase-chevron ${!collapsed ? 'open' : ''}` }, '\u25B6'),
        editingPhase
          ? React.createElement('div', { className: 'inline-edit-row', onClick: e => e.stopPropagation() },
              React.createElement('input', { className: 'edit-input', value: phaseName,
                onChange: e => setPhaseName(e.target.value), style: { width: '150px' } }),
              React.createElement('input', { className: 'edit-input', value: phaseFullName,
                onChange: e => setPhaseFullName(e.target.value), style: { width: '200px' }, placeholder: 'Nom complet' }),
              React.createElement('button', { className: 'btn btn-sm', style: { background: 'rgba(255,255,255,0.2)', color: 'white', border: 'none' }, onClick: handleSavePhase }, '\u2713'),
              React.createElement('button', { className: 'btn btn-sm', style: { background: 'rgba(255,255,255,0.1)', color: 'white', border: 'none' }, onClick: () => setEditingPhase(false) }, '\u2715')
            )
          : React.createElement(React.Fragment, null,
              React.createElement('span', { className: 'phase-name' }, phase.ext_id, ' \u2014 ', phase.name),
              phase.full_name && React.createElement('span', { className: 'phase-fullname' }, phase.full_name)
            )
      ),
      React.createElement('div', { className: 'phase-header-right' },
        React.createElement('span', { className: 'phase-stats' },
          doneCount, '/', steps.length,
          activeCount > 0 ? ` \u2022 ${activeCount} en cours` : ''
        ),
        React.createElement('div', { className: 'phase-actions', onClick: e => e.stopPropagation() },
          React.createElement('button', { onClick: () => onAddStep(phase.id) }, '+'),
          React.createElement('button', { onClick: () => { setEditingPhase(true); setPhaseName(phase.name); setPhaseFullName(phase.full_name); } }, '\u270E'),
          React.createElement('button', { onClick: () => { if (confirm(`Supprimer la phase "${phase.name}" ?`)) onDeletePhase(phase.id); } }, '\u2715')
        )
      )
    ),

    !collapsed && React.createElement('div', { className: 'phase-body' },
      steps.length === 0
        ? React.createElement('div', { style: { textAlign: 'center', padding: '20px', color: 'var(--text-muted)' } }, 'Aucune étape')
        : React.createElement('div', { className: 'phase-steps' },
            steps.map((step, i) =>
              React.createElement(React.Fragment, { key: step.id },
                React.createElement(GrafcetEtape, {
                  step, projectId, phaseColor: phase.color,
                  onUpdate: onUpdateStep,
                  onDelete: onDeleteStep,
                  onAddComment, onDeleteComment,
                  onUpload, onDeleteAttachment, onPreview
                })
              )
            )
          )
    )
  );
}

function MiniGrafcet({ phases, onSelectPhase }) {
  return React.createElement('div', { className: 'mini-grafcet' },
    React.createElement('h4', {
      style: { fontSize: '11px', fontWeight: '700', color: 'var(--text-muted)', textTransform: 'uppercase',
        letterSpacing: '1px', marginBottom: '12px' }
    }, 'Vue synoptique'),
    phases.map((phase, i) => {
      const steps = phase.steps || [];
      const done = steps.filter(s => s.status === 'done').length;
      const hasActive = steps.some(s => s.status === 'active');
      const pct = steps.length > 0 ? (done / steps.length) * 100 : 0;

      return React.createElement(React.Fragment, { key: phase.id },
        React.createElement('div', {
          className: `mini-phase ${hasActive ? 'active' : ''}`,
          onClick: () => onSelectPhase(phase.id)
        },
          React.createElement('div', { className: 'mini-phase-header' },
            React.createElement('span', { className: 'mini-phase-name', style: { color: phase.color } },
              phase.ext_id
            ),
            React.createElement('span', { className: 'mini-phase-count' }, `${done}/${steps.length}`)
          ),
          React.createElement('div', { className: 'mini-phase-bar' },
            React.createElement('div', {
              className: 'mini-phase-bar-fill',
              style: { width: `${pct}%`, backgroundColor: phase.color }
            })
          )
        )
      );
    })
  );
}
