import { and, eq } from "drizzle-orm";

import { jsonFailure, jsonSuccess, readJsonBody } from "@/modules/core/server/api";
import { hashPassword, normalizeEmail, requirePermission, toPublicAccount } from "@/modules/core/server/auth";
import { recordAuditLog } from "@/modules/core/server/audit";
import { getDatabase } from "@/modules/core/server/db";
import { getRoleDefinitions, hasPermission } from "@/modules/core/server/permissions";
import { accounts, memberships, organizations, roles } from "@/modules/core/server/schema";
import {
  listSettingsAccounts,
  listSettingsMemberships,
  listSettingsOrganizations,
} from "@/modules/core/server/settings";

function isRecord(value: unknown): value is Record<string, unknown> {
  return typeof value === "object" && value !== null && !Array.isArray(value);
}

function readString(source: Record<string, unknown>, key: string): string {
  const value = source[key];
  return typeof value === "string" ? value.trim() : "";
}

export async function GET(): Promise<Response> {
  const auth = await requirePermission("account:read", {
    action: "account.list",
    targetType: "account",
  });

  if (!auth.success) {
    return auth.response;
  }

  const canReadAllAccounts = Boolean(auth.context.account.platformRoleId) || hasPermission(auth.context.permissions, "platform:manage");
  const organizationId = canReadAllAccounts ? undefined : auth.context.organization?.id;
  const [accountRows, membershipRows, organizationRows, roleDefinitions] = await Promise.all([
    listSettingsAccounts(organizationId ? { organizationId } : {}),
    listSettingsMemberships(organizationId ? { organizationId } : {}),
    listSettingsOrganizations(organizationId ? { organizationId } : {}),
    getRoleDefinitions(auth.context.organization?.id),
  ]);
  const roleById = new Map(roleDefinitions.map((role) => [role.id, role]));
  const organizationById = new Map(organizationRows.map((organization) => [organization.id, organization]));

  return jsonSuccess("账号列表已加载", {
    accounts: accountRows.map((account) => {
      const membership = auth.context.organization?.id
        ? membershipRows.find(
            (item) =>
              item.accountId === account.id && item.organizationId === auth.context.organization?.id && item.status === "active",
            )
        : membershipRows.find((item) => item.accountId === account.id && item.status === "active");
      const organization = membership ? organizationById.get(membership.organizationId) : undefined;
      const platformRole = account.platformRoleId ? roleById.get(account.platformRoleId) : undefined;

      return toPublicAccount(account, platformRole?.key ?? membership?.roleKey, organization);
    }),
  });
}

export async function POST(request: Request): Promise<Response> {
  const auth = await requirePermission("account:manage", {
    action: "account.create",
    targetType: "account",
  });

  if (!auth.success) {
    return auth.response;
  }

  const body = await readJsonBody(request);
  if (!isRecord(body)) {
    return jsonFailure("请求数据格式无效");
  }

  const name = readString(body, "name");
  const email = readString(body, "email");
  const avatarUrl = readString(body, "avatarUrl");
  const password = readString(body, "password");
  const roleId = readString(body, "roleId");
  const organizationId = readString(body, "organizationId") || auth.context.organization?.id;

  if (!name || !email || !password || !roleId || !organizationId) {
    return jsonFailure("姓名、邮箱、密码、机构和角色不能为空");
  }

  const database = getDatabase();
  const passwordHash = hashPassword(password);
  try {
    const created = await database.transaction(async (transaction) => {
    const normalizedEmail = normalizeEmail(email);
    const existingAccountRows = await transaction
      .select({ id: accounts.id })
      .from(accounts)
      .where(eq(accounts.email, normalizedEmail))
      .limit(1);
    if (existingAccountRows.length > 0) {
      throw new Error("账号已存在");
    }

    const organizationRows = await transaction.select().from(organizations).where(eq(organizations.id, organizationId)).limit(1);
    const organization = organizationRows[0];
    if (!organization) {
      throw new Error("机构不存在");
    }

    const roleRows = await transaction
      .select()
      .from(roles)
      .where(and(eq(roles.id, roleId), eq(roles.organizationId, organizationId)))
      .limit(1);
    const role = roleRows[0];
    if (!role) {
      throw new Error("角色不存在");
    }

    const accountRows = await transaction
      .insert(accounts)
      .values({
        name,
        email: normalizedEmail,
        avatarUrl,
        passwordHash: passwordHash.hash,
        passwordSalt: passwordHash.salt,
        status: "active",
      })
      .returning();
    const account = accountRows[0];
    if (!account) {
      throw new Error("账号创建失败");
    }

    await transaction.insert(memberships).values({
      accountId: account.id,
      organizationId,
      roleId,
      status: "active",
    });

      return { account, organization, role };
    });

    await recordAuditLog({
      actor: auth.context.account,
      organizationId,
      action: "account.create",
      targetType: "account",
      targetId: created.account.id,
      result: "success",
      reason: `创建机构用户：${created.account.email}`,
    });

    return jsonSuccess("账号已创建", {
      account: toPublicAccount(created.account, created.role.key, {
        id: created.organization.id,
        name: created.organization.name,
        slug: created.organization.slug,
        status: created.organization.status,
        registrationEnabled: created.organization.registrationEnabled,
        oidcEnabled: created.organization.oidcEnabled,
        oidcIssuerUrl: created.organization.oidcIssuerUrl,
        oidcClientId: created.organization.oidcClientId,
        oidcHasClientSecret: created.organization.oidcClientSecret.length > 0,
        oidcScopes: created.organization.oidcScopes,
        oidcRedirectUri: created.organization.oidcRedirectUri,
        oidcAvatarClaim: created.organization.oidcAvatarClaim,
        oidcAutoProvision: created.organization.oidcAutoProvision,
        createdAt: created.organization.createdAt.toISOString(),
        updatedAt: created.organization.updatedAt.toISOString(),
      }),
    }, 201);
  } catch (error) {
    const reason = error instanceof Error ? error.message : "账号创建失败";
    return jsonFailure(reason, reason === "账号已存在" ? 409 : 400);
  }
}
