import Link from "next/link";
import { and, asc, eq, inArray } from "drizzle-orm";
import { requireSession } from "@/lib/auth";
import { accountScope, usersWithData } from "@/lib/accounts";
import { departmentPaths } from "@/lib/rbac";
import { db } from "@/db";
import { users, userTerritories, territories, departments } from "@/db/schema";
import { PageHeader, EmptyState } from "@/components/ui";
import { formatDateTime } from "@/lib/format";
import { CreateUserForm, UserTable, type UserRow, type DepartmentOption } from "./user-forms";
import {
  toggleUserActiveAction,
  toggleUserCanUploadDocumentsAction,
  toggleCanEditStaffInfoAction,
  toggleCanPostAnnouncementsAction,
  unlockUserLoginAction,
  deleteUserAction,
} from "./actions";

export const dynamic = "force-dynamic";

export default async function UsersPage() {
  const session = await requireSession();

  // Ban giám đốc quản lý mọi tài khoản; Giám đốc khu vực / Quản lý quản lý cấp dưới trong nhánh mình (cha–con).
  const scope = await accountScope(session);
  if (!scope) {
    return (
      <>
        <PageHeader title="Người dùng & phân quyền" />
        <EmptyState
          message="Bạn không có quyền quản trị người dùng."
          hint="Dành cho Ban giám đốc, và Giám đốc khu vực / Quản lý đã được gán phòng ban (quản lý cấp dưới trong nhánh của mình)."
        />
      </>
    );
  }
  const NONE = ["00000000-0000-0000-0000-000000000000"];

  const [userRows, territoryRows, departmentRows, assignments] = await Promise.all([
    db
      .select({
        id: users.id,
        email: users.email,
        fullName: users.fullName,
        phone: users.phone,
        jobTitle: users.jobTitle,
        role: users.role,
        territoryId: users.territoryId,
        departmentId: users.departmentId,
        isActive: users.isActive,
        canUploadDocuments: users.canUploadDocuments,
        canEditStaffInfo: users.canEditStaffInfo,
        canPostAnnouncements: users.canPostAnnouncements,
        birthDate: users.birthDate,
        gender: users.gender,
        lastLoginAt: users.lastLoginAt,
        lockedUntil: users.lockedUntil,
      })
      .from(users)
      .where(
        and(
          eq(users.tenantId, session.tenantId),
          scope.all ? undefined : inArray(users.id, scope.userIds.length > 0 ? scope.userIds : NONE),
        ),
      )
      .orderBy(asc(users.role), asc(users.fullName)),
    db
      .select({ id: territories.id, name: territories.name, level: territories.level })
      .from(territories)
      .where(
        and(
          eq(territories.tenantId, session.tenantId),
          eq(territories.isActive, true),
          // Chỉ cho gán tới cấp tỉnh/thành trở lên; gán tới phường là quá chi tiết
          // và làm danh sách chọn dài không dùng được.
          inArray(territories.level, ["REGION", "PROVINCE"]),
          scope.all ? undefined : inArray(territories.id, scope.territoryIds.length > 0 ? scope.territoryIds : NONE),
        ),
      )
      .orderBy(asc(territories.code)),
    db
      .select({
        id: departments.id,
        name: departments.name,
        parentId: departments.parentId,
      })
      .from(departments)
      .where(
        and(
          eq(departments.tenantId, session.tenantId),
          eq(departments.isActive, true),
          scope.all ? undefined : inArray(departments.id, scope.departmentIds),
        ),
      )
      .orderBy(asc(departments.sortOrder), asc(departments.code)),
    db
      .select({ userId: userTerritories.userId, territoryId: userTerritories.territoryId })
      .from(userTerritories)
      .where(eq(userTerritories.tenantId, session.tenantId)),
  ]);

  /* Làm phẳng cây phòng ban thành danh sách có độ sâu, để ô chọn hiển thị thụt lề
     theo cấp mà không cần component cây riêng. */
  const departmentOptions: DepartmentOption[] = [];
  const walkDepartments = (parentId: string | null, depth: number) => {
    for (const node of departmentRows.filter((d) => d.parentId === parentId)) {
      departmentOptions.push({ id: node.id, name: node.name, depth });
      walkDepartments(node.id, depth + 1);
    }
  };
  // Quản lý chỉ thấy nhánh của mình nên gốc của nhánh không có cha trong danh sách — coi là gốc.
  const knownDepartmentIds = new Set(departmentRows.map((d) => d.id));
  for (const root of departmentRows.filter((d) => !d.parentId || !knownDepartmentIds.has(d.parentId))) {
    departmentOptions.push({ id: root.id, name: root.name, depth: 0 });
    walkDepartments(root.id, 1);
  }

  const managedByUser = new Map<string, string[]>();
  for (const row of assignments) {
    const list = managedByUser.get(row.userId) ?? [];
    list.push(row.territoryId);
    managedByUser.set(row.userId, list);
  }

  const rows: UserRow[] = userRows.map((user) => ({
    id: user.id,
    email: user.email,
    fullName: user.fullName,
    phone: user.phone,
    jobTitle: user.jobTitle,
    role: user.role,
    territoryId: user.territoryId,
    departmentId: user.departmentId,
    managedTerritoryIds: managedByUser.get(user.id) ?? [],
    birthDate: user.birthDate,
    gender: user.gender,
    lastLoginAt: user.lastLoginAt ? formatDateTime(user.lastLoginAt) : null,
  }));

  const territoryNames = Object.fromEntries(territoryRows.map((t) => [t.id, t.name]));
  // Hiển thị đủ cấp "Phòng › Team" thay vì chỉ tên team.
  const paths = await departmentPaths(session.tenantId);
  const departmentNames = Object.fromEntries(departmentRows.map((d) => [d.id, paths.get(d.id) ?? d.name]));
  // Chỉ tài khoản chưa từng đăng nhập và chưa có dữ liệu nghiệp vụ mới xoá được (tạo nhầm); còn lại dùng "Khoá".
  const withData = await usersWithData(userRows.map((u) => u.id));
  const deletableMap = Object.fromEntries(
    userRows.map((u) => [u.id, !u.lastLoginAt && !withData.has(u.id) && u.id !== session.userId]),
  );
  const activeMap = Object.fromEntries(userRows.map((u) => [u.id, u.isActive]));
  // Đang bị tạm khoá đăng nhập do nhập sai mật khẩu nhiều lần (khác với việc Ban giám đốc chủ động khoá tài khoản).
  const now = Date.now();
  const lockedMap = Object.fromEntries(userRows.map((u) => [u.id, !!u.lockedUntil && u.lockedUntil.getTime() > now]));
  const canUploadDocumentsMap = Object.fromEntries(userRows.map((u) => [u.id, u.canUploadDocuments]));
  const canEditStaffInfoMap = Object.fromEntries(userRows.map((u) => [u.id, u.canEditStaffInfo]));
  const canPostAnnouncementsMap = Object.fromEntries(userRows.map((u) => [u.id, u.canPostAnnouncements]));

  return (
    <>
      <PageHeader
        title="Người dùng & phân quyền"
        subtitle={
          scope.all
            ? "Vai trò quyết định mức quyền, phòng ban quyết định phạm vi dữ liệu: Ban giám đốc thấy toàn công ty, Quản lý thấy nhánh phòng ban mình phụ trách, NVKD chỉ thấy khách hàng mình phụ trách."
            : "Bạn quản lý các tài khoản cấp dưới trong nhánh mình phụ trách: tạo, sửa, điều chuyển trong nhánh, khoá/mở khoá, cấp lại mật khẩu. Chỉ gán được vai trò thấp hơn vai trò của bạn và chỉ cấp được quyền mà chính bạn đang có."
        }
        actions={
          <Link href="/danh-muc" className="btn-ghost">
            ← Danh mục
          </Link>
        }
      />

      <div className="flex flex-col gap-5">
        <CreateUserForm
          territories={territoryRows}
          departments={departmentOptions}
          allowedRoles={scope.assignableRoles}
          requireDepartment={!scope.all}
        />

        <UserTable
          users={rows}
          territories={territoryRows}
          departments={departmentOptions}
          territoryNames={territoryNames}
          departmentNames={departmentNames}
          currentUserId={session.userId}
          activeMap={activeMap}
          onToggleActive={toggleUserActiveAction}
          lockedMap={lockedMap}
          onUnlockLogin={unlockUserLoginAction}
          canUploadDocumentsMap={canUploadDocumentsMap}
          onToggleCanUploadDocuments={toggleUserCanUploadDocumentsAction}
          canEditStaffInfoMap={canEditStaffInfoMap}
          onToggleCanEditStaffInfo={toggleCanEditStaffInfoAction}
          canPostAnnouncementsMap={canPostAnnouncementsMap}
          onToggleCanPostAnnouncements={toggleCanPostAnnouncementsAction}
          canGrantPostAnnouncements={scope.holdsPostAnnouncements}
          onDelete={deleteUserAction}
          deletableMap={deletableMap}
          allowedRoles={scope.assignableRoles}
          canGrantUploadDocuments={scope.holdsUploadDocuments}
          canGrantEditStaffInfo={scope.holdsEditStaffInfo}
        />
      </div>

      <p className="mt-4 text-xs text-ink-400">
        Khoá tài khoản có hiệu lực ngay lập tức — phiên đăng nhập được đối chiếu lại với cơ sở dữ liệu
        ở mỗi lần truy cập, không phải chờ hết hạn.
      </p>
    </>
  );
}
