<template>
  <div class="git-contribution-chart">
    <div class="flex justify-between align-items-center mb-4">
      <h3 class="text-lg font-semibold m-0">Contributions {{ currentYear }}</h3>
      <div v-if="!loading && totalContributions > 0" class="text-500">
        <i class="pi pi-calendar mr-2"></i>
        {{ totalContributions }} Commits
      </div>
    </div>

    <div v-if="loading" class="text-center py-8">
      <i class="pi pi-spin pi-spinner text-4xl text-primary"></i>
    </div>

    <div v-else-if="error" class="p-4 border-round surface-border border-1 text-center">
      <i class="pi pi-exclamation-triangle text-orange-500 text-3xl mb-2"></i>
      <p class="text-500">{{ error }}</p>
    </div>

    <div v-else-if="contributionGrid.length > 0" class="contribution-heatmap">
      <div class="heatmap-wrapper">
        <!-- Month labels -->
        <div class="month-labels-row">
          <div class="weekday-spacer"></div>
          <div class="month-labels">
            <div 
              v-for="(month, index) in monthLabels"
              :key="index"
              :style="{ gridColumn: `${month.startCol} / span ${month.colSpan}` }"
              class="month-label"
            >
              {{ month.label }}
            </div>
          </div>
        </div>

        <!-- Grid with weekday labels -->
        <div class="grid-container">
          <!-- Weekday labels on the left -->
          <div class="weekday-labels">
            <div class="weekday-label"></div>
            <div class="weekday-label">Mo</div>
            <div class="weekday-label"></div>
            <div class="weekday-label">Mi</div>
            <div class="weekday-label"></div>
            <div class="weekday-label">Fr</div>
            <div class="weekday-label"></div>
          </div>

          <!-- Heatmap grid -->
          <div class="heatmap-grid">
            <div 
              v-for="(day, index) in contributionGrid"
              :key="index"
              :class="['contribution-cell', getIntensityClass(day.count)]"
              :style="{ gridRow: day.row, gridColumn: day.col }"
              :title="day.tooltip"
            >
            </div>
          </div>
        </div>
      </div>
      
      <div class="legend mt-3 flex gap-2 align-items-center justify-end">
        <span class="text-sm text-500">Weniger</span>
        <div class="legend-cell intensity-0"></div>
        <div class="legend-cell intensity-1"></div>
        <div class="legend-cell intensity-2"></div>
        <div class="legend-cell intensity-3"></div>
        <div class="legend-cell intensity-4"></div>
        <span class="text-sm text-500">Mehr</span>
      </div>
    </div>

    <div v-else class="p-4 border-round surface-border border-1 text-center text-500">
      <i class="pi pi-info-circle text-3xl mb-2"></i>
      <p>Keine Contributions für {{ currentYear }} gefunden</p>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, watch } from 'vue'
import { useToast } from 'primevue/usetoast'

const props = defineProps({
  repositoryId: {
    type: Number,
    required: true
  },
  branch: {
    type: String,
    default: 'main'
  },
  author: {
    type: String,
    default: null
  },
  year: {
    type: Number,
    default: null
  }
})

const toast = useToast()
const contributionData = ref([])
const loading = ref(false)
const error = ref(null)
const currentYear = computed(() => props.year || new Date().getFullYear())

const totalContributions = computed(() => {
  return contributionData.value.reduce((sum, day) => sum + day.count, 0)
})

const contributionGrid = computed(() => {
  if (contributionData.value.length === 0) return []
  
  const grid = []
  const firstDay = new Date(currentYear.value, 0, 1)
  
  // Find the first Sunday on or before January 1st to start the grid
  const firstSunday = new Date(firstDay)
  while (firstSunday.getDay() !== 0) {
    firstSunday.setDate(firstSunday.getDate() - 1)
  }
  
  // Create a map of dates to contribution counts
  const contributionMap = {}
  contributionData.value.forEach(day => {
    contributionMap[day.date] = day.count
  })
  
  let col = 1
  let currentDate = new Date(firstSunday)
  const lastDay = new Date(currentYear.value, 11, 31)
  
  while (currentDate <= lastDay || currentDate.getDay() !== 0) {
    const dateStr = currentDate.toISOString().split('T')[0]
    const weekday = currentDate.getDay() // 0 = Sunday, 6 = Saturday
    const row = weekday + 1 // Grid row: 1-7 (Sunday-Saturday)
    
    // Only add cells for the current year
    if (currentDate.getFullYear() === currentYear.value) {
      const count = contributionMap[dateStr] || 0
      const date = new Date(currentDate)
      
      grid.push({
        date: dateStr,
        count: count,
        row: row,
        col: col,
        tooltip: `${count} ${count === 1 ? 'Commit' : 'Commits'} am ${formatDateShort(date)}`
      })
    } else if (currentDate < firstDay) {
      // Placeholder for days before the year starts
      grid.push({
        date: dateStr,
        count: -1, // Special value for empty placeholder
        row: row,
        col: col,
        tooltip: ''
      })
    }
    
    // Move to next column on Saturday
    if (weekday === 6) {
      col++
    }
    
    currentDate.setDate(currentDate.getDate() + 1)
  }
  
  return grid
})

const monthLabels = computed(() => {
  if (contributionGrid.value.length === 0) return []
  
  const labels = []
  const months = [
    { name: 'Jan', index: 0 },
    { name: 'Feb', index: 1 },
    { name: 'Mär', index: 2 },
    { name: 'Apr', index: 3 },
    { name: 'Mai', index: 4 },
    { name: 'Jun', index: 5 },
    { name: 'Jul', index: 6 },
    { name: 'Aug', index: 7 },
    { name: 'Sep', index: 8 },
    { name: 'Okt', index: 9 },
    { name: 'Nov', index: 10 },
    { name: 'Dez', index: 11 }
  ]
  
  const firstDayOfYear = new Date(currentYear.value, 0, 1)
  const firstSunday = new Date(firstDayOfYear)
  while (firstSunday.getDay() !== 0) {
    firstSunday.setDate(firstSunday.getDate() - 1)
  }
  
  months.forEach(month => {
    const firstDayOfMonth = new Date(currentYear.value, month.index, 1)
    const daysSinceFirstSunday = Math.floor((firstDayOfMonth - firstSunday) / (1000 * 60 * 60 * 24))
    const col = Math.floor(daysSinceFirstSunday / 7) + 1
    
    // Calculate how many weeks this month spans
    const lastDayOfMonth = new Date(currentYear.value, month.index + 1, 0)
    const daysSinceFirstSundayEnd = Math.floor((lastDayOfMonth - firstSunday) / (1000 * 60 * 60 * 24))
    const endCol = Math.floor(daysSinceFirstSundayEnd / 7) + 1
    const colSpan = Math.max(1, endCol - col + 1)
    
    // Only show month label if there's enough space (at least 2 columns)
    if (colSpan >= 2) {
      labels.push({
        label: month.name,
        startCol: col,
        colSpan: colSpan
      })
    }
  })
  
  return labels
})

const chartData = computed(() => {
  const labels = contributionData.value.map(d => d.date)
  const data = contributionData.value.map(d => d.count)

  return {
    labels,
    datasets: [
      {
        label: 'Commits pro Tag',
        data,
        backgroundColor: '#10b981',
        borderColor: '#059669',
        borderWidth: 1
      }
    ]
  }
})

const chartOptions = ref({
  responsive: true,
  maintainAspectRatio: false,
  plugins: {
    legend: {
      display: false
    },
    tooltip: {
      callbacks: {
        label: (context) => {
          return `${context.parsed.y} Commits`
        }
      }
    }
  },
  scales: {
    x: {
      grid: {
        display: false
      },
      ticks: {
        maxRotation: 45,
        minRotation: 45
      }
    },
    y: {
      beginAtZero: true,
      ticks: {
        stepSize: 1
      }
    }
  }
})

onMounted(() => {
  loadContributions()
})

watch(() => [props.repositoryId, props.branch, props.author, props.year], () => {
  loadContributions()
})

async function loadContributions() {
  loading.value = true
  error.value = null

  try {
    let url = `/api/git-repos/${props.repositoryId}/contributions?branch=${props.branch}&year=${currentYear.value}`
    if (props.author) {
      url += `&author=${encodeURIComponent(props.author)}`
    }

    const response = await fetch(url)

    if (!response.ok) {
      const errorData = await response.json()
      throw new Error(errorData.error || 'Fehler beim Laden der Contributions')
    }

    const data = await response.json()
    contributionData.value = data.contributions || []
  } catch (err) {
    console.error('Error loading contributions:', err)
    error.value = err.message
    toast.add({
      severity: 'error',
      summary: 'Fehler',
      detail: err.message || 'Contributions konnten nicht geladen werden',
      life: 3000
    })
    contributionData.value = []
  } finally {
    loading.value = false
  }
}

function getIntensityClass(count) {
  if (count < 0) return 'intensity-empty' // Placeholder cells
  if (count === 0) return 'intensity-0'
  if (count <= 2) return 'intensity-1'
  if (count <= 5) return 'intensity-2'
  if (count <= 10) return 'intensity-3'
  return 'intensity-4'
}

function formatDate(dateString) {
  if (!dateString) return 'Invalid Date'
  const date = new Date(dateString)
  if (isNaN(date.getTime())) return 'Invalid Date'
  return date.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' })
}

function formatDateShort(date) {
  return date.toLocaleDateString('de-DE', { 
    day: 'numeric', 
    month: 'short',
    year: 'numeric'
  })
}

defineExpose({
  loadContributions
})
</script>

<style scoped>
.git-contribution-chart {
  width: 100%;
}

.contribution-heatmap {
  margin-top: 1rem;
}

.heatmap-wrapper {
  overflow-x: auto;
  padding: 0.5rem 0;
}

.month-labels-row {
  display: flex;
  margin-bottom: 0.5rem;
}

.weekday-spacer {
  width: 30px;
  flex-shrink: 0;
}

.month-labels {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 13px;
  gap: 3px;
  flex: 1;
  margin-left: 3px;
}

.month-label {
  font-size: 0.75rem;
  color: var(--text-color-secondary);
  text-align: left;
}

.grid-container {
  display: flex;
  gap: 3px;
}

.weekday-labels {
  display: grid;
  grid-template-rows: repeat(7, 13px);
  gap: 3px;
  width: 30px;
  flex-shrink: 0;
}

.weekday-label {
  font-size: 0.65rem;
  color: var(--text-color-secondary);
  display: flex;
  align-items: center;
  justify-content: flex-start;
  height: 13px;
}

.heatmap-grid {
  display: grid;
  grid-template-rows: repeat(7, 13px);
  grid-auto-flow: column;
  grid-auto-columns: 13px;
  gap: 3px;
}

.contribution-cell {
  border-radius: 2px;
  cursor: pointer;
  transition: all 0.15s ease;
  min-height: 13px;
  min-width: 13px;
  border: 1px solid rgba(0, 0, 0, 0.06);
}

:global(.dark) .contribution-cell {
  border: 1px solid rgba(255, 255, 255, 0.08);
}

.contribution-cell:not(.intensity-empty):hover {
  outline: 2px solid rgba(0, 0, 0, 0.3);
  outline-offset: 0;
}

.intensity-empty {
  background-color: transparent;
  cursor: default;
}

.intensity-0 {
  background-color: var(--surface-200);
}

.intensity-1 {
  background-color: #9be9a8;
}

.intensity-2 {
  background-color: #40c463;
}

.intensity-3 {
  background-color: #30a14e;
}

.intensity-4 {
  background-color: #216e39;
}

:global(.dark) .intensity-0 {
  background-color: var(--surface-700);
}

.legend {
  display: flex;
  align-items: center;
}

.legend-cell {
  width: 14px;
  height: 14px;
  border-radius: 2px;
}
</style>
