<script setup lang="ts">
import type { AdminTenant, AdminUser } from "~/composables/useAdmin"

const auth = useAuthStore()
const route = useRoute()
const router = useRouter()
const toast = useToast()
const admin = useAdmin()

const tenantId = Number(route.params.id)
const loading = ref(true)
const saving = ref(false)
const exportingTenant = ref(false)
const importingTenant = ref(false)
const tenantExportProgress = ref<null | {
  status: string
  filesDone: number
  filesTotal: number
  filename: string
}>(null)
const tenantImportProgress = ref<null | {
  status: string
  filesDone: number
  filesTotal: number
  filename: string
}>(null)
const creatingUser = ref(false)
const createUserModalOpen = ref(false)
const createdUserPassword = ref("")
const importFileInput = ref<HTMLInputElement | null>(null)
const lastImportResult = ref<null | {
  tenantId: number
  tableCount: number
  rowCount: number
  restoredFiles: number
  skippedFiles: number
}>(null)
const lockedOptions = [
  { label: "Aktiv", value: null },
  { label: "Tenant-Wartung", value: "maintenance_tenant" },
  { label: "Globale Wartung", value: "maintenance" },
  { label: "Allgemeine Sperre", value: "general" },
  { label: "Kein Abonnement", value: "no_subscription" },
]

const tenantForm = ref<AdminTenant | null>(null)
const assignedUsers = ref<AdminUser[]>([])
const createUserForm = ref({
  email: "",
  password: "",
  first_name: "",
  last_name: "",
  is_admin: false,
  multiTenant: false,
})

const fetchTenant = async () => {
  loading.value = true

  try {
    const overview = await admin.getOverview()
    const tenant = overview.tenants.find((entry) => entry.id === tenantId)

    if (!tenant) {
      toast.add({ title: "Tenant nicht gefunden", color: "red" })
      await router.push("/administration/tenants")
      return
    }

    tenantForm.value = { ...tenant }
    assignedUsers.value = overview.users.filter((user) => user.tenant_ids.includes(tenantId))
  } catch (err: any) {
    console.error("[administration/tenants/show]", err)
    toast.add({
      title: "Tenant konnte nicht geladen werden",
      description: err?.data?.error || err?.message || "Unbekannter Fehler",
      color: "red",
    })
  } finally {
    loading.value = false
  }
}

const saveTenant = async () => {
  if (!tenantForm.value || saving.value) return

  saving.value = true

  try {
    await admin.updateTenant(tenantForm.value.id, {
      name: tenantForm.value.name,
      short: tenantForm.value.short,
      locked: tenantForm.value.locked || null,
    })

    await fetchTenant()
    await auth.fetchMe()

    toast.add({ title: "Tenant gespeichert", color: "green" })
  } catch (err: any) {
    console.error("[administration/tenants/save]", err)
    toast.add({
      title: "Tenant konnte nicht gespeichert werden",
      description: err?.data?.error || err?.message || "Unbekannter Fehler",
      color: "red",
    })
  } finally {
    saving.value = false
  }
}

const downloadTenantExport = async () => {
  if (!tenantForm.value || exportingTenant.value) return

  exportingTenant.value = true
  tenantExportProgress.value = null

  try {
    const started = await admin.startTenantExport(tenantForm.value.id)
    let job = started

    tenantExportProgress.value = {
      status: job.status,
      filesDone: job.filesDone || 0,
      filesTotal: job.filesTotal || 0,
      filename: job.filename,
    }

    while (!["ready", "failed"].includes(job.status)) {
      await new Promise((resolve) => setTimeout(resolve, 1500))
      job = await admin.getTenantExport(started.exportId)
      tenantExportProgress.value = {
        status: job.status,
        filesDone: job.filesDone || 0,
        filesTotal: job.filesTotal || 0,
        filename: job.filename,
      }
    }

    if (job.status === "failed") {
      throw new Error(job.error || "Export konnte nicht erstellt werden.")
    }

    const blob = await admin.downloadTenantExport(started.exportId)
    const objectUrl = URL.createObjectURL(blob)
    const link = document.createElement("a")

    link.href = objectUrl
    link.download = job.filename || `fedeo-tenant-${tenantForm.value.id}.fedeo-export.zip`
    document.body.appendChild(link)
    link.click()
    link.remove()
    URL.revokeObjectURL(objectUrl)

    toast.add({ title: "Mandantenexport erstellt", description: job.filename, color: "green" })
  } catch (err: any) {
    console.error("[administration/tenants/export]", err)
    toast.add({
      title: "Mandant konnte nicht exportiert werden",
      description: err?.data?.error || err?.message || "Unbekannter Fehler",
      color: "red",
    })
  } finally {
    exportingTenant.value = false
  }
}

const openImportFileDialog = () => {
  importFileInput.value?.click()
}

const importTenantExport = async (event: Event) => {
  const input = event.target as HTMLInputElement
  const file = input.files?.[0]
  if (!file || importingTenant.value) return

  importingTenant.value = true
  tenantImportProgress.value = null
  lastImportResult.value = null

  try {
    const targetTenantId = tenantForm.value?.id || tenantId
    const isZipExport = file.name.endsWith(".zip") || file.name.endsWith(".fedeo-export.zip") || file.type === "application/zip"
    let result

    if (isZipExport) {
      const formData = new FormData()
      formData.append("file", file)
      formData.append("targetTenantId", String(targetTenantId))
      result = await admin.importTenant(formData)
    } else {
      result = await admin.importTenant({
        exportData: JSON.parse(await file.text()),
        targetTenantId,
      })
    }

    const importJobId = result.importId || result.exportId
    if (importJobId) {
      let job = result

      tenantImportProgress.value = {
        status: job.status,
        filesDone: job.filesDone || 0,
        filesTotal: job.filesTotal || 0,
        filename: job.filename || file.name,
      }

      while (!["ready", "failed"].includes(job.status)) {
        await new Promise((resolve) => setTimeout(resolve, 1500))
        job = await admin.getTenantExport(importJobId)
        tenantImportProgress.value = {
          status: job.status,
          filesDone: job.filesDone || 0,
          filesTotal: job.filesTotal || 0,
          filename: job.filename || file.name,
        }
      }

      if (job.status === "failed") {
        throw new Error(job.error || "Import konnte nicht abgeschlossen werden.")
      }

      await fetchTenant()
      await auth.fetchMe()
      await auth.switchTenant(String(job.tenantId || targetTenantId))

      toast.add({
        title: "Mandantenimport abgeschlossen",
        description: job.filename || file.name,
        color: "green",
      })
      return
    }

    const rowCount = (result.tables || []).reduce((sum, table) => sum + table.rows, 0)

    lastImportResult.value = {
      tenantId: result.tenantId,
      tableCount: result.tables?.length || 0,
      rowCount,
      restoredFiles: result.files?.restored || 0,
      skippedFiles: result.files?.skipped || 0,
    }

    await fetchTenant()
    await auth.fetchMe()
    await auth.switchTenant(String(result.tenantId))

    toast.add({
      title: "Mandantenimport abgeschlossen",
      description: `${rowCount} Datensätze und ${lastImportResult.value.restoredFiles} Dateien verarbeitet.`,
      color: "green",
    })
  } catch (err: any) {
    console.error("[administration/tenants/import]", err)
    toast.add({
      title: "Mandant konnte nicht importiert werden",
      description: err?.data?.error || err?.message || "Unbekannter Fehler",
      color: "red",
    })
  } finally {
    importingTenant.value = false
    input.value = ""
  }
}

const createTenantUser = async () => {
  if (!tenantForm.value || creatingUser.value) return

  creatingUser.value = true

  try {
    const response = await admin.createUser(createUserForm.value)
    const createdUserId = response?.user?.id

    if (!createdUserId) {
      throw new Error("Benutzer konnte nach dem Anlegen nicht zugeordnet werden.")
    }

    await admin.updateUserAccess(createdUserId, {
      tenant_ids: [tenantForm.value.id],
      role_assignments: [],
      profile_defaults: {
        first_name: createUserForm.value.first_name,
        last_name: createUserForm.value.last_name,
      },
      profile_assignments: [
        {
          tenant_id: tenantForm.value.id,
          profile_id: null,
        },
      ],
    })

    createdUserPassword.value = response.initialPassword || ""
    createUserModalOpen.value = false
    createUserForm.value = {
      email: "",
      password: "",
      first_name: "",
      last_name: "",
      is_admin: false,
      multiTenant: false,
    }

    await fetchTenant()

    toast.add({
      title: "Benutzer angelegt",
      description: "Der Benutzer wurde direkt diesem Tenant zugeordnet und das Profil wurde erstellt.",
      color: "green",
    })
  } catch (err: any) {
    console.error("[administration/tenants/create-user]", err)
    toast.add({
      title: "Benutzer konnte nicht angelegt werden",
      description: err?.data?.error || err?.message || "Unbekannter Fehler",
      color: "red",
    })
  } finally {
    creatingUser.value = false
  }
}

onMounted(async () => {
  if (!auth.user?.is_admin) {
    await router.push("/")
    return
  }

  await fetchTenant()
})
</script>

<template>
  <UDashboardNavbar title="Administration: Tenants">
    <template #left>
      <UButton icon="i-heroicons-chevron-left" variant="outline" @click="router.push('/administration/tenants')">
        Tenants
      </UButton>
    </template>
    <template #right>
      <UButton icon="i-heroicons-user-plus" variant="soft" @click="createUserModalOpen = true">
        Benutzer anlegen
      </UButton>
      <UButton color="primary" :loading="saving" @click="saveTenant">
        Speichern
      </UButton>
    </template>
  </UDashboardNavbar>

  <UDashboardPanelContent>
    <UCard v-if="!loading && tenantForm">
      <div class="flex items-start justify-between gap-4 mb-6">
        <div>
          <h2 class="text-xl font-semibold">{{ tenantForm.name }}</h2>
          <p class="text-sm text-gray-500">Tenant-ID {{ tenantForm.id }}</p>
        </div>
      </div>

      <USeparator label="Tenant" />

      <UForm :state="tenantForm" class="grid grid-cols-1 md:grid-cols-2 gap-6 mt-4">
        <UFormField label="Name">
          <UInput v-model="tenantForm.name" />
        </UFormField>

        <UFormField label="Kürzel">
          <UInput v-model="tenantForm.short" />
        </UFormField>

        <UFormField label="Locked Mode">
          <USelectMenu
            v-model="tenantForm.locked"
            :items="lockedOptions"
            value-key="value"
            label-key="label"
          />
        </UFormField>
      </UForm>

      <UAlert
        v-if="tenantForm.lockedByExportJobId"
        class="mt-4"
        title="Automatische Sperre aktiv"
        :description="`Dieser Tenant wird gerade durch Export/Import ${tenantForm.lockedByExportJobId} pausiert.`"
        color="warning"
        variant="soft"
      />
    </UCard>

    <UCard v-if="!loading && tenantForm" class="mt-3">
      <USeparator label="Backup und Umzug" />

      <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mt-4">
        <div class="border border-gray-200 dark:border-gray-800 rounded-lg p-4">
          <div class="font-medium">Full Export</div>
          <p class="text-sm text-gray-500 mt-1">
            Erstellt ein portables ZIP-Archiv mit Mandantendaten, Benutzerzuordnungen, Rollen, Profilen und Dateien.
          </p>
          <div v-if="tenantExportProgress" class="mt-4 space-y-2">
            <UProgress
              :model-value="tenantExportProgress.filesTotal ? Math.round((tenantExportProgress.filesDone / tenantExportProgress.filesTotal) * 100) : undefined"
            />
            <p class="text-xs text-gray-500">
              {{ tenantExportProgress.status === 'ready' ? 'Download wird vorbereitet' : 'Export wird erstellt' }}
              <span v-if="tenantExportProgress.filesTotal">
                · {{ tenantExportProgress.filesDone }} / {{ tenantExportProgress.filesTotal }} Dateien
              </span>
            </p>
          </div>
          <UButton
            class="mt-4"
            icon="i-heroicons-arrow-down-tray"
            :loading="exportingTenant"
            @click="downloadTenantExport"
          >
            Export herunterladen
          </UButton>
        </div>

        <div class="border border-gray-200 dark:border-gray-800 rounded-lg p-4">
          <div class="font-medium">Import</div>
          <p class="text-sm text-gray-500 mt-1">
            Spielt einen FEDEO-Mandantenexport auf diesem Server ein. Bestehende Datensätze mit gleicher ID werden übersprungen.
          </p>
          <input
            ref="importFileInput"
            type="file"
            accept="application/json,application/zip,.json,.zip,.fedeo-export.zip"
            class="hidden"
            @change="importTenantExport"
          >
          <UButton
            class="mt-4"
            icon="i-heroicons-arrow-up-tray"
            color="warning"
            :loading="importingTenant"
            @click="openImportFileDialog"
          >
            Export importieren
          </UButton>
          <div v-if="tenantImportProgress" class="mt-4 space-y-2">
            <UProgress
              :model-value="tenantImportProgress.filesTotal ? Math.round((tenantImportProgress.filesDone / tenantImportProgress.filesTotal) * 100) : undefined"
            />
            <p class="text-xs text-gray-500">
              {{ tenantImportProgress.status === 'ready' ? 'Import abgeschlossen' : 'Import wird verarbeitet' }}
              <span v-if="tenantImportProgress.filesTotal">
                · {{ tenantImportProgress.filesDone }} / {{ tenantImportProgress.filesTotal }} Schritte
              </span>
            </p>
          </div>
        </div>
      </div>

      <UAlert
        v-if="lastImportResult"
        class="mt-4"
        title="Letzter Import"
        :description="`Tenant ${lastImportResult.tenantId}: ${lastImportResult.rowCount} Datensätze aus ${lastImportResult.tableCount} Tabellen verarbeitet, ${lastImportResult.restoredFiles} Dateien wiederhergestellt, ${lastImportResult.skippedFiles} Dateien übersprungen.`"
        color="green"
        variant="soft"
      />
    </UCard>

    <UCard v-if="!loading && tenantForm" class="mt-3">
      <USeparator label="Zugeordnete Benutzer" />

      <UTable
        :data="assignedUsers"
        :columns="normalizeTableColumns([
          { key: 'display_name', label: 'Benutzer' },
          { key: 'email', label: 'E-Mail' }
        ])"
        :on-select="(row) => router.push(`/administration/users/${row.original?.id || row.id}`)"
        class="mt-4"
      >
        <template #empty>
          <TableEmptyState label="Keine zugeordneten Benutzer gefunden" />
        </template>
      </UTable>
    </UCard>

    <USkeleton v-if="loading" class="h-80" />
  </UDashboardPanelContent>

  <UModal v-model:open="createUserModalOpen">
    <template #content>
      <UCard>
        <template #header>
          <div class="text-lg font-semibold">Benutzer in Tenant anlegen</div>
        </template>

        <UForm :state="createUserForm" class="space-y-4" @submit.prevent="createTenantUser">
          <UFormField label="Tenant">
            <UInput :model-value="tenantForm?.name || ''" readonly />
          </UFormField>

          <UFormField label="E-Mail">
            <UInput v-model="createUserForm.email" type="email" />
          </UFormField>

          <UFormField label="Initialpasswort">
            <UInput v-model="createUserForm.password" placeholder="Leer lassen für automatisches Passwort" />
          </UFormField>

          <UFormField label="Vorname für Profil">
            <UInput v-model="createUserForm.first_name" />
          </UFormField>

          <UFormField label="Nachname für Profil">
            <UInput v-model="createUserForm.last_name" />
          </UFormField>

          <UFormField label="Administrative Freigabe">
            <div class="flex items-center gap-3 h-10">
              <USwitch v-model="createUserForm.is_admin" />
              <span class="text-sm text-gray-600">Benutzer darf die Administration öffnen</span>
            </div>
          </UFormField>

          <UFormField label="Multi-Tenant">
            <div class="flex items-center gap-3 h-10">
              <USwitch v-model="createUserForm.multiTenant" />
              <span class="text-sm text-gray-600">Weitere Tenant-Zuordnungen sind erlaubt</span>
            </div>
          </UFormField>

          <UAlert
            title="Automatische Zuordnung"
            description="Der Benutzer wird nach dem Anlegen direkt diesem Tenant zugeordnet und bekommt dort automatisch ein Profil mit den angegebenen Stammdaten."
            color="primary"
            variant="soft"
          />

          <div class="flex justify-end gap-3 pt-2">
            <UButton color="gray" variant="soft" @click="createUserModalOpen = false">
              Abbrechen
            </UButton>
            <UButton type="submit" color="primary" :loading="creatingUser">
              Benutzer anlegen
            </UButton>
          </div>
        </UForm>
      </UCard>
    </template>
  </UModal>

  <div class="mx-5 mb-5">
    <UAlert
      v-if="createdUserPassword"
      title="Initialpasswort für neuen Benutzer"
      :description="createdUserPassword"
      color="amber"
      variant="soft"
      close-button
      @close="createdUserPassword = ''"
    />
  </div>
</template>
