<template>
  <div class="plotly-chart">
    <div class="chart-header">
      <h3>{{ title }}</h3>
      <button v-if="loading" class="refresh-btn" disabled>
        Chargement...
      </button>

    </div>
    
    <div 
      ref="plotlyDiv" 
      :id="chartId"
      class="chart-container"
      :class="{ loading: loading }"
    >
      <div v-if="loading" class="loading-spinner">
        <div class="spinner"></div>
        <p>Chargement des données...</p>
      </div>

    </div>
  </div>
</template>

<script>
import { ref, onMounted, onUnmounted, nextTick, watch } from 'vue'
import Plotly from 'plotly.js-dist'
import { csvParse } from 'd3-dsv'

export default {
  name: 'PlotlyChart',
  props: {
    title: {
      type: String,
      default: ''
    },
    csvUrl: {
      type: String,
      default: ''
    },
    dataType: {
      type: String,
      default: 'csv', // 'csv' ou 'football-field'
      validator: (value) => ['csv', 'football-field'].includes(value)
    },
    chartId: {
      type: String,
      default: () => ``
    },
    height: {
      type: [String, Number],
      default: 500
    },
    customLayout: {
      type: Object,
      default: () => ({})
    },
    keypointsData: {
      type: Array,
      default: () => []
    },
    cameraParams: {
      type: Object,
      default: () => null
    }
  },
  emits: ['data-loaded', 'error'],
  setup(props, { emit }) {
    const plotlyDiv = ref(null)
    const loading = ref(false)
    const error = ref(null)
    const chartData = ref([])
    
    // Fonction pour décompresser les données du CSV
    const unpack = (rows, key) => {
      return rows.map(row => row[key])
    }
    
    // Fonction pour charger les données depuis le CSV
    const loadData = async () => {
      loading.value = true
      error.value = null
      
      try {
        if (props.dataType === 'football-field') {
          // Générer les données du terrain de football
          await generateFootballFieldData()
        } else {
          // Charger depuis CSV (comportement original)
          await loadCsvData()
        }
        
        await renderChart()
        emit('data-loaded', { traces: chartData.value })
        
      } catch (err) {
        console.error('Erreur lors du chargement des données:', err)
        error.value = err.message
        emit('error', err)
      } finally {
        loading.value = false
      }
    }
    
    // Fonction pour charger les données CSV (ancien comportement)
    const loadCsvData = async () => {
      const response = await fetch(props.csvUrl)
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`)
      }
      
      const csvText = await response.text()
      const rows = csvParse(csvText)
      
      if (!rows || rows.length === 0) {
        throw new Error('Aucune donnée trouvée dans le CSV')
      }
      
      // Création des traces comme dans votre exemple
      const trace1 = {
        x: unpack(rows, 'x1'),
        y: unpack(rows, 'y1'),
        z: unpack(rows, 'z1'),
        mode: 'markers',
        marker: {
          size: 12,
          line: {
            color: 'rgba(217, 217, 217, 0.14)',
            width: 0.5
          },
          opacity: 0.8
        },
        type: 'scatter3d',
        name: 'Série 1'
      }
      
      const trace2 = {
        x: unpack(rows, 'x2'),
        y: unpack(rows, 'y2'),
        z: unpack(rows, 'z2'),
        mode: 'markers',
        marker: {
          color: 'rgb(127, 127, 127)',
          size: 12,
          symbol: 'circle',
          line: {
            color: 'rgb(204, 204, 204)',
            width: 1
          },
          opacity: 0.8
        },
        type: 'scatter3d',
        name: 'Série 2'
      }
      
      chartData.value = [trace1, trace2]
    }
    
    // Fonction pour générer les données du terrain de football
    const generateFootballFieldData = async () => {
      const fieldLength = 105 // mètres
      const fieldWidth = 68   // mètres
      
      const traces = []
      
      // 1. Contour principal du terrain
      const fieldCorners = {
        x: [-fieldLength/2, fieldLength/2, fieldLength/2, -fieldLength/2, -fieldLength/2],
        y: [-fieldWidth/2, -fieldWidth/2, fieldWidth/2, fieldWidth/2, -fieldWidth/2],
        z: [0, 0, 0, 0, 0],
        mode: 'lines',
        type: 'scatter3d',
        line: { color: '#00FF00', width: 6 },
        name: 'Terrain principal',
        showlegend: true
      }
      traces.push(fieldCorners)
      
      // 2. Ligne médiane
      const midline = {
        x: [0, 0],
        y: [-fieldWidth/2, fieldWidth/2],
        z: [0, 0],
        mode: 'lines',
        type: 'scatter3d',
        line: { color: 'bleu', width: 4 },
        name: 'Ligne médiane',
        showlegend: true
      }
      traces.push(midline)
      
      // 3. Surface de réparation gauche
      const leftPenaltyArea = {
        x: [-fieldLength/2, -fieldLength/2+16.5, -fieldLength/2+16.5, -fieldLength/2, -fieldLength/2],
        y: [-20.16, -20.16, 20.16, 20.16, -20.16],
        z: [0, 0, 0, 0, 0],
        mode: 'lines',
        type: 'scatter3d',
        line: { color: '#FF6B6B', width: 5 },
        name: 'Surface de réparation',
        showlegend: true
      }
      traces.push(leftPenaltyArea)
      
      // 4. Surface de réparation droite
      const rightPenaltyArea = {
        x: [fieldLength/2, fieldLength/2-16.5, fieldLength/2-16.5, fieldLength/2, fieldLength/2],
        y: [-20.16, -20.16, 20.16, 20.16, -20.16],
        z: [0, 0, 0, 0, 0],
        mode: 'lines',
        type: 'scatter3d',
        line: { color: '#FF6B6B', width: 5 },
        name: 'Surface de réparation droite',
        showlegend: false // Eviter la duplication dans la légende
      }
      traces.push(rightPenaltyArea)
      
      // 5. Surface de but gauche (6 yards)
      const leftGoalArea = {
        x: [-fieldLength/2, -fieldLength/2+5.5, -fieldLength/2+5.5, -fieldLength/2, -fieldLength/2],
        y: [-9.16, -9.16, 9.16, 9.16, -9.16],
        z: [0, 0, 0, 0, 0],
        mode: 'lines',
        type: 'scatter3d',
        line: { color: '#4ECDC4', width: 4 },
        name: 'Surface de but',
        showlegend: true
      }
      traces.push(leftGoalArea)
      
      // 6. Surface de but droite
      const rightGoalArea = {
        x: [fieldLength/2, fieldLength/2-5.5, fieldLength/2-5.5, fieldLength/2, fieldLength/2],
        y: [-9.16, -9.16, 9.16, 9.16, -9.16],
        z: [0, 0, 0, 0, 0],
        mode: 'lines',
        type: 'scatter3d',
        line: { color: '#4ECDC4', width: 4 },
        showlegend: false
      }
      traces.push(rightGoalArea)
      
      // 7. Cercle central
      const circlePoints = 50
      const radius = 9.15
      const theta = Array.from({length: circlePoints}, (_, i) => (i / (circlePoints - 1)) * 2 * Math.PI)
      const centerCircle = {
        x: theta.map(t => radius * Math.cos(t)),
        y: theta.map(t => radius * Math.sin(t)),
        z: theta.map(() => 0),
        mode: 'lines',
        type: 'scatter3d',
        line: { color: '#FFE66D', width: 4 },
        name: 'Cercle central',
        showlegend: true
      }
      traces.push(centerCircle)
      
      // 8. Points de penalty
      const penaltySpots = {
        x: [-fieldLength/2 + 11, fieldLength/2 - 11],
        y: [0, 0],
        z: [0, 0],
        mode: 'markers',
        type: 'scatter3d',
        marker: { 
          color: '#FFFFFF', 
          size: 8,
          symbol: 'circle'
        },
        name: 'Points de penalty',
        showlegend: true
      }
      traces.push(penaltySpots)
      
      // 9. Point central
      const centerSpot = {
        x: [0],
        y: [0],
        z: [0],
        mode: 'markers',
        type: 'scatter3d',
        marker: { 
          color: '#FFFFFF', 
          size: 6,
          symbol: 'circle'
        },
        name: 'Point central',
        showlegend: true
      }
      traces.push(centerSpot)
      
      // 10. Keypoints détectés (si disponibles)
      if (props.keypointsData && props.keypointsData.length > 0) {
        const keypointsTrace = {
          x: props.keypointsData.map(kp => kp.world_coords?.x || 0),
          y: props.keypointsData.map(kp => kp.world_coords?.y || 0),
          z: props.keypointsData.map(() => 0.5), // Légèrement au-dessus du terrain
          mode: 'markers+text',
          type: 'scatter3d',
          marker: { 
            color: '#FF1744', 
            size: 6,
            symbol: 'circle',
            line: {
              color: '#FFFFFF',
              width: 2
            }
          },
          text: props.keypointsData.map(kp => `KP ${kp.id}`),
          textposition: 'top center',
          textfont: {
            color: 'black',
            size: 8,
            family: 'Arial, sans-serif'
          },
          name: 'Keypoints détectés',
          showlegend: false,
          hovertemplate: 
            '<b>Keypoint %{text}</b><br>' +
            'X: %{x:.1f}m<br>' +
            'Y: %{y:.1f}m<br>' +
            '<extra></extra>'
        }
        traces.push(keypointsTrace)
      }
      
      // 11. Position de la caméra (si disponible)
      if (props.cameraParams?.position_meters) {
        const [camX, camY, camZ] = props.cameraParams.position_meters
        
        const cameraTrace = {
          x: [camX],
          y: [camY], 
          z: [camZ],
          mode: 'markers+text',
          type: 'scatter3d',
          marker: { 
            color: '#2196F3', 
            size: 15,
            symbol: 'square',
            line: {
              color: '#FFFFFF',
              width: 3
            }
          },
          text: ['📷 Caméra'],
          textposition: 'top center',
          textfont: {
            color: '#2196F3',
            size: 12,
            family: 'Arial, sans-serif'
          },
          name: 'Position caméra',
          showlegend: false,
          hovertemplate: 
            '<b>📷 Position de la caméra</b><br>' +
            'X: %{x:.2f}m<br>' +
            'Y: %{y:.2f}m<br>' +
            'Z: %{z:.2f}m<br>' +
            '<extra></extra>'
        }
        traces.push(cameraTrace)
        
        // 12. Ligne de vue de la caméra vers le centre du terrain (optionnel)
        const sightLineTrace = {
          x: [camX, 0],
          y: [camY, 0],
          z: [camZ, 0],
          mode: 'lines',
          type: 'scatter3d',
          line: { 
            color: '#2196F3', 
            width: 2,
            dash: 'dot'
          },
          name: 'Ligne de vue',
          showlegend: false,
          hoverinfo: 'skip'
        }
        traces.push(sightLineTrace)
      }
      
      chartData.value = traces
    }
    
    // Fonction pour rendre le graphique
    const renderChart = async () => {
      if (!plotlyDiv.value || chartData.value.length === 0) return
      
      let defaultLayout = {
        margin: {
          l: 0,
          r: 0,
          b: 0,
          t: 0
        },
        height: typeof props.height === 'number' ? props.height : parseInt(props.height),
        scene: {
          xaxis: { title: 'X Axis' },
          yaxis: { title: 'Y Axis' },
          zaxis: { title: 'Z Axis' }
        }
      }
      
      // Layout spécifique pour le terrain de football
      if (props.dataType === 'football-field') {
        const shift_l = 10;
        const shift_w = 40;
        
        // Ranges de base
        let baseLength = 52.5 + shift_l;  // range X: [-baseLength, baseLength]
        let baseWidth = 34 + shift_w;     // range Y: [-baseWidth, baseWidth]  
        let baseHeight = 35;              // range Z: [-baseHeight, baseHeight]
        
        // Position de la caméra
        const camX = props.cameraParams?.position_meters?.[0] || 0;
        const camY = props.cameraParams?.position_meters?.[1] || 0;
        const camZ = props.cameraParams?.position_meters?.[2] || 0;
        
        // Vérifier si la caméra dépasse les ranges et ajuster si nécessaire
        const maxCamX = Math.abs(camX);
        const maxCamY = Math.abs(camY);
        const maxCamZ = Math.abs(camZ);
        
        // Ratios actuels pour conserver les proportions
        const ratioXY = baseLength / baseWidth;  // ratio X/Y
        const ratioXZ = baseLength / baseHeight; // ratio X/Z
        const ratioYZ = baseWidth / baseHeight;  // ratio Y/Z
        
        // Ajuster les ranges si la caméra dépasse
        if (maxCamX > baseLength) {
          baseLength = maxCamX + 10; // marge de 10m
          baseWidth = baseLength / ratioXY; // conserver ratio X/Y
          baseHeight = baseLength / ratioXZ; // conserver ratio X/Z
        }
        
        if (maxCamY > baseWidth) {
          baseWidth = maxCamY + 10; // marge de 10m
          baseLength = baseWidth * ratioXY; // conserver ratio X/Y
          baseHeight = baseWidth / ratioYZ; // conserver ratio Y/Z
        }
        
        if (maxCamZ > baseHeight) {
          baseHeight = maxCamZ + 10; // marge de 10m
          baseLength = baseHeight * ratioXZ; // conserver ratio X/Z
          baseWidth = baseHeight * ratioYZ; // conserver ratio Y/Z
        }
        
        // Valeurs finales
        const length = baseLength;
        const witdh = baseWidth;
        const height = baseHeight;

        defaultLayout.scene = {
          xaxis: { 
            title: '',
            range: [-length, length],
            showgrid: false,
            showticklabels: false,
            showline: false,
            zeroline: false,
            dtick: 20
          },
          yaxis: { 
            title: '',
            range: [-witdh, witdh],
            showgrid: false,
            showticklabels: false,
            showline: false,
            zeroline: false,
            dtick: 20
          },
          zaxis: { 
            title: '',
            range: [-height, height],
            showgrid: false,
            showticklabels: false,
            showline: false,
            zeroline: false,
            dtick: 0
          },
          aspectmode: 'manual',
          aspectratio: { x: 1., y: 1, z: 0.3 },
          camera: {
            eye: { x: 0, y: 1, z: -0.6 },
            center: { x: 0, y: 0, z: 0 },
            up: { x: 0, y: -1, z: 0 } 
          }
        }
        defaultLayout.margin.t = 10
        defaultLayout.showlegend = false
      }
      
      const layout = {
        ...defaultLayout,
        ...props.customLayout
      }
      
      const config = {
        responsive: true,
        displayModeBar: true,
        modeBarButtonsToRemove: ['pan2d', 'lasso2d'],
        displaylogo: false
      }
      
      await nextTick()
      await Plotly.newPlot(plotlyDiv.value, chartData.value, layout, config)
    }
    
    // Fonction de nettoyage
    const cleanup = () => {
      if (plotlyDiv.value) {
        Plotly.purge(plotlyDiv.value)
      }
    }
    
    // Fonction pour redimensionner le graphique
    const resizeChart = () => {
      if (plotlyDiv.value) {
        Plotly.Plots.resize(plotlyDiv.value)
      }
    }
    
    // Watcher pour recharger quand les keypoints changent
    watch(() => props.keypointsData, () => {
      if (props.dataType === 'football-field') {
        loadData()
      }
    }, { deep: true })

    // Watcher pour recharger quand les paramètres de la caméra changent
    watch(() => props.cameraParams, () => {
      if (props.dataType === 'football-field') {
        loadData()
      }
    }, { deep: true })
    
    // Lifecycle hooks
    onMounted(() => {
      loadData()
      window.addEventListener('resize', resizeChart)
    })
    
    onUnmounted(() => {
      cleanup()
      window.removeEventListener('resize', resizeChart)
    })
    
    return {
      plotlyDiv,
      loading,
      error,
      loadData,
      resizeChart
    }
  }
}
</script>

<style scoped>
.plotly-chart {
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
  overflow: hidden;
}



.chart-container {
  position: relative;
  min-height: 200px;
}

.chart-container.loading {
  display: flex;
  align-items: center;
  justify-content: center;
}

.loading-spinner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
}

.spinner {
  width: 40px;
  height: 40px;
  border: 4px solid #f3f3f3;
  border-top: 4px solid #007bff;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

.error-message {
  text-align: center;
  padding: 2rem;
  color: #dc3545;
}

.retry-btn {
  background: #dc3545;
  color: white;
  border: none;
  padding: 0.5rem 1rem;
  border-radius: 4px;
  cursor: pointer;
  margin-top: 1rem;
}

.retry-btn:hover {
  background: #c82333;
}

/* Correction de l'alignement de la modebar Plotly */
.plotly-chart :deep(.modebar) {
  display: flex !important;
  align-items: center !important;
  justify-content: flex-end !important;
  padding: 5px !important;
  background: none !important;
}

.plotly-chart :deep(.modebar-group) {
  display: flex !important;
  align-items: center !important;
  margin: 0 2px !important;
  background: none !important;
  border: none !important;
}

.plotly-chart :deep(.modebar-btn) {
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  margin: 0 1px !important;
  background: none !important;
  border: none !important;
}

/* Personnalisation des icônes */
.plotly-chart :deep(.modebar-btn .icon path) {
  fill: black !important;
}

.plotly-chart :deep(.modebar-btn:hover) {
  background: rgba(0, 0, 0, 0.1) !important;
}

.plotly-chart :deep(.modebar-btn.active) {
  background: rgba(0, 0, 0, 0.2) !important;
}

/* Responsive */
@media (max-width: 768px) {
  .chart-header {
    flex-direction: column;
    gap: 0.5rem;
    text-align: center;
  }
  
  .chart-container {
    min-height: 300px;
  }
}
</style> 