<template>
  <div class="p-6">
    <!-- Header -->
    <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">Projects</h1>
      <button
        @click="openCreateDialog"
        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"
      >
        + Add
      </button>
    </div>

    <!-- Projects Grid -->
    <TransitionGroup v-if="projectsStore.projects.length > 0" name="list" tag="div" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
      <div
        v-for="(project, index) in projectsStore.projects"
        :key="project.id"
        class="group bg-bg-surface border border-border-subtle rounded-lg shadow-[0_1px_3px_rgba(0,0,0,0.3)] card-hover cursor-pointer"
        :style="{ transitionDelay: `${index * 30}ms` }"
        @click="openEditDialog(project)"
      >
        <div class="flex border-l-[2px] hover:border-l-[3px] rounded-l-lg transition-all duration-150" :style="{ borderLeftColor: project.color }">
          <div class="flex-1 p-4">
            <div class="flex items-start justify-between">
              <div>
                <h3 class="text-[0.8125rem] font-semibold text-text-primary">{{ project.name }}</h3>
                <p class="text-xs text-text-secondary mt-0.5">{{ getClientName(project.client_id) }} · {{ project.budget_amount ? formatCurrency(project.budget_amount) + ' fixed' : formatCurrency(project.hourly_rate) + '/hr' }}</p>
              </div>
              <div class="flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity duration-100">
                <button
                  @click.stop="openEditDialog(project)"
                  class="p-1.5 text-text-tertiary hover:text-text-secondary transition-colors duration-150"
                  title="Edit"
                >
                  <svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
                    <path stroke-linecap="round" stroke-linejoin="round" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
                  </svg>
                </button>
                <button
                  @click.stop="confirmDelete(project)"
                  class="p-1.5 text-text-tertiary hover:text-status-error transition-colors duration-150"
                  title="Delete"
                >
                  <svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
                    <path stroke-linecap="round" stroke-linejoin="round" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
                  </svg>
                </button>
              </div>
            </div>
            <div v-if="project.budget_hours" class="mt-2">
              <div class="flex items-center justify-between mb-1">
                <span class="text-[0.625rem] text-text-tertiary">{{ getBudgetUsed(project).toFixed(0) }}h / {{ project.budget_hours }}h</span>
                <span class="text-[0.625rem]" :class="getBudgetPct(project) > 90 ? 'text-status-error' : getBudgetPct(project) > 75 ? 'text-status-warning' : 'text-text-tertiary'">{{ getBudgetPct(project).toFixed(0) }}%</span>
              </div>
              <div class="w-full bg-bg-elevated rounded-full h-1">
                <div
                  class="h-1 rounded-full progress-bar"
                  :class="getBudgetPct(project) > 90 ? 'bg-status-error' : getBudgetPct(project) > 75 ? 'bg-status-warning' : 'bg-accent'"
                  :style="{ width: Math.min(getBudgetPct(project), 100) + '%' }"
                />
              </div>
            </div>
          </div>
        </div>
      </div>
    </TransitionGroup>

    <!-- Empty State -->
    <div v-else class="flex flex-col items-center justify-center py-16">
      <FolderKanban class="w-12 h-12 text-text-tertiary animate-float" :stroke-width="1.5" />
      <p class="text-sm text-text-secondary mt-4">No projects yet</p>
      <p class="text-xs text-text-tertiary mt-2 max-w-xs text-center">Projects organize your time entries and set billing rates for clients.</p>
      <button
        @click="openCreateDialog"
        class="mt-4 px-4 py-2 bg-accent text-bg-base text-xs font-medium rounded-lg hover:bg-accent-hover transition-colors"
      >
        Create Project
      </button>
    </div>

    <!-- Create/Edit Dialog -->
    <Transition name="modal">
    <div
      v-if="showDialog"
      class="fixed inset-0 bg-black/70 backdrop-blur-[4px] flex items-center justify-center p-4 z-50"
      @click.self="tryCloseDialog"
    >
      <div class="bg-bg-surface border border-border-subtle rounded-lg shadow-[0_1px_3px_rgba(0,0,0,0.3)] w-full max-w-2xl p-6 max-h-[calc(100vh-2rem)] overflow-y-auto">
        <h2 class="text-[1.125rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-4">
          {{ editingProject ? 'Edit Project' : 'Create Project' }}
        </h2>

        <form @submit.prevent="handleSubmit" class="space-y-4">
          <!-- Two-column layout: Identity | Billing -->
          <div class="grid grid-cols-2 gap-6">
            <!-- Left column: Identity -->
            <div class="space-y-4">
              <div>
                <label class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">Name *</label>
                <input
                  v-model="formData.name"
                  type="text"
                  required
                  class="w-full px-3 py-2 bg-bg-inset border border-border-subtle rounded-lg text-[0.8125rem] text-text-primary focus:outline-none focus:border-border-visible"
                  placeholder="Project name"
                />
              </div>

              <div>
                <label class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">Client</label>
                <AppSelect
                  v-model="formData.client_id"
                  :options="clientsStore.clients"
                  label-key="name"
                  value-key="id"
                  placeholder="No client"
                  :placeholder-value="undefined"
                />
              </div>

              <div>
                <label class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">Color</label>
                <AppColorPicker
                  v-model="formData.color"
                  :presets="colorPresets"
                />
              </div>
            </div>

            <!-- Right column: Billing -->
            <div class="space-y-4">
              <div>
                <label class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">Billing Type</label>
                <div class="flex rounded-lg border border-border-subtle overflow-hidden">
                  <button
                    type="button"
                    @click="billingType = 'hourly'"
                    class="flex-1 px-3 py-1.5 text-[0.75rem] font-medium transition-colors duration-150"
                    :class="billingType === 'hourly' ? 'bg-accent text-bg-base' : 'text-text-secondary hover:bg-bg-elevated'"
                  >
                    Hourly
                  </button>
                  <button
                    type="button"
                    @click="billingType = 'fixed'"
                    class="flex-1 px-3 py-1.5 text-[0.75rem] font-medium transition-colors duration-150 border-l border-border-subtle"
                    :class="billingType === 'fixed' ? 'bg-accent text-bg-base' : 'text-text-secondary hover:bg-bg-elevated'"
                  >
                    Fixed Budget
                  </button>
                </div>
              </div>

              <!-- Hourly billing fields -->
              <template v-if="billingType === 'hourly'">
                <div>
                  <label class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">Hourly Rate ({{ getCurrencySymbol() }})</label>
                  <AppNumberInput
                    v-model="formData.hourly_rate"
                    :min="0"
                    :step="1"
                    :precision="2"
                    :prefix="getCurrencySymbol()"
                  />
                </div>
                <div>
                  <label class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">Budget Hours</label>
                  <AppNumberInput
                    :model-value="formData.budget_hours ?? 0"
                    @update:model-value="formData.budget_hours = $event || null"
                    :min="0"
                    :step="1"
                    :precision="0"
                    placeholder="No limit"
                  />
                </div>
              </template>

              <!-- Fixed budget fields -->
              <template v-if="billingType === 'fixed'">
                <div>
                  <label class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">Budget Amount ({{ getCurrencySymbol() }})</label>
                  <AppNumberInput
                    :model-value="formData.budget_amount ?? 0"
                    @update:model-value="formData.budget_amount = $event || null"
                    :min="0"
                    :step="100"
                    :precision="2"
                    :prefix="getCurrencySymbol()"
                  />
                </div>
                <div>
                  <label class="block text-[0.6875rem] text-text-tertiary uppercase tracking-[0.08em] mb-1.5">Budget Hours</label>
                  <AppNumberInput
                    :model-value="formData.budget_hours ?? 0"
                    @update:model-value="formData.budget_hours = $event || null"
                    :min="0"
                    :step="1"
                    :precision="0"
                    placeholder="No limit"
                  />
                </div>
              </template>
            </div>
          </div>

          <!-- Tasks -->
          <div class="border border-border-subtle rounded-lg overflow-hidden">
            <button
              type="button"
              @click="tasksExpanded = !tasksExpanded"
              class="w-full flex items-center justify-between px-3 py-2.5 text-[0.8125rem] text-text-primary hover:bg-bg-elevated transition-colors"
            >
              <span>Tasks ({{ allTasks.length }})</span>
              <ChevronDown
                class="w-4 h-4 text-text-tertiary transition-transform duration-200"
                :class="{ 'rotate-180': tasksExpanded }"
                :stroke-width="1.5"
              />
            </button>
            <div v-if="tasksExpanded" class="border-t border-border-subtle px-3 py-3 space-y-2.5">
              <div v-if="allTasks.length > 0" class="space-y-1.5">
                <div
                  v-for="(task, i) in allTasks"
                  :key="task.id ?? `pending-${i}`"
                  class="flex items-center justify-between gap-2 px-2.5 py-1.5 bg-bg-inset rounded-lg"
                >
                  <span class="text-[0.75rem] text-text-primary truncate flex-1">{{ task.name }}</span>
                  <button
                    type="button"
                    @click="removeTask(task, i)"
                    class="p-1 text-text-tertiary hover:text-status-error transition-colors shrink-0"
                  >
                    <X class="w-3.5 h-3.5" :stroke-width="1.5" />
                  </button>
                </div>
              </div>
              <p v-else class="text-[0.6875rem] text-text-tertiary">No tasks. Add tasks to break down project work.</p>
              <div class="flex items-center gap-2 pt-1">
                <input
                  v-model="newTaskName"
                  type="text"
                  class="flex-1 px-2.5 py-1.5 bg-bg-inset border border-border-subtle rounded-lg text-[0.75rem] text-text-primary placeholder-text-tertiary focus:outline-none focus:border-border-visible"
                  placeholder="New task name..."
                  @keydown.enter.prevent="addTask"
                />
                <button
                  type="button"
                  @click="addTask"
                  :disabled="!newTaskName.trim()"
                  class="px-3 py-1.5 bg-accent text-bg-base text-[0.75rem] font-medium rounded-lg hover:bg-accent-hover transition-colors disabled:opacity-40 disabled:cursor-not-allowed"
                >
                  Add
                </button>
              </div>
            </div>
          </div>

          <!-- Tracked Apps -->
          <div class="border border-border-subtle rounded-lg overflow-hidden">
            <button
              type="button"
              @click="trackedAppsExpanded = !trackedAppsExpanded"
              class="w-full flex items-center justify-between px-3 py-2.5 text-[0.8125rem] text-text-primary hover:bg-bg-elevated transition-colors"
            >
              <span>Tracked Apps ({{ allTrackedApps.length }})</span>
              <ChevronDown
                class="w-4 h-4 text-text-tertiary transition-transform duration-200"
                :class="{ 'rotate-180': trackedAppsExpanded }"
                :stroke-width="1.5"
              />
            </button>
            <div v-if="trackedAppsExpanded" class="border-t border-border-subtle px-3 py-3 space-y-2.5">
              <div v-if="allTrackedApps.length > 0" class="space-y-1.5">
                <div
                  v-for="app in allTrackedApps"
                  :key="app.exe_path || app.exe_name"
                  class="flex items-center justify-between gap-2 px-2.5 py-1.5 bg-bg-inset rounded-lg"
                >
                  <div class="flex items-center gap-2 flex-1 min-w-0">
                    <img
                      v-if="app.icon"
                      :src="app.icon"
                      class="w-4 h-4 shrink-0"
                      alt=""
                    />
                    <div v-else class="w-4 h-4 shrink-0 rounded bg-bg-elevated" />
                    <div class="flex-1 min-w-0">
                      <p class="text-[0.75rem] text-text-primary truncate">{{ app.display_name || app.exe_name }}</p>
                      <p class="text-[0.6875rem] text-text-tertiary truncate">{{ app.exe_name }}</p>
                    </div>
                  </div>
                  <button
                    type="button"
                    @click="removeTrackedApp(app)"
                    class="p-1 text-text-tertiary hover:text-status-error transition-colors shrink-0"
                  >
                    <X class="w-3.5 h-3.5" :stroke-width="1.5" />
                  </button>
                </div>
              </div>
              <p v-else class="text-[0.6875rem] text-text-tertiary">No tracked apps. Timer will run without app visibility checks.</p>
              <div class="flex items-center gap-2 pt-1">
                <RunningAppsPicker :exclude-paths="excludedPaths" @select="addTrackedAppFromPicker" />
                <button
                  type="button"
                  @click="browseForApp"
                  class="flex items-center gap-1.5 px-2.5 py-1.5 border border-border-subtle text-text-secondary text-[0.75rem] rounded-lg hover:bg-bg-elevated hover:text-text-primary transition-colors"
                >
                  <FolderOpen class="w-3.5 h-3.5" :stroke-width="1.5" />
                  Browse...
                </button>
              </div>
            </div>
          </div>

          <!-- Buttons -->
          <div class="flex justify-end gap-3 pt-4">
            <button
              type="button"
              @click="closeDialog"
              class="px-4 py-2 border border-border-subtle text-text-secondary rounded-lg hover:bg-bg-elevated transition-colors duration-150"
            >
              Cancel
            </button>
            <button
              type="submit"
              class="px-4 py-2 bg-accent text-bg-base font-medium rounded-lg hover:bg-accent-hover transition-colors duration-150"
            >
              {{ editingProject ? 'Update' : 'Create' }}
            </button>
          </div>
        </form>
      </div>
    </div>
    </Transition>

    <!-- Delete Confirmation Dialog -->
    <Transition name="modal">
    <div
      v-if="showDeleteDialog"
      class="fixed inset-0 bg-black/70 backdrop-blur-[4px] flex items-center justify-center p-4 z-50"
      @click.self="cancelDelete"
    >
      <div class="bg-bg-surface border border-border-subtle rounded-lg shadow-[0_1px_3px_rgba(0,0,0,0.3)] w-full max-w-sm p-6">
        <h2 class="text-[1.125rem] font-semibold font-[family-name:var(--font-heading)] text-text-primary mb-2">Delete Project</h2>
        <p class="text-[0.75rem] text-text-secondary mb-6">
          Are you sure you want to delete "{{ projectToDelete?.name }}"? This action cannot be undone.
        </p>
        <div class="flex justify-end gap-3">
          <button
            @click="cancelDelete"
            class="px-4 py-2 border border-border-subtle text-text-secondary rounded-lg hover:bg-bg-elevated transition-colors duration-150"
          >
            Cancel
          </button>
          <button
            @click="handleDelete"
            class="px-4 py-2 border border-status-error text-status-error font-medium rounded-lg hover:bg-status-error/10 transition-colors duration-150"
          >
            Delete
          </button>
        </div>
      </div>
    </div>
    </Transition>

    <AppDiscardDialog :show="showDiscardDialog" @cancel="cancelDiscard" @discard="confirmDiscard" />
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, onMounted } from 'vue'
import { FolderKanban, ChevronDown, X, FolderOpen } from 'lucide-vue-next'
import { invoke } from '@tauri-apps/api/core'
import { open as openFileDialog } from '@tauri-apps/plugin-dialog'
import AppNumberInput from '../components/AppNumberInput.vue'
import AppSelect from '../components/AppSelect.vue'
import AppDiscardDialog from '../components/AppDiscardDialog.vue'
import RunningAppsPicker from '../components/RunningAppsPicker.vue'
import AppColorPicker from '../components/AppColorPicker.vue'
import { useProjectsStore, type Project, type Task } from '../stores/projects'
import { useClientsStore } from '../stores/clients'
import { useSettingsStore } from '../stores/settings'
import { formatCurrency, getCurrencySymbol } from '../utils/locale'
import { useFormGuard } from '../utils/formGuard'

interface TrackedApp {
  id?: number
  project_id: number
  exe_name: string
  exe_path?: string
  display_name?: string
  icon?: string
}


const colorPresets = ['#D97706', '#3B82F6', '#8B5CF6', '#EC4899', '#10B981', '#EF4444', '#06B6D4', '#6B7280']

const projectsStore = useProjectsStore()
const clientsStore = useClientsStore()
const settingsStore = useSettingsStore()

const { showDiscardDialog, snapshot: snapshotForm, tryClose: tryCloseForm, confirmDiscard, cancelDiscard } = useFormGuard()

function getFormData() {
  return { name: formData.name, client_id: formData.client_id, hourly_rate: formData.hourly_rate, color: formData.color, archived: formData.archived, budget_hours: formData.budget_hours, budget_amount: formData.budget_amount }
}

function tryCloseDialog() {
  tryCloseForm(getFormData(), closeDialog)
}

// Dialog state
const showDialog = ref(false)
const showDeleteDialog = ref(false)
const editingProject = ref<Project | null>(null)
const projectToDelete = ref<Project | null>(null)

// Billing type
const billingType = ref<'hourly' | 'fixed'>('hourly')

// Task state
const projectTasksList = ref<Task[]>([])
const pendingNewTasks = ref<string[]>([])
const pendingRemoveTaskIds = ref<number[]>([])
const newTaskName = ref('')
const tasksExpanded = ref(false)

const allTasks = computed(() => {
  const existing = projectTasksList.value.filter(t => !pendingRemoveTaskIds.value.includes(t.id!))
  const pending = pendingNewTasks.value.map(name => ({ name, project_id: 0 } as Task))
  return [...existing, ...pending]
})

async function loadProjectTasks(projectId: number) {
  projectTasksList.value = await projectsStore.fetchTasks(projectId)
}

function addTask() {
  const name = newTaskName.value.trim()
  if (!name) return
  pendingNewTasks.value.push(name)
  newTaskName.value = ''
}

function removeTask(task: Task, index: number) {
  if (task.id) {
    pendingRemoveTaskIds.value.push(task.id)
  } else {
    // It's a pending task - index offset by existing tasks count
    const existingCount = projectTasksList.value.filter(t => !pendingRemoveTaskIds.value.includes(t.id!)).length
    pendingNewTasks.value.splice(index - existingCount, 1)
  }
}

async function saveTasks(projectId: number) {
  for (const id of pendingRemoveTaskIds.value) {
    await projectsStore.deleteTask(id)
  }
  for (const name of pendingNewTasks.value) {
    await projectsStore.createTask({ project_id: projectId, name })
  }
  pendingNewTasks.value = []
  pendingRemoveTaskIds.value = []
}

// Tracked apps state
const trackedApps = ref<TrackedApp[]>([])
const pendingAddApps = ref<TrackedApp[]>([])
const pendingRemoveIds = ref<number[]>([])
const trackedAppsExpanded = ref(false)

const allTrackedApps = computed(() => {
  return [
    ...trackedApps.value.filter(a => !pendingRemoveIds.value.includes(a.id!)),
    ...pendingAddApps.value,
  ]
})

const excludedPaths = computed(() =>
  allTrackedApps.value.map(a => (a.exe_path || '').toLowerCase())
)

async function loadTrackedApps(projectId: number) {
  try {
    trackedApps.value = await invoke<TrackedApp[]>('get_tracked_apps', { projectId })
  } catch (e) {
    console.error('Failed to load tracked apps:', e)
    trackedApps.value = []
  }
}

function addTrackedAppFromPicker(app: { exe_name: string; exe_path: string; display_name: string; icon?: string | null }) {
  if (allTrackedApps.value.some(a => (a.exe_path || '').toLowerCase() === app.exe_path.toLowerCase())) return
  pendingAddApps.value.push({
    project_id: 0,
    exe_name: app.exe_name,
    exe_path: app.exe_path,
    display_name: app.display_name,
    icon: app.icon || undefined,
  })
}

async function browseForApp() {
  const result = await openFileDialog({
    multiple: false,
    filters: [{ name: 'Executables', extensions: ['exe', '*'] }],
  })
  if (!result) return
  const filePath = typeof result === 'string' ? result : String(result)
  const normalized = filePath.replace(/\//g, '\\')
  const exeName = normalized.split('\\').pop() || normalized
  const displayName = exeName.replace(/\.exe$/i, '')
  if (allTrackedApps.value.some(a => (a.exe_path || '').toLowerCase() === normalized.toLowerCase())) return
  pendingAddApps.value.push({
    project_id: 0,
    exe_name: exeName,
    exe_path: normalized,
    display_name: displayName,
  })
}

function removeTrackedApp(app: TrackedApp) {
  if (app.id) {
    pendingRemoveIds.value.push(app.id)
  } else {
    pendingAddApps.value = pendingAddApps.value.filter(a => a !== app)
  }
}

async function saveTrackedApps(projectId: number) {
  for (const id of pendingRemoveIds.value) {
    await invoke('remove_tracked_app', { id })
  }
  for (const app of pendingAddApps.value) {
    await invoke('add_tracked_app', { app: { ...app, project_id: projectId } })
  }
  pendingAddApps.value = []
  pendingRemoveIds.value = []
}

// Form data
const formData = reactive<Project>({
  name: '',
  client_id: undefined,
  hourly_rate: 0,
  color: '#D97706',
  archived: false,
  budget_hours: null,
  budget_amount: null
})

// Budget status
const budgetStatus = ref<Record<number, { used_hours: number }>>({})

async function loadBudgetStatus() {
  for (const project of projectsStore.projects) {
    if (project.id && project.budget_hours) {
      try {
        const status = await invoke<{ used_hours: number; used_amount: number }>('get_project_budget_status', { projectId: project.id })
        budgetStatus.value[project.id] = status
      } catch (e) {
        // ignore
      }
    }
  }
}

function getBudgetUsed(project: any): number {
  return budgetStatus.value[project.id]?.used_hours || 0
}

function getBudgetPct(project: any): number {
  if (!project.budget_hours) return 0
  const used = getBudgetUsed(project)
  return (used / project.budget_hours) * 100
}

// Get client name by ID
function getClientName(clientId?: number): string {
  if (!clientId) return 'No client'
  const client = clientsStore.clients.find(c => c.id === clientId)
  return client?.name || 'Unknown client'
}

// Open create dialog
function openCreateDialog() {
  editingProject.value = null
  formData.name = ''
  formData.client_id = undefined
  formData.hourly_rate = parseFloat(settingsStore.settings.hourly_rate) || 0
  formData.color = '#F59E0B'
  formData.archived = false
  formData.budget_hours = null
  formData.budget_amount = null
  billingType.value = 'hourly'
  trackedApps.value = []
  pendingAddApps.value = []
  pendingRemoveIds.value = []
  trackedAppsExpanded.value = false
  projectTasksList.value = []
  pendingNewTasks.value = []
  pendingRemoveTaskIds.value = []
  newTaskName.value = ''
  tasksExpanded.value = false
  snapshotForm(getFormData())
  showDialog.value = true
}

// Open edit dialog
async function openEditDialog(project: Project) {
  editingProject.value = project
  formData.id = project.id
  formData.name = project.name
  formData.client_id = project.client_id
  formData.hourly_rate = project.hourly_rate
  formData.color = project.color
  formData.archived = project.archived
  formData.budget_hours = project.budget_hours ?? null
  formData.budget_amount = project.budget_amount ?? null
  // Infer billing type from existing data
  billingType.value = (project.budget_amount && project.budget_amount > 0) ? 'fixed' : 'hourly'
  pendingAddApps.value = []
  pendingRemoveIds.value = []
  trackedAppsExpanded.value = false
  projectTasksList.value = []
  pendingNewTasks.value = []
  pendingRemoveTaskIds.value = []
  newTaskName.value = ''
  tasksExpanded.value = false
  if (project.id) {
    await loadTrackedApps(project.id)
    await loadProjectTasks(project.id)
    if (trackedApps.value.length > 0) trackedAppsExpanded.value = true
    if (projectTasksList.value.length > 0) tasksExpanded.value = true
  } else {
    trackedApps.value = []
  }
  snapshotForm(getFormData())
  showDialog.value = true
}

// Close dialog
function closeDialog() {
  showDialog.value = false
  editingProject.value = null
}

// Handle form submit
async function handleSubmit() {
  // Clear irrelevant billing fields based on type
  if (billingType.value === 'hourly') {
    formData.budget_amount = null
  } else {
    formData.hourly_rate = 0
  }

  let projectId: number | undefined
  if (editingProject.value) {
    await projectsStore.updateProject({ ...formData })
    projectId = formData.id
  } else {
    projectId = (await projectsStore.createProject({ ...formData })) ?? undefined
  }
  if (projectId) {
    await saveTrackedApps(projectId)
    await saveTasks(projectId)
  }
  closeDialog()
}

// Confirm delete
function confirmDelete(project: Project) {
  projectToDelete.value = project
  showDeleteDialog.value = true
}

// Cancel delete
function cancelDelete() {
  showDeleteDialog.value = false
  projectToDelete.value = null
}

// Handle delete
async function handleDelete() {
  if (projectToDelete.value?.id) {
    await projectsStore.deleteProject(projectToDelete.value.id)
  }
  cancelDelete()
}

// Load data on mount
onMounted(async () => {
  await Promise.all([
    projectsStore.fetchProjects(),
    clientsStore.fetchClients(),
    settingsStore.fetchSettings()
  ])
  await loadBudgetStatus()
})
</script>
