import {
  createUserAction,
  removeProjectUserAction,
  resetUserPasswordAction,
  savePermissionOverridesAction,
  saveProjectUserAction,
  updateUserAction
} from "@/app/actions";
import { AppShell } from "@/components/AppShell";
import { DeleteButton } from "@/components/DeleteButton";
import { EmptyState } from "@/components/EmptyState";
import { PageHeader } from "@/components/PageHeader";
import { StatusMessage } from "@/components/StatusMessage";
import { shortDate } from "@/lib/format";
import {
  overrideLabels,
  permissionGroups,
  projectUserStatusLabels,
  roleLabels,
  rolePermissionDefaults,
  userStatusLabels
} from "@/lib/permissions";
import { getSelectedProject } from "@/lib/projects";
import { prisma } from "@/lib/prisma";

const roleOptions = Object.entries(roleLabels);
const userStatusOptions = Object.entries(userStatusLabels);
const projectUserStatusOptions = Object.entries(projectUserStatusLabels);
const overrideOptions = Object.entries(overrideLabels);

export default async function UsersPermissionsPage({
  searchParams
}: {
  searchParams?: Promise<Record<string, string | string[] | undefined>>;
}) {
  const params = (await searchParams) ?? {};
  const selected = typeof params.projectId === "string" ? params.projectId : undefined;
  const { user, projects, project, permissions, projectRole } = await getSelectedProject(selected, "users.view");

  if (!project) {
    return (
      <AppShell projects={projects} username={user.name ?? user.username ?? user.email} role={projectRole ?? user.role} permissions={permissions}>
        <EmptyState title="Create a project before managing users." href="/projects" actionLabel="Create project" />
      </AppShell>
    );
  }

  const canCreateUsers = Boolean(permissions?.["users.create"]);
  const canEditUsers = Boolean(permissions?.["users.edit"]);
  const canResetPasswords = Boolean(permissions?.["users.resetPassword"]);
  const canDisableUsers = Boolean(permissions?.["users.disable"]);
  const canManagePermissions = Boolean(permissions?.["users.managePermissions"]);
  const canViewAudit = Boolean(permissions?.["audit.view"]);

  const users = await prisma.user.findMany({
    include: {
      projectUsers: {
        where: { projectId: project.id },
        include: { overrides: true }
      }
    },
    orderBy: [{ status: "asc" }, { name: "asc" }, { username: "asc" }]
  });
  const projectUsers = users.flatMap((item) => item.projectUsers);
  const assignedUserIds = new Set(projectUsers.map((projectUser) => projectUser.userId));
  const unassignedUsers = users.filter((item) => !assignedUserIds.has(item.id));
  const auditLogs = canViewAudit
    ? await prisma.auditLog.findMany({
        where: { projectId: project.id },
        include: { user: true },
        orderBy: { createdAt: "desc" },
        take: 50
      })
    : [];

  return (
    <AppShell projects={projects} selectedProjectId={project.id} username={user.name ?? user.username ?? user.email} role={projectRole ?? user.role} permissions={permissions}>
      <PageHeader
        title="Users & Permissions"
        description="Assign users to this project, choose their role, and apply project-specific allow/deny overrides."
      />
      <StatusMessage updated={params.updated} deleted={params.deleted} error={params.error} />

      <section className="grid gap-6 xl:grid-cols-[0.8fr_1.2fr]">
        {canCreateUsers ? (
          <form action={createUserAction} className="panel grid gap-4 p-4">
            <h3 className="font-semibold text-ink">Create User</h3>
            <input type="hidden" name="projectId" value={project.id} />
            <div className="grid gap-4 md:grid-cols-2">
              <label className="grid gap-2">
                <span className="label">Full name</span>
                <input className="field" name="name" />
              </label>
              <label className="grid gap-2">
                <span className="label">Email</span>
                <input className="field" name="email" type="email" />
              </label>
            </div>
            <div className="grid gap-4 md:grid-cols-2">
              <label className="grid gap-2">
                <span className="label">Username</span>
                <input className="field" name="username" />
              </label>
              <label className="grid gap-2">
                <span className="label">Phone</span>
                <input className="field" name="phone" />
              </label>
            </div>
            <div className="grid gap-4 md:grid-cols-2">
              <label className="grid gap-2">
                <span className="label">Temporary password</span>
                <input className="field" name="password" type="password" required />
              </label>
              <label className="grid gap-2">
                <span className="label">User status</span>
                <select className="field" name="status" defaultValue="ACTIVE">
                  {userStatusOptions.map(([value, label]) => (
                    <option key={value} value={value}>{label}</option>
                  ))}
                </select>
              </label>
            </div>
            <div className="grid gap-4 md:grid-cols-2">
              <label className="grid gap-2">
                <span className="label">Global role</span>
                <select className="field" name="globalRole" defaultValue="VIEWER">
                  {roleOptions.map(([value, label]) => (
                    <option key={value} value={value}>{label}</option>
                  ))}
                </select>
              </label>
              <label className="grid gap-2">
                <span className="label">Role for {project.name}</span>
                <select className="field" name="projectRole" defaultValue="VIEWER">
                  {roleOptions.map(([value, label]) => (
                    <option key={value} value={value}>{label}</option>
                  ))}
                </select>
              </label>
            </div>
            <textarea className="field min-h-20" name="notes" placeholder="Notes" />
            <button className="btn-primary">Create user</button>
          </form>
        ) : null}

        <div className="panel overflow-hidden">
          <div className="border-b border-line px-4 py-3">
            <h3 className="font-semibold text-ink">Project Access</h3>
          </div>
          <div className="overflow-x-auto">
            <table className="w-full min-w-[860px]">
              <thead className="table-head">
                <tr>
                  <th className="px-3 py-2">User</th>
                  <th className="px-3 py-2">Project role</th>
                  <th className="px-3 py-2">Project status</th>
                  <th className="px-3 py-2">Last login</th>
                  <th className="px-3 py-2">Overrides</th>
                </tr>
              </thead>
              <tbody>
                {projectUsers.map((projectUser) => {
                  const account = users.find((item) => item.id === projectUser.userId);
                  if (!account) return null;
                  return (
                    <tr key={projectUser.id}>
                      <td className="table-cell">
                        <div className="font-medium text-ink">{account.name ?? account.username ?? account.email ?? "Unnamed user"}</div>
                        <div className="text-xs text-slate-500">{account.email ?? account.username ?? account.phone ?? "-"}</div>
                      </td>
                      <td className="table-cell">{roleLabels[projectUser.role]}</td>
                      <td className="table-cell">{projectUserStatusLabels[projectUser.status]}</td>
                      <td className="table-cell">{shortDate(account.lastLoginAt)}</td>
                      <td className="table-cell">{projectUser.overrides.length}</td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
            {projectUsers.length === 0 ? <div className="p-6 text-sm text-slate-600">No users are assigned to this project yet.</div> : null}
          </div>
        </div>
      </section>

      {canManagePermissions && unassignedUsers.length > 0 ? (
        <section className="panel mt-6 p-4">
          <h3 className="font-semibold text-ink">Assign Existing User</h3>
          <form action={saveProjectUserAction} className="mt-3 grid gap-3 md:grid-cols-[1fr_180px_180px_auto]">
            <input type="hidden" name="projectId" value={project.id} />
            <select className="field" name="userId" required>
              {unassignedUsers.map((item) => (
                <option key={item.id} value={item.id}>{item.name ?? item.username ?? item.email ?? item.id}</option>
              ))}
            </select>
            <select className="field" name="role" defaultValue="VIEWER">
              {roleOptions.map(([value, label]) => (
                <option key={value} value={value}>{label}</option>
              ))}
            </select>
            <select className="field" name="status" defaultValue="ACTIVE">
              {projectUserStatusOptions.map(([value, label]) => (
                <option key={value} value={value}>{label}</option>
              ))}
            </select>
            <button className="btn-primary">Assign</button>
          </form>
        </section>
      ) : null}

      <section className="mt-6 grid gap-4">
        {users.map((account) => {
          const assignment = account.projectUsers[0];
          return (
            <details key={account.id} className="panel p-4">
              <summary className="cursor-pointer list-none">
                <div className="flex flex-col gap-2 md:flex-row md:items-center md:justify-between">
                  <div>
                    <h3 className="font-semibold text-ink">{account.name ?? account.username ?? account.email ?? "Unnamed user"}</h3>
                    <p className="text-sm text-slate-600">{account.email ?? account.username ?? "No email or username"} · {userStatusLabels[account.status]}</p>
                  </div>
                  <span className="inline-flex rounded-md bg-slate-100 px-2 py-1 text-xs font-semibold text-slate-700">
                    {assignment ? roleLabels[assignment.role] : "No project access"}
                  </span>
                </div>
              </summary>

              <div className="mt-4 grid gap-6 xl:grid-cols-2">
                {canEditUsers ? (
                  <form action={updateUserAction} className="grid gap-3">
                    <h4 className="font-medium text-ink">User Profile</h4>
                    <input type="hidden" name="projectId" value={project.id} />
                    <input type="hidden" name="userId" value={account.id} />
                    <input className="field" name="name" defaultValue={account.name ?? ""} placeholder="Full name" />
                    <input className="field" name="email" type="email" defaultValue={account.email ?? ""} placeholder="Email" />
                    <input className="field" name="username" defaultValue={account.username ?? ""} placeholder="Username" />
                    <input className="field" name="phone" defaultValue={account.phone ?? ""} placeholder="Phone" />
                    <select className="field" name="globalRole" defaultValue={account.role}>
                      {roleOptions.map(([value, label]) => (
                        <option key={value} value={value}>{label}</option>
                      ))}
                    </select>
                    <select className="field" name="status" defaultValue={account.status}>
                      {userStatusOptions.map(([value, label]) => (
                        <option key={value} value={value}>{label}</option>
                      ))}
                    </select>
                    <textarea className="field min-h-20" name="notes" defaultValue={account.notes ?? ""} />
                    <button className="btn-primary">Save profile</button>
                  </form>
                ) : null}

                <div className="grid gap-4">
                  {canManagePermissions ? (
                    <form action={saveProjectUserAction} className="grid gap-3">
                      <h4 className="font-medium text-ink">Project Role</h4>
                      <input type="hidden" name="projectId" value={project.id} />
                      <input type="hidden" name="userId" value={account.id} />
                      <select className="field" name="role" defaultValue={assignment?.role ?? "VIEWER"}>
                        {roleOptions.map(([value, label]) => (
                          <option key={value} value={value}>{label}</option>
                        ))}
                      </select>
                      <select className="field" name="status" defaultValue={assignment?.status ?? "ACTIVE"}>
                        {projectUserStatusOptions.map(([value, label]) => (
                          <option key={value} value={value}>{label}</option>
                        ))}
                      </select>
                      <textarea className="field min-h-20" name="notes" defaultValue={assignment?.notes ?? ""} placeholder="Project access notes" />
                      <button className="btn-primary">Save project role</button>
                    </form>
                  ) : null}

                  {canResetPasswords ? (
                    <form action={resetUserPasswordAction} className="grid gap-3">
                      <h4 className="font-medium text-ink">Reset Password</h4>
                      <input type="hidden" name="projectId" value={project.id} />
                      <input type="hidden" name="userId" value={account.id} />
                      <input className="field" name="password" type="password" placeholder="New password" required />
                      <button className="btn-secondary">Reset password</button>
                    </form>
                  ) : null}

                  {canDisableUsers && assignment ? (
                    <form action={removeProjectUserAction}>
                      <input type="hidden" name="projectId" value={project.id} />
                      <input type="hidden" name="projectUserId" value={assignment.id} />
                      <DeleteButton label="Remove from project" message="Remove this user's access to this project?" />
                    </form>
                  ) : null}
                </div>
              </div>

              {canManagePermissions && assignment ? (
                <form action={savePermissionOverridesAction} className="mt-6 grid gap-4">
                  <input type="hidden" name="projectId" value={project.id} />
                  <input type="hidden" name="projectUserId" value={assignment.id} />
                  <div className="flex flex-col gap-2 md:flex-row md:items-center md:justify-between">
                    <h4 className="font-medium text-ink">Permission Overrides</h4>
                    <input className="field md:max-w-xs" type="search" placeholder="Search permissions" />
                  </div>
                  {permissionGroups.map((group) => (
                    <div key={group.label} className="rounded-md border border-line">
                      <div className="border-b border-line bg-slate-50 px-3 py-2 text-sm font-semibold text-ink">{group.label}</div>
                      <div className="grid gap-0">
                        {group.permissions.map((permission) => {
                          const override = assignment.overrides.find((item) => item.permissionKey === permission.key)?.value ?? "DEFAULT";
                          const roleDefault = rolePermissionDefaults[assignment.role][permission.key];
                          return (
                            <label key={permission.key} className="grid gap-2 border-b border-line px-3 py-2 last:border-b-0 md:grid-cols-[1fr_160px_180px] md:items-center">
                              <span>
                                <span className="block text-sm font-medium text-ink">{permission.label}</span>
                                <span className="text-xs text-slate-500">{permission.key}</span>
                              </span>
                              <span className={`text-xs font-semibold ${roleDefault ? "text-emerald-700" : "text-slate-500"}`}>
                                Default: {roleDefault ? "Allowed" : "Denied"}
                              </span>
                              <select className="field" name={`override:${permission.key}`} defaultValue={override}>
                                {overrideOptions.map(([value, label]) => (
                                  <option key={value} value={value}>{label}</option>
                                ))}
                              </select>
                            </label>
                          );
                        })}
                      </div>
                    </div>
                  ))}
                  <button className="btn-primary">Save permission overrides</button>
                </form>
              ) : null}
            </details>
          );
        })}
      </section>

      {canViewAudit ? (
        <section className="panel mt-6 overflow-hidden">
          <div className="border-b border-line px-4 py-3">
            <h3 className="font-semibold text-ink">Audit Log</h3>
          </div>
          <div className="overflow-x-auto">
            <table className="w-full min-w-[760px]">
              <thead className="table-head">
                <tr>
                  <th className="px-3 py-2">When</th>
                  <th className="px-3 py-2">User</th>
                  <th className="px-3 py-2">Action</th>
                  <th className="px-3 py-2">Entity</th>
                </tr>
              </thead>
              <tbody>
                {auditLogs.map((log) => (
                  <tr key={log.id}>
                    <td className="table-cell">{shortDate(log.createdAt)}</td>
                    <td className="table-cell">{log.user?.name ?? log.user?.username ?? log.user?.email ?? "-"}</td>
                    <td className="table-cell">{log.action}</td>
                    <td className="table-cell">{log.entityType}{log.entityId ? ` · ${log.entityId}` : ""}</td>
                  </tr>
                ))}
              </tbody>
            </table>
            {auditLogs.length === 0 ? <div className="p-6 text-sm text-slate-600">No audit records for this project yet.</div> : null}
          </div>
        </section>
      ) : null}
    </AppShell>
  );
}
