"use client";

import { FormEvent, useState } from "react";
import { Pencil, Plus, Power } from "lucide-react";
import { useRouter } from "next/navigation";

import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Dialog } from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import type { ApiResult } from "@/modules/core/server/api";
import type { Permission, RoleDefinition } from "@/modules/core/types";

type PermissionDefinition = {
  id: Permission;
  label: string;
  category: string;
  description: string;
};

type RoleManagementClientProps = {
  permissions: PermissionDefinition[];
};

export function RoleManagementClient({ permissions }: RoleManagementClientProps): React.ReactElement {
  const router = useRouter();
  const [message, setMessage] = useState("");
  const [isPending, setIsPending] = useState(false);

  async function handleSubmit(event: FormEvent<HTMLFormElement>): Promise<void> {
    event.preventDefault();
    setMessage("");
    setIsPending(true);
    const formData = new FormData(event.currentTarget);
    const response = await fetch("/api/settings/roles", {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({
        label: String(formData.get("label") ?? ""),
        key: String(formData.get("key") ?? ""),
        description: String(formData.get("description") ?? ""),
        permissions: formData.getAll("permissions").map(String),
      }),
    });
    const result = (await response.json()) as ApiResult<{ role: RoleDefinition }>;
    setIsPending(false);

    if (!result.success) {
      setMessage(result.reason);
      return;
    }

    setMessage(result.reason);
    event.currentTarget.reset();
    router.refresh();
  }

  return (
    <Card>
      <CardHeader>
        <CardTitle>新增角色</CardTitle>
        <CardDescription>角色由系统注册权限点组合而成。</CardDescription>
      </CardHeader>
      <CardContent>
        <form className="grid gap-4" onSubmit={handleSubmit}>
          <div className="grid gap-3 md:grid-cols-3">
            <Input name="label" placeholder="角色名称" required />
            <Input name="key" placeholder="角色标识，可留空" />
            <Input name="description" placeholder="角色说明" />
          </div>
          <div className="grid gap-2 sm:grid-cols-2 xl:grid-cols-3">
            {permissions.map((permission) => (
              <label className="flex items-start gap-2 rounded-md border p-3 text-sm" key={permission.id}>
                <input className="mt-1" name="permissions" type="checkbox" value={permission.id} />
                <span>
                  <span className="block font-medium">{permission.label}</span>
                  <span className="block text-xs text-muted-foreground">{permission.id}</span>
                </span>
              </label>
            ))}
          </div>
          <Button className="w-fit" disabled={isPending} type="submit">
            <Plus className="size-4" aria-hidden="true" />
            新增角色
          </Button>
        </form>
        {message ? (
          <p className="mt-3 rounded-md bg-secondary px-3 py-2 text-sm text-secondary-foreground" role="status">
            {message}
          </p>
        ) : null}
      </CardContent>
    </Card>
  );
}

type RoleRowActionsProps = {
  permissions: PermissionDefinition[];
  role: RoleDefinition;
};

export function RoleRowActions({ permissions, role }: RoleRowActionsProps): React.ReactElement {
  const router = useRouter();
  const [isEditOpen, setIsEditOpen] = useState(false);
  const [message, setMessage] = useState("");
  const [isPending, setIsPending] = useState(false);

  async function updateRole(payload: Record<string, string | boolean | string[]>): Promise<void> {
    setMessage("");
    setIsPending(true);
    const response = await fetch(`/api/settings/roles/${role.id}`, {
      method: "PATCH",
      headers: { "content-type": "application/json" },
      body: JSON.stringify(payload),
    });
    const result = (await response.json()) as ApiResult<{ role: RoleDefinition }>;
    setIsPending(false);

    if (!result.success) {
      setMessage(result.reason);
      return;
    }

    setMessage(result.reason);
    setIsEditOpen(false);
    router.refresh();
  }

  async function disableRole(): Promise<void> {
    setMessage("");
    setIsPending(true);
    const response = await fetch(`/api/settings/roles/${role.id}`, {
      method: "DELETE",
    });
    const result = (await response.json()) as ApiResult<{ role: RoleDefinition }>;
    setIsPending(false);

    if (!result.success) {
      setMessage(result.reason);
      return;
    }

    router.refresh();
  }

  async function handleSubmit(event: FormEvent<HTMLFormElement>): Promise<void> {
    event.preventDefault();
    const formData = new FormData(event.currentTarget);
    await updateRole({
      label: String(formData.get("label") ?? ""),
      key: String(formData.get("key") ?? ""),
      description: String(formData.get("description") ?? ""),
      isEnabled: String(formData.get("isEnabled") ?? "") === "true",
      permissions: formData.getAll("permissions").map(String),
    });
  }

  if (role.isSystem) {
    return <span className="block text-right text-xs text-muted-foreground">内置只读</span>;
  }

  return (
    <div className="flex items-center justify-end gap-2">
      <Button onClick={() => setIsEditOpen(true)} size="sm" type="button" variant="outline">
        <Pencil className="size-4" aria-hidden="true" />
        编辑
      </Button>
      {role.isEnabled ? (
        <Button disabled={isPending} onClick={() => void disableRole()} size="sm" type="button" variant="destructive">
          <Power className="size-4" aria-hidden="true" />
          停用
        </Button>
      ) : (
        <Button
          disabled={isPending}
          onClick={() => void updateRole({ isEnabled: true })}
          size="sm"
          type="button"
          variant="outline"
        >
          <Power className="size-4" aria-hidden="true" />
          启用
        </Button>
      )}
      <Dialog
        description="编辑自定义角色的名称、说明、状态和权限点。"
        onClose={() => setIsEditOpen(false)}
        open={isEditOpen}
        title="编辑角色"
      >
        <form className="grid gap-4" onSubmit={handleSubmit}>
          <div className="grid gap-3 md:grid-cols-2">
            <label className="grid gap-2 text-sm">
              <span className="font-medium">角色名称</span>
              <Input defaultValue={role.label} name="label" required />
            </label>
            <label className="grid gap-2 text-sm">
              <span className="font-medium">角色标识</span>
              <Input defaultValue={role.key} name="key" required />
            </label>
          </div>
          <label className="grid gap-2 text-sm">
            <span className="font-medium">角色说明</span>
            <Input defaultValue={role.description} name="description" />
          </label>
          <label className="grid gap-2 text-sm">
            <span className="font-medium">状态</span>
            <select
              className="h-11 w-full rounded-md border bg-background px-3 text-sm outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring"
              defaultValue={String(role.isEnabled)}
              name="isEnabled"
            >
              <option value="true">启用</option>
              <option value="false">停用</option>
            </select>
          </label>
          <div className="grid gap-2 sm:grid-cols-2 xl:grid-cols-3">
            {permissions.map((permission) => (
              <label className="flex items-start gap-2 rounded-md border p-3 text-sm" key={permission.id}>
                <input
                  className="mt-1"
                  defaultChecked={role.permissions.includes(permission.id)}
                  name="permissions"
                  type="checkbox"
                  value={permission.id}
                />
                <span>
                  <span className="block font-medium">{permission.label}</span>
                  <span className="block text-xs text-muted-foreground">{permission.id}</span>
                </span>
              </label>
            ))}
          </div>
          {message ? (
            <p className="rounded-md bg-secondary px-3 py-2 text-sm text-secondary-foreground" role="status">
              {message}
            </p>
          ) : null}
          <div className="flex justify-end gap-2">
            <Button onClick={() => setIsEditOpen(false)} type="button" variant="outline">
              取消
            </Button>
            <Button disabled={isPending} type="submit">
              保存
            </Button>
          </div>
        </form>
      </Dialog>
    </div>
  );
}
