<template>
  <div class="p-6">
    <div class="flex items-center justify-between mb-6">
      <h1 class="text-[1.75rem] font-bold font-[family-name:var(--font-heading)] tracking-tight text-text-primary">Timesheet</h1>

      <!-- Week Navigation -->
      <div class="flex items-center gap-3">
        <button
          @click="prevWeek"
          class="p-1.5 text-text-secondary hover:text-text-primary transition-colors duration-150"
          title="Previous week"
        >
          <ChevronLeft class="w-5 h-5" :stroke-width="2" />
        </button>

        <button
          @click="goToThisWeek"
          class="px-3 py-1.5 text-xs text-text-secondary border border-border-subtle rounded-lg hover:text-text-primary hover:bg-bg-elevated transition-colors duration-150"
        >
          This Week
        </button>

        <button
          @click="nextWeek"
          class="p-1.5 text-text-secondary hover:text-text-primary transition-colors duration-150"
          title="Next week"
        >
          <ChevronRight class="w-5 h-5" :stroke-width="2" />
        </button>

        <span class="text-[0.8125rem] text-text-primary font-medium ml-2">
          {{ weekRangeLabel }}
        </span>
      </div>
    </div>

    <!-- Timesheet Table -->
    <Transition name="fade" mode="out-in">
    <div :key="weekStart" class="bg-bg-surface rounded-lg overflow-hidden">
      <table class="w-full">
        <thead>
          <tr class="border-b border-border-subtle">
            <th class="px-3 py-2 text-left text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] font-medium w-56">
              Project / Task
            </th>
            <th
              v-for="(day, i) in dayHeaders"
              :key="i"
              class="px-3 py-2 text-right text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] font-medium"
              :class="{ 'text-text-secondary': isToday(i) }"
            >
              {{ day }}
            </th>
            <th class="px-3 py-2 text-right text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] font-medium">
              Total
            </th>
          </tr>
        </thead>
        <tbody>
          <!-- Data rows -->
          <tr
            v-for="(row, rowIndex) in rows"
            :key="rowIndex"
            class="border-b border-border-subtle hover:bg-bg-elevated transition-colors duration-150"
          >
            <td class="px-3 py-2">
              <div class="flex items-center gap-2">
                <div
                  class="w-2 h-2 rounded-full shrink-0"
                  :style="{ backgroundColor: row.color }"
                />
                <span class="text-[0.75rem] text-text-primary truncate">{{ row.project_name }}</span>
                <span v-if="row.task_name" class="text-[0.75rem] text-text-tertiary truncate">/ {{ row.task_name }}</span>
              </div>
            </td>
            <td
              v-for="(seconds, dayIndex) in row.days"
              :key="dayIndex"
              class="px-3 py-2 text-right text-[0.75rem] font-mono"
              :class="seconds > 0 ? 'text-accent-text' : 'text-text-tertiary'"
            >
              {{ formatHM(seconds) }}
            </td>
            <td class="px-3 py-2 text-right text-[0.75rem] font-mono text-accent-text font-medium">
              {{ formatHM(rowTotal(row)) }}
            </td>
          </tr>

          <!-- Add Row (inline) -->
          <tr v-if="showAddRow" class="border-b border-border-subtle bg-bg-inset">
            <td class="px-3 py-2" colspan="9">
              <div class="flex items-center gap-3">
                <div class="w-48">
                  <AppSelect
                    v-model="newRowProjectId"
                    :options="availableProjects"
                    label-key="name"
                    value-key="id"
                    placeholder="Select project"
                    :placeholder-value="null"
                    :searchable="true"
                  />
                </div>
                <div class="w-48">
                  <AppSelect
                    v-model="newRowTaskId"
                    :options="availableTasks"
                    label-key="name"
                    value-key="id"
                    placeholder="No task"
                    :placeholder-value="null"
                    :searchable="true"
                    :disabled="!newRowProjectId"
                  />
                </div>
                <button
                  @click="confirmAddRow"
                  :disabled="!newRowProjectId"
                  class="px-3 py-1.5 bg-accent text-bg-base text-xs font-medium rounded-lg hover:bg-accent-hover transition-colors duration-150 disabled:opacity-40 disabled:cursor-not-allowed"
                >
                  Add
                </button>
                <button
                  @click="cancelAddRow"
                  class="px-3 py-1.5 text-text-secondary text-xs hover:text-text-primary transition-colors duration-150"
                >
                  Cancel
                </button>
              </div>
            </td>
          </tr>

          <!-- Empty state -->
          <tr v-if="rows.length === 0 && !showAddRow">
            <td colspan="9" class="px-3 py-8 text-center">
              <p class="text-[0.75rem] text-text-tertiary">No timesheet data for this week</p>
            </td>
          </tr>
        </tbody>
        <tfoot>
          <!-- Column totals -->
          <tr class="border-t border-border-visible bg-bg-elevated">
            <td class="px-3 py-2 text-[0.6875rem] text-text-secondary uppercase tracking-[0.08em] font-medium">
              Total
            </td>
            <td
              v-for="(total, i) in columnTotals"
              :key="i"
              class="px-3 py-2 text-right text-[0.75rem] font-mono text-text-primary font-medium"
            >
              {{ formatHM(total) }}
            </td>
            <td class="px-3 py-2 text-right text-[0.75rem] font-mono text-accent-text font-bold">
              {{ formatHM(grandTotal) }}
            </td>
          </tr>
        </tfoot>
      </table>
    </div>
    </Transition>

    <!-- Add Row Button -->
    <button
      v-if="!showAddRow"
      @click="startAddRow"
      class="mt-3 flex items-center gap-1.5 text-text-secondary text-xs hover:text-text-primary transition-colors duration-150"
    >
      <Plus class="w-4 h-4" :stroke-width="2" />
      Add Row
    </button>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, onMounted } from 'vue'
import { ChevronLeft, ChevronRight, Plus } from 'lucide-vue-next'
import { invoke } from '@tauri-apps/api/core'
import AppSelect from '../components/AppSelect.vue'
import { useProjectsStore, type Task } from '../stores/projects'

const projectsStore = useProjectsStore()

// ── Types ──────────────────────────────────────────────────────────────

interface TimesheetRow {
  project_id: number
  project_name: string
  color: string
  task_id: number | null
  task_name: string | null
  days: number[] // 7 elements, Mon-Sun, in seconds
}

// ── Week state ─────────────────────────────────────────────────────────

/** The Monday of the currently displayed week (YYYY-MM-DD) */
const weekStart = ref('')

function getMonday(d: Date): Date {
  const date = new Date(d)
  const day = date.getDay()
  // getDay(): 0=Sun, 1=Mon … 6=Sat → offset to Monday
  const diff = day === 0 ? -6 : 1 - day
  date.setDate(date.getDate() + diff)
  date.setHours(0, 0, 0, 0)
  return date
}

function formatISODate(d: Date): string {
  const y = d.getFullYear()
  const m = String(d.getMonth() + 1).padStart(2, '0')
  const day = String(d.getDate()).padStart(2, '0')
  return `${y}-${m}-${day}`
}

function goToThisWeek() {
  weekStart.value = formatISODate(getMonday(new Date()))
}

function prevWeek() {
  const d = new Date(weekStart.value)
  d.setDate(d.getDate() - 7)
  weekStart.value = formatISODate(d)
}

function nextWeek() {
  const d = new Date(weekStart.value)
  d.setDate(d.getDate() + 7)
  weekStart.value = formatISODate(d)
}

// ── Computed labels ────────────────────────────────────────────────────

const weekDates = computed(() => {
  const start = new Date(weekStart.value)
  return Array.from({ length: 7 }, (_, i) => {
    const d = new Date(start)
    d.setDate(start.getDate() + i)
    return d
  })
})

const shortDayNames = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']

const shortMonthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']

const dayHeaders = computed(() =>
  weekDates.value.map((d, i) => `${shortDayNames[i]} ${d.getDate()}`)
)

const weekRangeLabel = computed(() => {
  if (weekDates.value.length === 0) return ''
  const first = weekDates.value[0]
  const last = weekDates.value[6]

  const fMonth = shortMonthNames[first.getMonth()]
  const lMonth = shortMonthNames[last.getMonth()]
  const fDay = first.getDate()
  const lDay = last.getDate()
  const year = last.getFullYear()

  if (fMonth === lMonth) {
    return `${fMonth} ${fDay} - ${lDay}, ${year}`
  }
  return `${fMonth} ${fDay} - ${lMonth} ${lDay}, ${year}`
})

function isToday(dayIndex: number): boolean {
  const d = weekDates.value[dayIndex]
  if (!d) return false
  const today = new Date()
  return (
    d.getFullYear() === today.getFullYear() &&
    d.getMonth() === today.getMonth() &&
    d.getDate() === today.getDate()
  )
}

// ── Timesheet data ─────────────────────────────────────────────────────

const rows = ref<TimesheetRow[]>([])
const loading = ref(false)

async function fetchTimesheetData() {
  loading.value = true
  try {
    const data = await invoke<TimesheetRow[]>('get_timesheet_data', {
      weekStart: weekStart.value,
    })
    rows.value = data
  } catch (error) {
    console.error('Failed to fetch timesheet data:', error)
    rows.value = []
  } finally {
    loading.value = false
  }
}

// Re-fetch whenever weekStart changes
watch(weekStart, () => {
  fetchTimesheetData()
})

// ── Totals ─────────────────────────────────────────────────────────────

function rowTotal(row: TimesheetRow): number {
  return row.days.reduce((sum, s) => sum + s, 0)
}

const columnTotals = computed(() => {
  const totals = [0, 0, 0, 0, 0, 0, 0]
  for (const row of rows.value) {
    for (let i = 0; i < 7; i++) {
      totals[i] += row.days[i] ?? 0
    }
  }
  return totals
})

const grandTotal = computed(() =>
  columnTotals.value.reduce((sum, s) => sum + s, 0)
)

// ── Formatting ─────────────────────────────────────────────────────────

function formatHM(seconds: number): string {
  if (seconds === 0) return '-'
  const h = Math.floor(seconds / 3600)
  const m = Math.floor((seconds % 3600) / 60)
  return `${h}:${String(m).padStart(2, '0')}`
}

// ── Add Row ────────────────────────────────────────────────────────────

const showAddRow = ref(false)
const newRowProjectId = ref<number | null>(null)
const newRowTaskId = ref<number | null>(null)
const availableTasks = ref<Task[]>([])

const availableProjects = computed(() =>
  projectsStore.projects.filter((p) => !p.archived)
)

// When selected project changes, fetch its tasks
watch(newRowProjectId, async (projectId) => {
  newRowTaskId.value = null
  if (projectId) {
    availableTasks.value = await projectsStore.fetchTasks(projectId)
  } else {
    availableTasks.value = []
  }
})

function startAddRow() {
  showAddRow.value = true
  newRowProjectId.value = null
  newRowTaskId.value = null
  availableTasks.value = []
}

function cancelAddRow() {
  showAddRow.value = false
  newRowProjectId.value = null
  newRowTaskId.value = null
}

function confirmAddRow() {
  if (!newRowProjectId.value) return

  const project = projectsStore.projects.find(
    (p) => p.id === newRowProjectId.value
  )
  if (!project) return

  // Check if this project+task combo already exists
  const exists = rows.value.some(
    (r) =>
      r.project_id === newRowProjectId.value &&
      r.task_id === (newRowTaskId.value ?? null)
  )
  if (exists) {
    cancelAddRow()
    return
  }

  const taskName =
    newRowTaskId.value
      ? availableTasks.value.find((t) => t.id === newRowTaskId.value)?.name ?? null
      : null

  rows.value.push({
    project_id: project.id!,
    project_name: project.name,
    color: project.color,
    task_id: newRowTaskId.value,
    task_name: taskName,
    days: [0, 0, 0, 0, 0, 0, 0],
  })

  cancelAddRow()
}

// ── Init ───────────────────────────────────────────────────────────────

onMounted(async () => {
  await projectsStore.fetchProjects()
  goToThisWeek() // triggers watch → fetchTimesheetData
})
</script>
