"use client";

import { useState } from "react";
import type {
  AnnouncementAudience,
  AnnouncementDisplayType,
} from "@prisma/client";
import { toast } from "sonner";
import {
  createAnnouncement,
  updateAnnouncement,
} from "@/actions/admin/announcements";
import { PendingSubmitButton } from "@/components/shared/pending-submit-button";
import { BooleanToggle } from "@/components/ui/boolean-toggle";
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogBody,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { Textarea } from "@/components/ui/textarea";
import { getErrorMessage } from "@/lib/errors";

interface AnnouncementOptionUser {
  id: string;
  email: string;
}

interface AnnouncementFormData {
  id: string;
  title: string;
  body: string;
  audience: AnnouncementAudience;
  displayType: AnnouncementDisplayType;
  targetUserId: string | null;
  dismissible: boolean;
  sendNotification: boolean;
  startAt: Date | string | null;
  endAt: Date | string | null;
}

const audienceLabels: Record<AnnouncementAudience, string> = {
  PUBLIC: "公开",
  USERS: "全部用户",
  ADMINS: "全部管理员",
  SPECIFIC_USER: "指定用户",
};

const displayTypeLabels: Record<AnnouncementDisplayType, string> = {
  INLINE: "普通公告",
  BIG: "大公告",
  POPUP: "弹窗公告",
};

function getAudienceLabel(value: unknown) {
  return audienceLabels[value as AnnouncementAudience] ?? "选择范围";
}

function getDisplayTypeLabel(value: unknown) {
  return displayTypeLabels[value as AnnouncementDisplayType] ?? "选择展示方式";
}

function getTargetUserLabel(users: AnnouncementOptionUser[], value: unknown) {
  if (!value) return "不指定";
  return users.find((user) => user.id === value)?.email ?? "选择用户";
}

function toDateTimeLocalValue(value: Date | string | null) {
  if (!value) {
    return "";
  }

  const date = new Date(value);
  if (Number.isNaN(date.getTime())) {
    return "";
  }

  const localTime = new Date(date.getTime() - date.getTimezoneOffset() * 60_000);
  return localTime.toISOString().slice(0, 16);
}

export function AnnouncementForm({
  users,
  announcement,
  triggerLabel,
  triggerVariant = "outline",
}: {
  users: AnnouncementOptionUser[];
  announcement: AnnouncementFormData;
  triggerLabel?: string;
  triggerVariant?: "default" | "outline" | "ghost";
}) {
  const [open, setOpen] = useState(false);
  const [audience, setAudience] = useState<AnnouncementAudience>(announcement.audience);

  async function handleSubmit(formData: FormData) {
    try {
      await updateAnnouncement(announcement.id, formData);
      toast.success("公告已更新");
      setOpen(false);
    } catch (error) {
      toast.error(getErrorMessage(error, "更新公告失败"));
    }
  }

  return (
    <Dialog
      open={open}
      onOpenChange={(nextOpen) => {
        if (nextOpen) {
          setAudience(announcement.audience);
        }
        setOpen(nextOpen);
      }}
    >
      <DialogTrigger render={<Button variant={triggerVariant} size="sm" />}>
        {triggerLabel ?? "编辑"}
      </DialogTrigger>
      <DialogContent className="flex max-h-[min(90dvh,38rem)] flex-col overflow-hidden p-0 sm:max-w-[30rem]">
        <DialogHeader className="border-b border-border/60 px-4 py-3 pr-10">
          <DialogTitle>编辑公告</DialogTitle>
        </DialogHeader>
        <DialogBody className="flex-1 px-4 py-3">
        <form action={handleSubmit} className="space-y-3 text-[12px] leading-5 [&_[data-slot=input]]:!h-8 [&_[data-slot=input]]:!min-h-8 [&_[data-slot=input]]:!px-2.5 [&_[data-slot=input]]:!text-xs [&_[data-slot=label]]:!text-xs [&_[data-slot=select-trigger]]:!h-8 [&_[data-slot=select-trigger]]:!min-h-8 [&_[data-slot=select-trigger]]:!px-2.5 [&_[data-slot=select-trigger]]:!text-xs [&_textarea]:!text-xs">
          <div className="grid gap-3 md:grid-cols-2">
            <div className="space-y-1.5">
              <Label htmlFor={`title-${announcement.id}`}>标题</Label>
              <Input id={`title-${announcement.id}`} name="title" defaultValue={announcement.title} required />
            </div>
            <div className="space-y-1.5">
              <Label htmlFor={`audience-${announcement.id}`}>目标范围</Label>
              <Select
                name="audience"
                value={audience}
                onValueChange={(value) => setAudience((value ?? "USERS") as AnnouncementAudience)}
              >
                <SelectTrigger id={`audience-${announcement.id}`} className="w-full">
                  <SelectValue>{(value) => getAudienceLabel(value)}</SelectValue>
                </SelectTrigger>
                <SelectContent align="start">
                  <SelectItem value="PUBLIC">公开（登录/注册页可见）</SelectItem>
                  <SelectItem value="USERS">全部用户</SelectItem>
                  <SelectItem value="ADMINS">全部管理员</SelectItem>
                  <SelectItem value="SPECIFIC_USER">指定用户</SelectItem>
                </SelectContent>
              </Select>
            </div>
          </div>

          <div className="grid gap-3 md:grid-cols-2">
            <div className="space-y-1.5">
              <Label htmlFor={`displayType-${announcement.id}`}>展示方式</Label>
              <Select
                name="displayType"
                defaultValue={announcement.displayType}
              >
                <SelectTrigger id={`displayType-${announcement.id}`} className="w-full">
                  <SelectValue>{(value) => getDisplayTypeLabel(value)}</SelectValue>
                </SelectTrigger>
                <SelectContent align="start">
                  <SelectItem value="INLINE">普通公告</SelectItem>
                  <SelectItem value="BIG">大公告</SelectItem>
                  <SelectItem value="POPUP">弹窗公告</SelectItem>
                </SelectContent>
              </Select>
            </div>
            <div className="space-y-1.5">
              <Label htmlFor={`dismissible-${announcement.id}`}>允许用户关闭</Label>
              <BooleanToggle
                id={`dismissible-${announcement.id}`}
                name="dismissible"
                defaultValue={announcement.dismissible}
                trueLabel="允许"
                falseLabel="不允许"
                ariaLabel="允许用户关闭"
                size="compact"
              />
            </div>
          </div>

          <div className="space-y-1.5">
            <Label htmlFor={`targetUserId-${announcement.id}`}>指定用户（可选）</Label>
            <Select
              name="targetUserId"
              defaultValue={announcement.targetUserId ?? ""}
              disabled={audience !== "SPECIFIC_USER"}
            >
              <SelectTrigger id={`targetUserId-${announcement.id}`} className="w-full">
                <SelectValue>{(value) => getTargetUserLabel(users, value)}</SelectValue>
              </SelectTrigger>
              <SelectContent align="start">
                <SelectItem value="">不指定</SelectItem>
                {users.map((user) => (
                  <SelectItem key={user.id} value={user.id}>
                    {user.email}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>

          <div className="space-y-1.5">
            <Label htmlFor={`body-${announcement.id}`}>内容</Label>
            <Textarea
              id={`body-${announcement.id}`}
              name="body"
              rows={5}
              defaultValue={announcement.body}
              required
            />
          </div>

          <div className="grid gap-3 md:grid-cols-2">
            <div className="space-y-1.5">
              <Label htmlFor={`startAt-${announcement.id}`}>开始时间（可选）</Label>
              <Input
                id={`startAt-${announcement.id}`}
                name="startAt"
                type="datetime-local"
                defaultValue={toDateTimeLocalValue(announcement.startAt)}
              />
            </div>
            <div className="space-y-1.5">
              <Label htmlFor={`endAt-${announcement.id}`}>结束时间（可选）</Label>
              <Input
                id={`endAt-${announcement.id}`}
                name="endAt"
                type="datetime-local"
                defaultValue={toDateTimeLocalValue(announcement.endAt)}
              />
            </div>
          </div>

          <div className="space-y-1.5">
            <Label htmlFor={`sendNotification-${announcement.id}`}>同步发送站内通知</Label>
            <BooleanToggle
              id={`sendNotification-${announcement.id}`}
              name="sendNotification"
              defaultValue={announcement.sendNotification}
              trueLabel="发送"
              falseLabel="不发送"
              ariaLabel="同步发送站内通知"
              size="compact"
            />
          </div>

          <PendingSubmitButton className="h-8 w-full" pendingLabel="保存中...">
            保存修改
          </PendingSubmitButton>
        </form>
        </DialogBody>
      </DialogContent>
    </Dialog>
  );
}

export function CreateAnnouncementButton({
  users,
}: {
  users: AnnouncementOptionUser[];
}) {
  const [open, setOpen] = useState(false);
  const [audience, setAudience] = useState<AnnouncementAudience>("USERS");

  async function handleSubmit(formData: FormData) {
    try {
      await createAnnouncement(formData);
      toast.success("公告已发布");
      setOpen(false);
      setAudience("USERS");
    } catch (error) {
      toast.error(getErrorMessage(error, "发布公告失败"));
    }
  }

  return (
    <Dialog
      open={open}
      onOpenChange={(nextOpen) => {
        if (nextOpen) {
          setAudience("USERS");
        }
        setOpen(nextOpen);
      }}
    >
      <DialogTrigger render={<Button />}>发布公告</DialogTrigger>
      <DialogContent className="flex max-h-[min(90dvh,38rem)] flex-col overflow-hidden p-0 sm:max-w-[30rem]">
        <DialogHeader className="border-b border-border/60 px-4 py-3 pr-10">
          <DialogTitle>发布公告</DialogTitle>
        </DialogHeader>
        <DialogBody className="flex-1 px-4 py-3">
        <form action={handleSubmit} className="space-y-3 text-[12px] leading-5 [&_[data-slot=input]]:!h-8 [&_[data-slot=input]]:!min-h-8 [&_[data-slot=input]]:!px-2.5 [&_[data-slot=input]]:!text-xs [&_[data-slot=label]]:!text-xs [&_[data-slot=select-trigger]]:!h-8 [&_[data-slot=select-trigger]]:!min-h-8 [&_[data-slot=select-trigger]]:!px-2.5 [&_[data-slot=select-trigger]]:!text-xs [&_textarea]:!text-xs">
          <div className="grid gap-3 md:grid-cols-2">
            <div className="space-y-1.5">
              <Label htmlFor="create-announcement-title">标题</Label>
              <Input id="create-announcement-title" name="title" required />
            </div>
            <div className="space-y-1.5">
              <Label htmlFor="create-announcement-audience">目标范围</Label>
              <Select
                name="audience"
                value={audience}
                onValueChange={(value) => setAudience((value ?? "USERS") as AnnouncementAudience)}
              >
                <SelectTrigger id="create-announcement-audience" className="w-full">
                  <SelectValue>{(value) => getAudienceLabel(value)}</SelectValue>
                </SelectTrigger>
                <SelectContent align="start">
                  <SelectItem value="PUBLIC">公开（登录/注册页可见）</SelectItem>
                  <SelectItem value="USERS">全部用户</SelectItem>
                  <SelectItem value="ADMINS">全部管理员</SelectItem>
                  <SelectItem value="SPECIFIC_USER">指定用户</SelectItem>
                </SelectContent>
              </Select>
            </div>
          </div>

          <div className="grid gap-3 md:grid-cols-2">
            <div className="space-y-1.5">
              <Label htmlFor="create-announcement-displayType">展示方式</Label>
              <Select
                name="displayType"
                defaultValue="INLINE"
              >
                <SelectTrigger id="create-announcement-displayType" className="w-full">
                  <SelectValue>{(value) => getDisplayTypeLabel(value)}</SelectValue>
                </SelectTrigger>
                <SelectContent align="start">
                  <SelectItem value="INLINE">普通公告</SelectItem>
                  <SelectItem value="BIG">大公告</SelectItem>
                  <SelectItem value="POPUP">弹窗公告</SelectItem>
                </SelectContent>
              </Select>
            </div>
            <div className="space-y-1.5">
              <Label htmlFor="create-announcement-dismissible">允许用户关闭</Label>
              <BooleanToggle
                id="create-announcement-dismissible"
                name="dismissible"
                defaultValue
                trueLabel="允许"
                falseLabel="不允许"
                ariaLabel="允许用户关闭"
                size="compact"
              />
            </div>
          </div>

          <div className="space-y-1.5">
            <Label htmlFor="create-announcement-targetUserId">指定用户（可选）</Label>
            <Select
              name="targetUserId"
              defaultValue=""
              disabled={audience !== "SPECIFIC_USER"}
            >
              <SelectTrigger id="create-announcement-targetUserId" className="w-full">
                <SelectValue>{(value) => getTargetUserLabel(users, value)}</SelectValue>
              </SelectTrigger>
              <SelectContent align="start">
                <SelectItem value="">不指定</SelectItem>
                {users.map((user) => (
                  <SelectItem key={user.id} value={user.id}>
                    {user.email}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>

          <div className="space-y-1.5">
            <Label htmlFor="create-announcement-body">内容</Label>
            <Textarea id="create-announcement-body" name="body" rows={5} required />
          </div>

          <div className="grid gap-3 md:grid-cols-2">
            <div className="space-y-1.5">
              <Label htmlFor="create-announcement-startAt">开始时间（可选）</Label>
              <Input id="create-announcement-startAt" name="startAt" type="datetime-local" />
            </div>
            <div className="space-y-1.5">
              <Label htmlFor="create-announcement-endAt">结束时间（可选）</Label>
              <Input id="create-announcement-endAt" name="endAt" type="datetime-local" />
            </div>
          </div>

          <div className="space-y-1.5">
            <Label htmlFor="create-announcement-sendNotification">同步发送站内通知</Label>
            <BooleanToggle
              id="create-announcement-sendNotification"
              name="sendNotification"
              defaultValue
              trueLabel="发送"
              falseLabel="不发送"
              ariaLabel="同步发送站内通知"
              size="compact"
            />
          </div>

          <PendingSubmitButton className="h-8 w-full" pendingLabel="发布中...">
            发布
          </PendingSubmitButton>
        </form>
        </DialogBody>
      </DialogContent>
    </Dialog>
  );
}
