"use client"

import { useState } from "react"
import { formatDistanceToNow } from "date-fns"
import { Bell, Plus, X, Send, Users, Radio } from "lucide-react"
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"

// ─── Types ────────────────────────────────────────────────────────────────────

export type NotificationItem = {
  id: string
  notificationId: string
  title: string
  body: string
  type: string
  createdBy: string | null
  createdAt: string
  readAt: string | null
}

export type NotificationUser = {
  id: string
  name: string | null
  email: string
}

export type NotificationsClientProps = {
  notifications: NotificationItem[]
  canCreate: boolean
  users: NotificationUser[]
}

// ─── Create Form ──────────────────────────────────────────────────────────────

type CreateFormProps = {
  users: NotificationUser[]
  onSent: () => void
  onCancel: () => void
}

function CreateNotificationForm({ users, onSent, onCancel }: CreateFormProps) {
  const [title, setTitle] = useState("")
  const [body, setBody] = useState("")
  const [type, setType] = useState<"broadcast" | "targeted">("broadcast")
  const [selectedUserIds, setSelectedUserIds] = useState<string[]>([])
  const [sending, setSending] = useState(false)
  const [error, setError] = useState("")
  const [search, setSearch] = useState("")

  const filteredUsers = users.filter((u) => {
    const q = search.toLowerCase()
    return (
      u.name?.toLowerCase().includes(q) ||
      u.email.toLowerCase().includes(q)
    )
  })

  function toggleUser(id: string) {
    setSelectedUserIds((prev) =>
      prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id]
    )
  }

  function selectAll() {
    setSelectedUserIds(filteredUsers.map((u) => u.id))
  }

  function clearAll() {
    setSelectedUserIds([])
  }

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault()
    if (!title.trim() || !body.trim()) return
    if (type === "targeted" && selectedUserIds.length === 0) {
      setError("Please select at least one recipient.")
      return
    }

    setSending(true)
    setError("")

    try {
      const res = await fetch("/api/notifications", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          title: title.trim(),
          body: body.trim(),
          type,
          recipientUserIds: type === "targeted" ? selectedUserIds : undefined,
        }),
      })

      if (!res.ok) {
        const data = await res.json().catch(() => null)
        throw new Error(data?.error ?? "Failed to send notification")
      }

      onSent()
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to send notification")
    } finally {
      setSending(false)
    }
  }

  return (
    <Card>
      <CardHeader className="flex-row items-center justify-between">
        <CardTitle className="text-sm font-medium">Send Notification</CardTitle>
        <Button type="button" variant="ghost" size="sm" onClick={onCancel}>
          <X className="h-4 w-4" />
        </Button>
      </CardHeader>
      <CardContent>
        <form onSubmit={handleSubmit} className="space-y-4">
          {error && (
            <div className="rounded-md border border-destructive/30 bg-destructive/10 p-2 text-xs text-destructive">
              {error}
            </div>
          )}

          {/* Title */}
          <div className="space-y-2">
            <Label>Title</Label>
            <Input
              value={title}
              onChange={(e) => setTitle(e.target.value)}
              placeholder="e.g. Office closed on Friday"
              required
            />
          </div>

          {/* Body */}
          <div className="space-y-2">
            <Label>Message</Label>
            <textarea
              className="min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
              value={body}
              onChange={(e) => setBody(e.target.value)}
              placeholder="Write your message here..."
              required
            />
          </div>

          {/* Audience toggle */}
          <div className="space-y-2">
            <Label>Audience</Label>
            <div className="flex gap-2">
              <button
                type="button"
                onClick={() => setType("broadcast")}
                className={cn(
                  "flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-xs transition-colors",
                  type === "broadcast"
                    ? "border-primary bg-primary text-primary-foreground"
                    : "border-border text-muted-foreground hover:text-foreground"
                )}
              >
                <Radio className="h-3 w-3" />
                Broadcast (everyone)
              </button>
              <button
                type="button"
                onClick={() => setType("targeted")}
                className={cn(
                  "flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-xs transition-colors",
                  type === "targeted"
                    ? "border-primary bg-primary text-primary-foreground"
                    : "border-border text-muted-foreground hover:text-foreground"
                )}
              >
                <Users className="h-3 w-3" />
                Targeted
              </button>
            </div>
          </div>

          {/* Recipient picker */}
          {type === "targeted" && (
            <div className="space-y-2">
              <div className="flex items-center justify-between">
                <Label>
                  Recipients{" "}
                  <span className="font-normal text-muted-foreground">
                    ({selectedUserIds.length} selected)
                  </span>
                </Label>
                <div className="flex gap-2 text-xs">
                  <button type="button" onClick={selectAll} className="text-primary hover:underline">
                    Select all
                  </button>
                  <span className="text-muted-foreground">·</span>
                  <button type="button" onClick={clearAll} className="text-muted-foreground hover:text-foreground">
                    Clear
                  </button>
                </div>
              </div>

              <Input
                placeholder="Search users..."
                value={search}
                onChange={(e) => setSearch(e.target.value)}
                className="h-8 text-xs"
              />

              <div className="max-h-44 overflow-y-auto rounded-md border border-input">
                {filteredUsers.length === 0 ? (
                  <p className="px-3 py-4 text-center text-xs text-muted-foreground">No users found</p>
                ) : (
                  filteredUsers.map((u) => (
                    <label
                      key={u.id}
                      className="flex cursor-pointer items-center gap-2 border-b border-border/50 px-3 py-2 text-sm last:border-0 hover:bg-muted/50"
                    >
                      <input
                        type="checkbox"
                        className="h-4 w-4 shrink-0"
                        checked={selectedUserIds.includes(u.id)}
                        onChange={() => toggleUser(u.id)}
                      />
                      <span className="truncate">{u.name ?? u.email}</span>
                      {u.name && (
                        <span className="ml-auto shrink-0 text-xs text-muted-foreground">
                          {u.email}
                        </span>
                      )}
                    </label>
                  ))
                )}
              </div>
            </div>
          )}

          <div className="flex justify-end gap-2">
            <Button type="button" variant="ghost" size="sm" onClick={onCancel}>
              Cancel
            </Button>
            <Button type="submit" size="sm" disabled={sending}>
              <Send className="mr-1.5 h-3.5 w-3.5" />
              {sending ? "Sending..." : "Send"}
            </Button>
          </div>
        </form>
      </CardContent>
    </Card>
  )
}

// ─── Notification Row ─────────────────────────────────────────────────────────

function NotificationRow({
  n,
  onRead,
}: {
  n: NotificationItem
  onRead?: () => void
}) {
  const isUnread = !n.readAt

  return (
    <div
      onClick={() => isUnread && onRead?.()}
      className={cn(
        "rounded-lg border border-border p-4 transition-colors",
        isUnread && "cursor-pointer border-primary/20 bg-primary/5 hover:bg-primary/10"
      )}
    >
      <div className="flex items-start justify-between gap-2">
        <p className={cn("text-sm leading-snug", isUnread && "font-semibold")}>{n.title}</p>
        {isUnread && (
          <span className="mt-1.5 h-2 w-2 shrink-0 rounded-full bg-primary" />
        )}
      </div>

      <p className="mt-1 text-sm text-muted-foreground">{n.body}</p>

      <div className="mt-2 flex items-center gap-1.5 text-[11px] text-muted-foreground/60">
        <span>{formatDistanceToNow(new Date(n.createdAt), { addSuffix: true })}</span>
        {n.createdBy && (
          <>
            <span>·</span>
            <span>from {n.createdBy}</span>
          </>
        )}
        <span>·</span>
        <span
          className={cn(
            "rounded px-1 py-0.5 text-[10px]",
            n.type === "broadcast"
              ? "bg-blue-500/10 text-blue-500"
              : "bg-violet-500/10 text-violet-500"
          )}
        >
          {n.type === "broadcast" ? "Everyone" : "Targeted"}
        </span>
      </div>
    </div>
  )
}

// ─── Empty State ──────────────────────────────────────────────────────────────

function EmptyState() {
  return (
    <div className="flex flex-col items-center gap-3 py-20 text-muted-foreground">
      <div className="flex h-12 w-12 items-center justify-center rounded-full border border-border bg-muted/40">
        <Bell className="h-5 w-5 opacity-40" />
      </div>
      <div className="text-center">
        <p className="text-sm font-medium">No notifications yet</p>
        <p className="text-xs text-muted-foreground/70">You're all caught up!</p>
      </div>
    </div>
  )
}

// ─── Main Client ──────────────────────────────────────────────────────────────

export default function NotificationsClient({
  notifications: initial,
  canCreate,
  users,
}: NotificationsClientProps) {
  const [notifications, setNotifications] = useState(initial)
  const [showCreate, setShowCreate] = useState(false)

  const unread = notifications.filter((n) => !n.readAt)
  const read = notifications.filter((n) => n.readAt)

  async function markRead(notificationId: string) {
    await fetch(`/api/notifications/${notificationId}/read`, { method: "PATCH" })
    setNotifications((prev) =>
      prev.map((n) =>
        n.notificationId === notificationId
          ? { ...n, readAt: new Date().toISOString() }
          : n
      )
    )
  }

  async function markAllRead() {
    const res = await fetch("/api/notifications/read-all", { method: "PATCH" })
    if (res.ok) {
      fetch("/api/notifications")
        .then((r) => r.json())
        .then(setNotifications)
        .catch(() => null)
    }
  }

  function handleSent() {
    setShowCreate(false)
    fetch("/api/notifications")
      .then((r) => r.json())
      .then(setNotifications)
      .catch(() => null)
  }

  return (
    <div className="mx-auto max-w-2xl space-y-6 p-6">
      {/* Page header */}
      <div className="flex items-center justify-between">
        <div>
          <h1 className="text-xl font-semibold">Notifications</h1>
          <p className="text-sm text-muted-foreground">
            {unread.length > 0 ? `${unread.length} unread` : "All caught up"}
          </p>
        </div>

        <div className="flex items-center gap-2">
          {unread.length > 0 && (
            <Button variant="ghost" size="sm" onClick={markAllRead}>
              Mark all read
            </Button>
          )}
          {canCreate && (
            <Button size="sm" onClick={() => setShowCreate((v) => !v)}>
              {showCreate ? (
                <><X className="mr-1.5 h-4 w-4" />Cancel</>
              ) : (
                <><Plus className="mr-1.5 h-4 w-4" />New</>
              )}
            </Button>
          )}
        </div>
      </div>

      {/* Create form */}
      {showCreate && canCreate && (
        <CreateNotificationForm
          users={users}
          onSent={handleSent}
          onCancel={() => setShowCreate(false)}
        />
      )}

      {/* Lists */}
      {notifications.length === 0 && !showCreate ? (
        <EmptyState />
      ) : (
        <>
          {unread.length > 0 && (
            <section className="space-y-2">
              <p className="text-xs font-medium uppercase tracking-wider text-muted-foreground">
                Unread
              </p>
              {unread.map((n) => (
                <NotificationRow
                  key={n.id}
                  n={n}
                  onRead={() => markRead(n.notificationId)}
                />
              ))}
            </section>
          )}

          {read.length > 0 && (
            <section className="space-y-2">
              <p className="text-xs font-medium uppercase tracking-wider text-muted-foreground">
                Earlier
              </p>
              {read.map((n) => (
                <NotificationRow key={n.id} n={n} />
              ))}
            </section>
          )}
        </>
      )}
    </div>
  )
}