import { createFileRoute, Link, useNavigate } from "@tanstack/react-router"
import { useState } from "react"
import { useTranslation } from "react-i18next"
import { useMutation } from "@tanstack/react-query"
import {
  ArrowLeft,
  ChevronRight,
  Download,
  Key,
  LogOut,
  RefreshCw,
  ShieldBan,
  Sparkles,
  Target,
  Upload,
  User,
} from "lucide-react"
import { Button } from "@/components/ui/button"
import { Switch } from "@/components/ui/switch"
import { useAuth, useIsAdmin } from "@/components/auth-provider"
import { API_URL } from "@/lib/api/client"
import { getToken } from "@/lib/auth"
import { reindexSearch } from "@/lib/api/users"
import { useSettings, useUpdateSettings } from "@/hooks/use-goals"
import { useDocumentTitle } from "@/hooks/use-document-title"

export const Route = createFileRoute("/_app/settings/")({
  component: SettingsPage,
})

type SettingsItem = {
  label: string
  description?: string
  to: string
  icon: React.ReactNode
}

function SettingsPage() {
  const { t } = useTranslation()
  useDocumentTitle(t("settings.title"))
  const { logout } = useAuth()
  const isAdmin = useIsAdmin()
  const navigate = useNavigate()

  const account: SettingsItem[] = [
    {
      label: t("settings.editProfile"),
      description: t("settings.editProfileDesc"),
      to: "/settings/edit-profile",
      icon: <User className="size-4" />,
    },
  ]

  const data: SettingsItem[] = [
    {
      label: t("settings.import"),
      description: t("settings.importDesc"),
      to: "/settings/import",
      icon: <Download className="size-4" />,
    },
    {
      label: t("settings.yearWrapUp"),
      description: t("settings.yearWrapUpDesc"),
      to: "/settings/wrapup",
      icon: <Sparkles className="size-4" />,
    },
  ]

  const integrations: SettingsItem[] = [
    {
      label: t("settings.webhookTokens"),
      description: t("settings.webhookTokensDesc"),
      to: "/settings/webhooks",
      icon: <Key className="size-4" />,
    },
  ]

  const social: SettingsItem[] = [
    {
      label: isAdmin ? t("settings.blockedUsersAndDomains") : t("settings.blockedUsers"),
      description: isAdmin ? t("settings.blockedUsersDescAdmin") : t("settings.blockedUsersDesc"),
      to: "/settings/blocked",
      icon: <ShieldBan className="size-4" />,
    },
  ]

  const handleLogout = () => {
    logout()
    navigate({ to: "/login" })
  }

  return (
    <div className="space-y-6 p-4">
      <div className="flex items-center gap-3">
        <Link to="/profile" className="text-muted-foreground">
          <ArrowLeft className="size-5" />
        </Link>
        <h1 className="text-lg font-bold">{t("settings.title")}</h1>
      </div>

      <SettingsGroup label={t("settings.account")} items={account} />
      <SettingsGroup label={t("settings.data")} items={data} />
      <ExportSection />
      <SettingsGroup label={t("settings.integrations")} items={integrations} />
      <SettingsGroup label={t("settings.socialGroup")} items={social} />

      <PrivacySection />

      {isAdmin && <AdminActions />}

      <button
        onClick={handleLogout}
        className="w-full rounded-xl bg-card p-3 text-sm font-medium text-red-400"
      >
        <div className="flex items-center gap-3">
          <LogOut className="size-4" />
          {t("settings.logOut")}
        </div>
      </button>
    </div>
  )
}

function PrivacySection() {
  const { t } = useTranslation()
  const { data: settings } = useSettings()
  const updateMutation = useUpdateSettings()

  return (
    <div>
      <p className="mb-1.5 px-1 text-xs font-medium text-muted-foreground">
        {t("settings.privacy")}
      </p>
      <div className="divide-y divide-border rounded-xl bg-card">
        <div className="flex items-center gap-3 p-3">
          <span className="text-muted-foreground">
            <Target className="size-4" />
          </span>
          <div className="flex-1">
            <p className="text-sm font-medium">{t("settings.federateGoals")}</p>
            <p className="text-xs text-muted-foreground">
              {t("settings.federateGoalsDesc")}
            </p>
          </div>
          <Switch
            checked={settings?.federate_goals ?? false}
            onCheckedChange={(checked) =>
              updateMutation.mutate({ federate_goals: checked })
            }
            disabled={updateMutation.isPending}
          />
        </div>
      </div>
    </div>
  )
}

function AdminActions() {
  const { t } = useTranslation()
  const reindex = useMutation({
    mutationFn: reindexSearch,
  })

  return (
    <div>
      <p className="mb-1.5 px-1 text-xs font-medium text-muted-foreground">
        {t("settings.admin")}
      </p>
      <div className="divide-y divide-border rounded-xl bg-card">
        <div className="flex items-center gap-3 p-3">
          <span className="text-muted-foreground">
            <RefreshCw className={`size-4 ${reindex.isPending ? "animate-spin" : ""}`} />
          </span>
          <div className="flex-1">
            <p className="text-sm font-medium">{t("settings.rebuildSearch")}</p>
            <p className="text-xs text-muted-foreground">
              {reindex.isSuccess ? t("settings.rebuildSearchDone") : t("settings.rebuildSearchDesc")}
            </p>
          </div>
          <Button variant="outline" size="sm" onClick={() => reindex.mutate()} disabled={reindex.isPending}>
            {reindex.isPending ? t("common.generating") : t("common.run")}
          </Button>
        </div>
      </div>
    </div>
  )
}

function ExportSection() {
  const { t } = useTranslation()
  const [exporting, setExporting] = useState<string | null>(null)

  async function handleExport(format: "csv" | "json") {
    setExporting(format)
    try {
      const res = await fetch(`${API_URL}/api/v1/diary/export?format=${format}`, {
        headers: { Authorization: `Bearer ${getToken()}` },
      })
      const blob = await res.blob()
      const url = URL.createObjectURL(blob)
      const a = document.createElement("a")
      a.href = url
      a.download = `diary.${format}`
      a.click()
      URL.revokeObjectURL(url)
    } finally {
      setExporting(null)
    }
  }

  return (
    <div>
      <p className="mb-1.5 px-1 text-xs font-medium text-muted-foreground">
        {t("settings.export")}
      </p>
      <div className="divide-y divide-border rounded-xl bg-card">
        <div className="flex items-center gap-3 p-3">
          <span className="text-muted-foreground">
            <Upload className="size-4" />
          </span>
          <div className="flex-1">
            <p className="text-sm font-medium">{t("settings.export")}</p>
            <p className="text-xs text-muted-foreground">
              {t("settings.exportDesc")}
            </p>
          </div>
          <div className="flex gap-2">
            <Button
              variant="outline"
              size="sm"
              onClick={() => handleExport("csv")}
              disabled={exporting !== null}
            >
              {exporting === "csv" ? t("settings.exporting") : t("settings.exportCsv")}
            </Button>
            <Button
              variant="outline"
              size="sm"
              onClick={() => handleExport("json")}
              disabled={exporting !== null}
            >
              {exporting === "json" ? t("settings.exporting") : t("settings.exportJson")}
            </Button>
          </div>
        </div>
      </div>
    </div>
  )
}

function SettingsGroup({
  label,
  items,
}: {
  label: string
  items: SettingsItem[]
}) {
  return (
    <div>
      <p className="mb-1.5 px-1 text-xs font-medium text-muted-foreground">
        {label}
      </p>
      <div className="divide-y divide-border rounded-xl bg-card">
        {items.map((item) => (
          <Link
            key={item.label}
            to={item.to}
            className="flex items-center gap-3 p-3"
          >
            <span className="text-muted-foreground">{item.icon}</span>
            <div className="flex-1">
              <p className="text-sm font-medium">{item.label}</p>
              {item.description && (
                <p className="text-xs text-muted-foreground">
                  {item.description}
                </p>
              )}
            </div>
            <ChevronRight className="size-4 text-muted-foreground" />
          </Link>
        ))}
      </div>
    </div>
  )
}
