import { useState, useEffect } from 'react'
import { createFileRoute } from '@tanstack/react-router'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import {
  vaultStatusOptions, vaultCategoryListOptions, vaultCategoryDetailOptions,
  vaultEntryListOptions, vaultKeys, vaultMutations, vaultCategoryMutations, vaultEntryMutations,
} from '@/api/vault'
import { usePagination } from '@/hooks/use-pagination'
import { useAuthStore } from '@/stores/auth.store'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Badge } from '@/components/ui/badge'
import { Skeleton } from '@/components/ui/skeleton'
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog'
import {
  DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import {
  KeyRound, Lock, Plus, MoreVertical, Trash2, Eye, EyeOff, Copy,
  FolderKey, Shield, ShieldAlert, User2, Globe, StickyNote,
} from 'lucide-react'
import { toast } from 'sonner'
import { CategoryPermissionsDialog } from '@/components/vault/category-permissions-dialog'
import type { VaultEntry } from '@/types/vault'

export const Route = createFileRoute('/_authenticated/vault/')({
  validateSearch: (search: Record<string, unknown>) => ({
    page: Number(search.page) || 1,
    limit: Number(search.limit) || 50,
    q: (search.q as string) || undefined,
    sort: (search.sort as string) || undefined,
    order: (search.order as 'asc' | 'desc') || 'asc',
  }),
  component: VaultPage,
})

function VaultPage() {
  const { data: status, isLoading: statusLoading } = useQuery(vaultStatusOptions())

  if (statusLoading) {
    return <div className="flex items-center justify-center h-[calc(100vh-6rem)]"><Skeleton className="h-32 w-80" /></div>
  }

  if (!status?.initialized) {
    return <InitializeView />
  }

  if (!status?.unlocked) {
    return <UnlockView />
  }

  return <VaultMain />
}

// --- Initialize View ---
function InitializeView() {
  const queryClient = useQueryClient()
  const hasPermission = useAuthStore((s) => s.hasPermission)
  const [password, setPassword] = useState('')
  const [confirm, setConfirm] = useState('')

  const initMutation = useMutation({
    mutationFn: () => vaultMutations.initialize(password),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: vaultKeys.status })
      toast.success('Vault initialized')
    },
    onError: (err) => toast.error(err.message),
  })

  if (!hasPermission('vault.admin')) {
    return (
      <div className="flex flex-col items-center justify-center h-[calc(100vh-6rem)] text-muted-foreground">
        <ShieldAlert className="h-12 w-12 mb-3 opacity-30" />
        <p>Vault has not been set up yet.</p>
        <p className="text-xs mt-1">Ask an administrator to initialize the vault.</p>
      </div>
    )
  }

  return (
    <div className="flex items-center justify-center h-[calc(100vh-6rem)]">
      <div className="w-80 space-y-4">
        <div className="text-center">
          <KeyRound className="h-10 w-10 mx-auto mb-2 text-muted-foreground" />
          <h2 className="text-lg font-semibold">Set Up Vault</h2>
          <p className="text-sm text-muted-foreground">Create a master password to protect your secrets.</p>
        </div>
        <form onSubmit={(e) => { e.preventDefault(); if (password === confirm && password.length >= 8) initMutation.mutate() }} className="space-y-3">
          <div className="space-y-1">
            <Label>Master Password</Label>
            <Input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="Min 8 characters" autoFocus />
          </div>
          <div className="space-y-1">
            <Label>Confirm Password</Label>
            <Input type="password" value={confirm} onChange={(e) => setConfirm(e.target.value)} />
          </div>
          {password && confirm && password !== confirm && (
            <p className="text-xs text-destructive">Passwords do not match</p>
          )}
          <Button type="submit" className="w-full" disabled={!password || password !== confirm || password.length < 8 || initMutation.isPending}>
            {initMutation.isPending ? 'Initializing...' : 'Initialize Vault'}
          </Button>
        </form>
      </div>
    </div>
  )
}

// --- Unlock View ---
function UnlockView() {
  const queryClient = useQueryClient()
  const [password, setPassword] = useState('')

  const unlockMutation = useMutation({
    mutationFn: () => vaultMutations.unlock(password),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: vaultKeys.status })
      toast.success('Vault unlocked')
    },
    onError: () => toast.error('Invalid master password'),
  })

  return (
    <div className="flex items-center justify-center h-[calc(100vh-6rem)]">
      <div className="w-80 space-y-4">
        <div className="text-center">
          <Lock className="h-10 w-10 mx-auto mb-2 text-muted-foreground" />
          <h2 className="text-lg font-semibold">Vault Locked</h2>
          <p className="text-sm text-muted-foreground">Enter the master password to unlock.</p>
        </div>
        <form onSubmit={(e) => { e.preventDefault(); if (password) unlockMutation.mutate() }} className="space-y-3">
          <Input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="Master password" autoFocus />
          <Button type="submit" className="w-full" disabled={!password || unlockMutation.isPending}>
            {unlockMutation.isPending ? 'Unlocking...' : 'Unlock'}
          </Button>
        </form>
      </div>
    </div>
  )
}

// --- Main Vault UI ---
function VaultMain() {
  const queryClient = useQueryClient()
  const hasPermission = useAuthStore((s) => s.hasPermission)
  const { params } = usePagination()
  const [selectedCategoryId, setSelectedCategoryId] = useState<string | null>(null)
  const [newCatOpen, setNewCatOpen] = useState(false)
  const [newCatName, setNewCatName] = useState('')
  const [newEntryOpen, setNewEntryOpen] = useState(false)
  const [entryForm, setEntryForm] = useState({ name: '', username: '', url: '', notes: '', secret: '' })
  const [editEntryId, setEditEntryId] = useState<string | null>(null)
  const [permissionsOpen, setPermissionsOpen] = useState(false)

  const { data: catData, isLoading: catsLoading } = useQuery(vaultCategoryListOptions())
  const { data: catDetail } = useQuery(vaultCategoryDetailOptions(selectedCategoryId ?? ''))
  const { data: entriesData, isLoading: entriesLoading } = useQuery(
    vaultEntryListOptions(selectedCategoryId ?? '', { ...params, limit: 50 }),
  )

  const categories = catData?.data ?? []
  const entries = entriesData?.data ?? []

  const lockMutation = useMutation({
    mutationFn: vaultMutations.lock,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: vaultKeys.status })
      toast.success('Vault locked')
    },
  })

  const createCatMutation = useMutation({
    mutationFn: () => vaultCategoryMutations.create({ name: newCatName.trim() }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: vaultKeys.categories })
      setNewCatOpen(false)
      setNewCatName('')
      toast.success('Category created')
    },
    onError: (err) => toast.error(err.message),
  })

  const deleteCatMutation = useMutation({
    mutationFn: vaultCategoryMutations.delete,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: vaultKeys.categories })
      setSelectedCategoryId(null)
      toast.success('Category deleted')
    },
    onError: (err) => toast.error(err.message),
  })

  const createEntryMutation = useMutation({
    mutationFn: () => vaultEntryMutations.create(selectedCategoryId!, {
      name: entryForm.name.trim(),
      username: entryForm.username || undefined,
      url: entryForm.url || undefined,
      notes: entryForm.notes || undefined,
      secret: entryForm.secret || undefined,
    }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: vaultKeys.entries(selectedCategoryId!) })
      setNewEntryOpen(false)
      setEntryForm({ name: '', username: '', url: '', notes: '', secret: '' })
      toast.success('Entry created')
    },
    onError: (err) => toast.error(err.message),
  })

  const updateEntryMutation = useMutation({
    mutationFn: () => vaultEntryMutations.update(editEntryId!, {
      name: entryForm.name.trim(),
      username: entryForm.username || undefined,
      url: entryForm.url || undefined,
      notes: entryForm.notes || undefined,
      secret: entryForm.secret || undefined,
    }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: vaultKeys.entries(selectedCategoryId!) })
      setEditEntryId(null)
      setNewEntryOpen(false)
      setEntryForm({ name: '', username: '', url: '', notes: '', secret: '' })
      toast.success('Entry updated')
    },
    onError: (err) => toast.error(err.message),
  })

  const deleteEntryMutation = useMutation({
    mutationFn: vaultEntryMutations.delete,
    onSuccess: () => {
      if (selectedCategoryId) queryClient.invalidateQueries({ queryKey: vaultKeys.entries(selectedCategoryId) })
      toast.success('Entry deleted')
    },
    onError: (err) => toast.error(err.message),
  })

  function openEditEntry(entry: VaultEntry) {
    setEditEntryId(entry.id)
    setEntryForm({ name: entry.name, username: entry.username ?? '', url: entry.url ?? '', notes: entry.notes ?? '', secret: '' })
    setNewEntryOpen(true)
  }

  function handleEntrySubmit(e: React.FormEvent) {
    e.preventDefault()
    if (!entryForm.name.trim()) return
    if (editEntryId) {
      updateEntryMutation.mutate()
    } else {
      createEntryMutation.mutate()
    }
  }

  return (
    <div className="flex gap-0 h-[calc(100vh-6rem)]">
      {/* Left Panel — Categories */}
      <div className="w-60 shrink-0 border-r overflow-y-auto p-3">
        <div className="flex items-center justify-between mb-3">
          <h2 className="text-sm font-semibold">Vault</h2>
          <div className="flex gap-1">
            {hasPermission('vault.admin') && (
              <Button variant="ghost" size="sm" className="h-7 w-7 p-0" onClick={() => lockMutation.mutate()} title="Lock vault">
                <Lock className="h-4 w-4" />
              </Button>
            )}
            <Dialog open={newCatOpen} onOpenChange={setNewCatOpen}>
              <DialogTrigger asChild>
                <Button variant="ghost" size="sm" className="h-7 w-7 p-0"><Plus className="h-4 w-4" /></Button>
              </DialogTrigger>
              <DialogContent>
                <DialogHeader><DialogTitle>New Category</DialogTitle></DialogHeader>
                <form onSubmit={(e) => { e.preventDefault(); if (newCatName.trim()) createCatMutation.mutate() }} className="space-y-4">
                  <div className="space-y-2">
                    <Label>Name</Label>
                    <Input value={newCatName} onChange={(e) => setNewCatName(e.target.value)} placeholder="e.g. WiFi Passwords" autoFocus />
                  </div>
                  <Button type="submit" disabled={!newCatName.trim() || createCatMutation.isPending}>
                    {createCatMutation.isPending ? 'Creating...' : 'Create'}
                  </Button>
                </form>
              </DialogContent>
            </Dialog>
          </div>
        </div>

        {catsLoading ? (
          <div className="space-y-2">{Array.from({ length: 4 }).map((_, i) => <Skeleton key={i} className="h-8 w-full" />)}</div>
        ) : categories.length === 0 ? (
          <p className="text-xs text-muted-foreground px-2">No categories yet</p>
        ) : (
          <div className="space-y-0.5">
            {categories.map((cat) => (
              <button
                key={cat.id}
                type="button"
                onClick={() => setSelectedCategoryId(cat.id)}
                className={`w-full flex items-center gap-2 px-2 py-1.5 rounded-md text-sm text-left transition-colors ${
                  selectedCategoryId === cat.id ? 'bg-accent text-accent-foreground' : 'hover:bg-muted'
                }`}
              >
                <FolderKey className="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
                <span className="truncate">{cat.name}</span>
              </button>
            ))}
          </div>
        )}
      </div>

      {/* Right Panel — Entries */}
      <div className="flex-1 overflow-y-auto">
        {/* Toolbar */}
        <div className="flex items-center gap-2 p-3 border-b">
          <div className="flex-1 text-sm font-medium">
            {catDetail ? catDetail.name : 'Select a category'}
          </div>
          {selectedCategoryId && (
            <>
              {catDetail?.accessLevel === 'admin' && (
                <>
                  <Button variant="outline" size="sm" onClick={() => setPermissionsOpen(true)}>
                    <Shield className="mr-2 h-4 w-4" />Permissions
                  </Button>
                  <Button variant="outline" size="sm" onClick={() => deleteCatMutation.mutate(selectedCategoryId)}>
                    <Trash2 className="mr-2 h-4 w-4" />Delete Category
                  </Button>
                </>
              )}
              {hasPermission('vault.edit') && (
                <Button variant="outline" size="sm" onClick={() => {
                  setEditEntryId(null)
                  setEntryForm({ name: '', username: '', url: '', notes: '', secret: '' })
                  setNewEntryOpen(true)
                }}>
                  <Plus className="mr-2 h-4 w-4" />Add Entry
                </Button>
              )}
            </>
          )}
        </div>

        {/* Content */}
        <div className="p-4">
          {!selectedCategoryId ? (
            <div className="text-center py-12 text-muted-foreground">
              <KeyRound className="h-12 w-12 mx-auto mb-3 opacity-30" />
              <p>Select a category to view secrets</p>
            </div>
          ) : entriesLoading ? (
            <div className="space-y-2">{Array.from({ length: 4 }).map((_, i) => <Skeleton key={i} className="h-16 w-full" />)}</div>
          ) : entries.length === 0 ? (
            <div className="text-center py-12 text-muted-foreground">
              <Plus className="h-10 w-10 mx-auto mb-3 opacity-30" />
              <p>No entries in this category</p>
            </div>
          ) : (
            <div className="space-y-2">
              {entries.map((entry) => (
                <EntryRow key={entry.id} entry={entry} onEdit={() => openEditEntry(entry)} onDelete={() => deleteEntryMutation.mutate(entry.id)} />
              ))}
            </div>
          )}
        </div>
      </div>

      {/* Permissions Dialog */}
      {selectedCategoryId && catDetail && (
        <CategoryPermissionsDialog
          categoryId={selectedCategoryId}
          categoryName={catDetail.name ?? ''}
          isPublic={catDetail.isPublic ?? false}
          open={permissionsOpen}
          onOpenChange={setPermissionsOpen}
        />
      )}

      {/* Entry Dialog */}
      <Dialog open={newEntryOpen} onOpenChange={(open) => { setNewEntryOpen(open); if (!open) setEditEntryId(null) }}>
        <DialogContent>
          <DialogHeader><DialogTitle>{editEntryId ? 'Edit Entry' : 'New Entry'}</DialogTitle></DialogHeader>
          <form onSubmit={handleEntrySubmit} className="space-y-3" autoComplete="off">
            <div className="space-y-1">
              <Label>Name *</Label>
              <Input value={entryForm.name} onChange={(e) => setEntryForm((f) => ({ ...f, name: e.target.value }))} placeholder="e.g. Store WiFi" autoFocus autoComplete="off" />
            </div>
            <div className="space-y-1">
              <Label>Username</Label>
              <Input value={entryForm.username} onChange={(e) => setEntryForm((f) => ({ ...f, username: e.target.value }))} placeholder="Optional" autoComplete="off" />
            </div>
            <div className="space-y-1">
              <Label>URL</Label>
              <Input value={entryForm.url} onChange={(e) => setEntryForm((f) => ({ ...f, url: e.target.value }))} placeholder="Optional" autoComplete="off" />
            </div>
            <div className="space-y-1">
              <Label>Notes</Label>
              <Input value={entryForm.notes} onChange={(e) => setEntryForm((f) => ({ ...f, notes: e.target.value }))} placeholder="Optional" autoComplete="off" />
            </div>
            <div className="space-y-1">
              <Label>{editEntryId ? 'New Secret (leave blank to keep current)' : 'Secret'}</Label>
              <Input type="password" value={entryForm.secret} onChange={(e) => setEntryForm((f) => ({ ...f, secret: e.target.value }))} placeholder="Password or secret value" autoComplete="new-password" />
            </div>
            <Button type="submit" disabled={!entryForm.name.trim() || createEntryMutation.isPending || updateEntryMutation.isPending}>
              {(createEntryMutation.isPending || updateEntryMutation.isPending) ? 'Saving...' : editEntryId ? 'Update' : 'Create'}
            </Button>
          </form>
        </DialogContent>
      </Dialog>
    </div>
  )
}

// --- Entry Row with Reveal ---
function EntryRow({ entry, onEdit, onDelete }: { entry: VaultEntry; onEdit: () => void; onDelete: () => void }) {
  const hasPermission = useAuthStore((s) => s.hasPermission)
  const [revealed, setRevealed] = useState<string | null>(null)
  const [revealing, setRevealing] = useState(false)

  // Auto-hide after 30 seconds
  useEffect(() => {
    if (revealed === null) return
    const timer = setTimeout(() => setRevealed(null), 30_000)
    return () => clearTimeout(timer)
  }, [revealed])

  async function handleReveal() {
    setRevealing(true)
    try {
      const res = await vaultEntryMutations.reveal(entry.id)
      setRevealed(res.value)
    } catch {
      toast.error('Failed to reveal secret')
    } finally {
      setRevealing(false)
    }
  }

  function handleCopy() {
    if (revealed) {
      navigator.clipboard.writeText(revealed)
      toast.success('Copied to clipboard')
    }
  }

  return (
    <div className="flex items-start gap-3 p-3 rounded-lg border hover:bg-accent/50 transition-colors group">
      <KeyRound className="h-5 w-5 mt-0.5 shrink-0 text-muted-foreground" />
      <div className="flex-1 min-w-0">
        <div className="flex items-center gap-2">
          <span className="font-medium text-sm">{entry.name}</span>
          {entry.hasSecret && <Badge variant="secondary" className="text-[10px]">secret</Badge>}
        </div>
        <div className="flex flex-wrap gap-x-4 gap-y-0.5 mt-1 text-xs text-muted-foreground">
          {entry.username && (
            <span className="flex items-center gap-1"><User2 className="h-3 w-3" />{entry.username}</span>
          )}
          {entry.url && (
            <span className="flex items-center gap-1"><Globe className="h-3 w-3" />{entry.url}</span>
          )}
          {entry.notes && (
            <span className="flex items-center gap-1"><StickyNote className="h-3 w-3" />{entry.notes}</span>
          )}
        </div>
        {revealed !== null && (
          <div className="mt-2 flex items-center gap-2">
            <code className="text-xs bg-muted px-2 py-1 rounded font-mono">{revealed}</code>
            <button type="button" onClick={handleCopy} className="text-muted-foreground hover:text-foreground">
              <Copy className="h-3.5 w-3.5" />
            </button>
            <button type="button" onClick={() => setRevealed(null)} className="text-muted-foreground hover:text-foreground">
              <EyeOff className="h-3.5 w-3.5" />
            </button>
          </div>
        )}
      </div>
      <div className="flex items-center gap-1 shrink-0">
        {entry.hasSecret && hasPermission('vault.edit') && revealed === null && (
          <Button variant="ghost" size="sm" className="h-7 px-2" onClick={handleReveal} disabled={revealing}>
            <Eye className="h-3.5 w-3.5 mr-1" />{revealing ? '...' : 'Reveal'}
          </Button>
        )}
        {hasPermission('vault.edit') && (
          <DropdownMenu>
            <DropdownMenuTrigger asChild>
              <button className="h-7 w-7 rounded-md flex items-center justify-center opacity-0 group-hover:opacity-100 hover:bg-muted transition-opacity">
                <MoreVertical className="h-3.5 w-3.5" />
              </button>
            </DropdownMenuTrigger>
            <DropdownMenuContent align="end">
              <DropdownMenuItem onClick={onEdit}>Edit</DropdownMenuItem>
              <DropdownMenuItem className="text-destructive" onClick={onDelete}>
                <Trash2 className="mr-2 h-4 w-4" />Delete
              </DropdownMenuItem>
            </DropdownMenuContent>
          </DropdownMenu>
        )}
      </div>
    </div>
  )
}
