"use client";

import { FormEvent, useMemo, useState } from "react";
import { Check, Plus, X } from "lucide-react";
import { useRouter } from "next/navigation";

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

type UserManagementClientProps = {
  organizations: Organization[];
  roles: RoleDefinition[];
  joinRequests: JoinRequest[];
};

function getOrganizationRoles(roles: RoleDefinition[], organizationId: string): RoleDefinition[] {
  return roles.filter((role) => role.scope === "organization" && role.organizationId === organizationId && role.isEnabled);
}

function getDefaultOrganizationId(organizations: Organization[]): string {
  return organizations[0]?.id ?? "";
}

export function UserManagementClient({
  organizations,
  roles,
  joinRequests,
}: UserManagementClientProps): React.ReactElement {
  const router = useRouter();
  const [selectedOrganizationId, setSelectedOrganizationId] = useState(() => getDefaultOrganizationId(organizations));
  const [message, setMessage] = useState("");
  const [isPending, setIsPending] = useState(false);

  const organizationRoles = useMemo(
    () => getOrganizationRoles(roles, selectedOrganizationId),
    [roles, selectedOrganizationId],
  );
  const pendingJoinRequests = joinRequests.filter((request) => request.status === "pending");

  async function handleCreateAccount(event: FormEvent<HTMLFormElement>): Promise<void> {
    event.preventDefault();
    setMessage("");
    setIsPending(true);

    const formData = new FormData(event.currentTarget);
    const response = await fetch("/api/settings/accounts", {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({
        organizationId: String(formData.get("organizationId") ?? ""),
        roleId: String(formData.get("roleId") ?? ""),
        name: String(formData.get("name") ?? ""),
        email: String(formData.get("email") ?? ""),
        password: String(formData.get("password") ?? ""),
      }),
    });
    const result = (await response.json()) as ApiResult<{ account: unknown }>;
    setIsPending(false);

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

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

  async function reviewJoinRequest(requestId: string, decision: "approved" | "rejected", roleId: string): Promise<void> {
    setMessage("");
    setIsPending(true);
    const response = await fetch(`/api/settings/join-requests/${requestId}`, {
      method: "PATCH",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ decision, roleId }),
    });
    const result = (await response.json()) as ApiResult<{ joinRequest: unknown }>;
    setIsPending(false);

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

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

  return (
    <section className="grid gap-4 xl:grid-cols-[0.9fr_1.1fr]">
      <Card>
        <CardHeader>
          <CardTitle>创建机构用户</CardTitle>
          <CardDescription>管理员创建账号后立即分配到机构和角色。</CardDescription>
        </CardHeader>
        <CardContent>
          <form className="grid gap-3" onSubmit={handleCreateAccount}>
            <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"
                name="organizationId"
                onChange={(event) => setSelectedOrganizationId(event.target.value)}
                value={selectedOrganizationId}
              >
                {organizations.map((organization) => (
                  <option key={organization.id} value={organization.id}>
                    {organization.name}
                  </option>
                ))}
              </select>
            </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"
                name="roleId"
                required
              >
                {organizationRoles.map((role) => (
                  <option key={role.id} value={role.id}>
                    {role.label}
                  </option>
                ))}
              </select>
            </label>

            <label className="grid gap-2 text-sm">
              <span className="font-medium">姓名</span>
              <Input name="name" required />
            </label>
            <label className="grid gap-2 text-sm">
              <span className="font-medium">邮箱</span>
              <Input name="email" required type="email" />
            </label>
            <label className="grid gap-2 text-sm">
              <span className="font-medium">初始密码</span>
              <Input minLength={6} name="password" required type="password" />
            </label>

            <Button disabled={isPending || organizationRoles.length === 0} 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>

      <Card>
        <CardHeader>
          <CardTitle>加入申请审批</CardTitle>
          <CardDescription>公开注册选择机构后进入这里审批。</CardDescription>
        </CardHeader>
        <CardContent className="space-y-3">
          {pendingJoinRequests.map((request) => {
            const requestRoles = getOrganizationRoles(roles, request.organizationId);
            const defaultRoleId = requestRoles.find((role) => role.key === "caregiver")?.id ?? requestRoles[0]?.id ?? "";

            return (
              <div key={request.id} className="rounded-md border p-3">
                <div className="flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between">
                  <div>
                    <p className="font-medium">{request.accountName}</p>
                    <p className="text-xs text-muted-foreground">{request.accountEmail}</p>
                    <p className="mt-2 text-sm text-muted-foreground">{request.organizationName}</p>
                  </div>
                  <Badge variant="warning">待审批</Badge>
                </div>
                <div className="mt-3 grid gap-2 sm:grid-cols-[1fr_auto_auto]">
                  <select
                    className="h-10 w-full rounded-md border bg-background px-3 text-sm outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring"
                    defaultValue={defaultRoleId}
                    id={`role-${request.id}`}
                  >
                    {requestRoles.map((role) => (
                      <option key={role.id} value={role.id}>
                        {role.label}
                      </option>
                    ))}
                  </select>
                  <Button
                    disabled={isPending || !defaultRoleId}
                    onClick={() => {
                      const element = document.getElementById(`role-${request.id}`);
                      const roleId = element instanceof HTMLSelectElement ? element.value : defaultRoleId;
                      void reviewJoinRequest(request.id, "approved", roleId);
                    }}
                    size="sm"
                    type="button"
                  >
                    <Check className="size-4" aria-hidden="true" />
                    通过
                  </Button>
                  <Button
                    disabled={isPending}
                    onClick={() => void reviewJoinRequest(request.id, "rejected", "")}
                    size="sm"
                    type="button"
                    variant="outline"
                  >
                    <X className="size-4" aria-hidden="true" />
                    拒绝
                  </Button>
                </div>
              </div>
            );
          })}
          {pendingJoinRequests.length === 0 ? <p className="text-sm text-muted-foreground">暂无待审批申请</p> : null}
        </CardContent>
      </Card>
    </section>
  );
}
