<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Button } from '@/components/ui/button'
import { Skeleton } from '@/components/ui/skeleton'
import { Switch } from '@/components/ui/switch'
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table'
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import { MoreHorizontal, Plus, Pencil, Trash2, GripVertical, Power } from 'lucide-vue-next'
import { api } from '@/api/client'
import type { Settings, IpProvider } from '@/api/types'
import { toast } from 'vue-sonner'
import AddIpProviderDialog from '@/components/AddIpProviderDialog.vue'
import DeleteConfirmDialog from '@/components/DeleteConfirmDialog.vue'
import draggable from 'vuedraggable'

const loading = ref(true)
const saving = ref(false)
const cronSchedule = ref('')

const providers = ref<IpProvider[]>([])
const providersLoading = ref(true)
const reordering = ref(false)

const dialogOpen = ref(false)
const editingProvider = ref<IpProvider | null>(null)

const deleteOpen = ref(false)
const deletingProvider = ref<IpProvider | null>(null)

onMounted(async () => {
  try {
    const [settings, providersData] = await Promise.all([
      api.get<Settings>('/api/settings'),
      api.get<IpProvider[]>('/api/ip-providers'),
    ])
    cronSchedule.value = settings.cron_schedule
    providers.value = providersData ?? []
  } catch (err) {
    toast.error(err instanceof Error ? err.message : 'Failed to load settings')
  } finally {
    loading.value = false
    providersLoading.value = false
  }
})

async function loadProviders() {
  try {
    providers.value = await api.get<IpProvider[]>('/api/ip-providers')
  } catch (err) {
    toast.error(err instanceof Error ? err.message : 'Failed to load IP providers')
  }
}

async function save() {
  saving.value = true
  try {
    const settings = await api.put<Settings>('/api/settings', {
      cron_schedule: cronSchedule.value,
    })
    cronSchedule.value = settings.cron_schedule
    toast.success('Settings saved')
  } catch (err) {
    toast.error(err instanceof Error ? err.message : 'Failed to save settings')
  } finally {
    saving.value = false
  }
}

function openAdd() {
  editingProvider.value = null
  dialogOpen.value = true
}

function openEdit(provider: IpProvider) {
  editingProvider.value = provider
  dialogOpen.value = true
}

function openDelete(provider: IpProvider) {
  deletingProvider.value = provider
  deleteOpen.value = true
}

async function confirmDelete() {
  if (!deletingProvider.value) return
  try {
    await api.delete(`/api/ip-providers/${deletingProvider.value.id}`)
    toast.success('IP provider deleted')
    deleteOpen.value = false
    await loadProviders()
  } catch (err) {
    toast.error(err instanceof Error ? err.message : 'Failed to delete IP provider')
  }
}

async function toggleEnabled(provider: IpProvider) {
  try {
    const newEnabled = provider.enabled === 1 ? 0 : 1
    await api.put(`/api/ip-providers/${provider.id}`, {
      url: provider.url,
      name: provider.name,
      enabled: newEnabled,
      priority: provider.priority,
    })
    provider.enabled = newEnabled
    toast.success(newEnabled === 1 ? 'Provider enabled' : 'Provider disabled')
  } catch (err) {
    toast.error(err instanceof Error ? err.message : 'Failed to update provider')
  }
}

function providerDisplayName(p: IpProvider) {
  return p.name?.trim() || p.url
}

async function onReorder() {
  reordering.value = true
  try {
    const ids = providers.value.map((p) => p.id)
    await api.put('/api/ip-providers/reorder', { ids })
    providers.value.forEach((p, i) => {
      p.priority = i
    })
  } catch (err) {
    toast.error(err instanceof Error ? err.message : 'Failed to reorder IP providers')
    await loadProviders()
  } finally {
    reordering.value = false
  }
}
</script>

<template>
  <div class="space-y-6">
    <div>
      <h1 class="text-2xl font-bold tracking-tight">Settings</h1>
      <p class="text-muted-foreground">Configure your DDNS updater</p>
    </div>

    <Card>
      <CardHeader>
        <CardTitle>Cron Schedule</CardTitle>
        <CardDescription>
          How often the DDNS updater checks for IP changes. Uses
          <a
            href="https://pkg.go.dev/github.com/robfig/cron/v3#hdr-Predefined_schedules"
            target="_blank"
            class="underline text-orange-500"
          >robfig/cron</a>
          syntax, e.g. <code class="text-xs bg-muted px-1 py-0.5 rounded">@every 1m</code>,
          <code class="text-xs bg-muted px-1 py-0.5 rounded">@every 5m</code>,
          <code class="text-xs bg-muted px-1 py-0.5 rounded">*/5 * * * *</code>.
        </CardDescription>
      </CardHeader>
      <CardContent>
        <template v-if="loading">
          <Skeleton class="h-9 w-full" />
        </template>
        <form v-else class="flex flex-col sm:flex-row sm:items-end gap-3" @submit.prevent="save">
          <div class="flex-1 space-y-2">
            <Label for="cron-schedule">Schedule</Label>
            <Input
              id="cron-schedule"
              v-model="cronSchedule"
              placeholder="@every 1m"
              required
            />
          </div>
          <Button
            type="submit"
            class="w-full sm:w-auto bg-orange-500 hover:bg-orange-500/90 text-white"
            :disabled="saving"
          >
            {{ saving ? 'Saving...' : 'Save' }}
          </Button>
        </form>
      </CardContent>
    </Card>

    <Card>
      <CardHeader>
        <div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3">
          <div>
            <CardTitle>IP Providers</CardTitle>
            <CardDescription>
              Services used to detect your public IP. The first responding provider is used; disable
              or reorder to change priority.
            </CardDescription>
          </div>
          <Button class="shrink-0 self-start sm:self-auto bg-orange-500 hover:bg-orange-500/90 text-white" @click="openAdd">
            <Plus class="mr-2 h-4 w-4" />
            Add Provider
          </Button>
        </div>
      </CardHeader>
      <CardContent>
        <!-- Desktop table -->
        <div class="hidden sm:block rounded-md border">
          <Table>
            <TableHeader>
              <TableRow>
                <TableHead class="w-8" aria-label="Reorder" />
                <TableHead>Name</TableHead>
                <TableHead>URL</TableHead>
                <TableHead class="w-24">Enabled</TableHead>
                <TableHead class="w-12" />
              </TableRow>
            </TableHeader>
            <template v-if="providersLoading">
              <TableBody>
                <TableRow v-for="i in 3" :key="i">
                  <TableCell v-for="j in 5" :key="j">
                    <Skeleton class="h-5 w-full" />
                  </TableCell>
                </TableRow>
              </TableBody>
            </template>
            <template v-else-if="providers.length === 0">
              <TableBody>
                <TableRow>
                  <TableCell colspan="5" class="text-center text-muted-foreground py-8">
                    No IP providers configured. Add one or use the built-in defaults.
                  </TableCell>
                </TableRow>
              </TableBody>
            </template>
            <draggable
              v-else
              v-model="providers"
              tag="tbody"
              item-key="id"
              handle=".drag-handle"
              :disabled="reordering"
              @end="onReorder"
            >
              <template #item="{ element: provider }">
                <tr
                  :key="provider.id"
                  data-slot="table-row"
                  class="hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors"
                >
                  <td
                    data-slot="table-cell"
                    class="w-8 px-2 p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]"
                  >
                    <div class="flex items-center justify-center h-full">
                      <GripVertical
                        class="drag-handle h-4 w-4 text-muted-foreground/70 hover:text-foreground cursor-grab active:cursor-grabbing transition-colors rounded p-1 hover:bg-accent/50"
                      />
                    </div>
                  </td>
                  <td
                    data-slot="table-cell"
                    class="p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]"
                  >
                    <span v-if="provider.name?.trim()" class="font-medium" :title="provider.name">
                      {{ provider.name.trim() }}
                    </span>
                    <span v-else class="text-muted-foreground">—</span>
                  </td>
                  <td
                    data-slot="table-cell"
                    class="p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]"
                  >
                    <span class="text-sm text-muted-foreground truncate font-mono block max-w-md" :title="provider.url">
                      {{ provider.url }}
                    </span>
                  </td>
                  <td
                    data-slot="table-cell"
                    class="w-24 p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]"
                  >
                    <Switch
                      :model-value="provider.enabled === 1"
                      @update:model-value="toggleEnabled(provider)"
                    />
                  </td>
                  <td
                    data-slot="table-cell"
                    class="w-12 p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]"
                  >
                    <DropdownMenu>
                      <DropdownMenuTrigger asChild>
                        <Button variant="ghost" size="icon" class="h-8 w-8">
                          <MoreHorizontal class="h-4 w-4" />
                        </Button>
                      </DropdownMenuTrigger>
                      <DropdownMenuContent align="end">
                        <DropdownMenuItem @click="openEdit(provider)">
                          <Pencil class="mr-2 h-4 w-4" />
                          Edit
                        </DropdownMenuItem>
                        <DropdownMenuItem class="text-destructive" @click="openDelete(provider)">
                          <Trash2 class="mr-2 h-4 w-4" />
                          Delete
                        </DropdownMenuItem>
                      </DropdownMenuContent>
                    </DropdownMenu>
                  </td>
                </tr>
              </template>
            </draggable>
          </Table>
        </div>
        <!-- Mobile cards -->
        <div class="sm:hidden space-y-3">
          <template v-if="providersLoading">
            <div v-for="i in 3" :key="i" class="rounded-lg border p-4">
              <Skeleton class="h-20 w-full" />
            </div>
          </template>
          <template v-else-if="providers.length === 0">
            <div class="rounded-lg border p-6 text-center text-sm text-muted-foreground">
              No IP providers configured. Add one or use the built-in defaults.
            </div>
          </template>
          <draggable
            v-else
            v-model="providers"
            item-key="id"
            handle=".drag-handle"
            :disabled="reordering"
            @end="onReorder"
            class="space-y-3"
          >
            <template #item="{ element: provider }">
              <div
                :key="provider.id"
                class="drag-handle rounded-lg border p-4 relative cursor-grab active:cursor-grabbing"
              >
                <div
                  :class="[
                    'absolute top-2 left-2 w-2 h-2 rounded-full',
                    provider.enabled === 1 ? 'bg-green-500' : 'bg-muted-foreground'
                  ]"
                  :title="provider.enabled === 1 ? 'Enabled' : 'Disabled'"
                />
                <div class="flex items-start gap-3">
                  <div class="min-w-0 flex-1 space-y-1">
                    <p v-if="provider.name?.trim()" class="font-semibold truncate">
                      {{ provider.name.trim() }}
                    </p>
                    <p v-else class="font-semibold text-muted-foreground">—</p>
                    <p class="text-xs font-mono text-muted-foreground truncate" :title="provider.url">
                      {{ provider.url }}
                    </p>
                  </div>
                  <DropdownMenu>
                    <DropdownMenuTrigger asChild>
                      <Button variant="ghost" size="icon" class="h-8 w-8 shrink-0">
                        <MoreHorizontal class="h-4 w-4" />
                      </Button>
                    </DropdownMenuTrigger>
                    <DropdownMenuContent align="end">
                      <DropdownMenuItem @click="toggleEnabled(provider)">
                        <Power
                          :class="[
                            'mr-2 h-4 w-4',
                            provider.enabled === 1 ? 'text-destructive' : 'text-green-500'
                          ]"
                        />
                        {{ provider.enabled === 1 ? 'Disable' : 'Enable' }}
                      </DropdownMenuItem>
                      <DropdownMenuItem @click="openEdit(provider)">
                        <Pencil class="mr-2 h-4 w-4" />
                        Edit
                      </DropdownMenuItem>
                      <DropdownMenuItem class="text-destructive" @click="openDelete(provider)">
                        <Trash2 class="mr-2 h-4 w-4" />
                        Delete
                      </DropdownMenuItem>
                    </DropdownMenuContent>
                  </DropdownMenu>
                </div>
              </div>
            </template>
          </draggable>
        </div>
      </CardContent>
    </Card>

    <AddIpProviderDialog
      v-model:open="dialogOpen"
      :provider="editingProvider"
      :next-priority="providers.length"
      @saved="loadProviders"
    />

    <DeleteConfirmDialog
      v-model:open="deleteOpen"
      title="Delete IP provider?"
      :description="
        deletingProvider
          ? `Remove '${providerDisplayName(deletingProvider)}' from the list?`
          : 'This action cannot be undone.'
      "
      @confirm="confirmDelete"
    />
  </div>
</template>
