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

import { jsonFailure, jsonSuccess, readJsonBody } from "@/modules/core/server/api";
import { recordAuditLog } from "@/modules/core/server/audit";
import { requirePermission, toPublicAccount } from "@/modules/core/server/auth";
import { getDatabase } from "@/modules/core/server/db";
import { hasPermission } from "@/modules/core/server/permissions";
import { accounts, memberships, organizations, roles, sessions } from "@/modules/core/server/schema";
import type { AccountStatus, Organization } from "@/modules/core/types";

type RouteContext = {
  params: Promise<{
    id: string;
  }>;
};

const ACCOUNT_STATUSES: AccountStatus[] = ["active", "disabled", "pending"];

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() : "";
}

function readStatus(value: unknown): AccountStatus | null {
  if (typeof value !== "string") {
    return null;
  }

  return ACCOUNT_STATUSES.find((status) => status === value) ?? null;
}

function toOrganization(row: typeof organizations.$inferSelect): Organization {
  return {
    id: row.id,
    name: row.name,
    slug: row.slug,
    status: row.status,
    registrationEnabled: row.registrationEnabled,
    oidcEnabled: row.oidcEnabled,
    oidcIssuerUrl: row.oidcIssuerUrl,
    oidcClientId: row.oidcClientId,
    oidcHasClientSecret: row.oidcClientSecret.length > 0,
    oidcScopes: row.oidcScopes,
    oidcRedirectUri: row.oidcRedirectUri,
    oidcAvatarClaim: row.oidcAvatarClaim,
    oidcAutoProvision: row.oidcAutoProvision,
    createdAt: row.createdAt.toISOString(),
    updatedAt: row.updatedAt.toISOString(),
  };
}

export async function PATCH(request: Request, context: RouteContext): Promise<Response> {
  const { id } = await context.params;
  const auth = await requirePermission("account:manage", {
    action: "account.update",
    targetType: "account",
    targetId: id,
  });

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

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

  const name = readString(body, "name");
  const avatarUrl = readString(body, "avatarUrl");
  const hasAvatarUrl = "avatarUrl" in body;
  const status = "status" in body ? readStatus(body.status) : null;
  const roleId = readString(body, "roleId");
  const requestedOrganizationId = readString(body, "organizationId");
  const organizationId = requestedOrganizationId || auth.context.organization?.id;

  if ("status" in body && !status) {
    return jsonFailure("账号状态无效");
  }

  if (!name && !hasAvatarUrl && !status && !roleId) {
    return jsonFailure("请至少填写一个要更新的字段");
  }

  if (id === auth.context.account.id && status === "disabled") {
    return jsonFailure("不能停用当前登录账号", 400);
  }

  const canManagePlatform = hasPermission(auth.context.permissions, "platform:manage");
  if (!canManagePlatform && requestedOrganizationId && requestedOrganizationId !== auth.context.organization?.id) {
    return jsonFailure("权限不足", 403);
  }

  const database = getDatabase();
  const targetAccountRows = await database.select().from(accounts).where(eq(accounts.id, id)).limit(1);
  const targetAccount = targetAccountRows[0];
  if (!targetAccount) {
    return jsonFailure("账号不存在", 404);
  }

  if (roleId && !organizationId) {
    return jsonFailure("请选择机构后分配角色", 400);
  }

  const organizationRows = organizationId
    ? await database.select().from(organizations).where(eq(organizations.id, organizationId)).limit(1)
    : [];
  const organization = organizationRows[0];
  if (roleId && !organization) {
    return jsonFailure("机构不存在", 404);
  }

  try {
    await database.transaction(async (transaction) => {
      if (name || hasAvatarUrl || status) {
        const updateValues: {
          name?: string;
          avatarUrl?: string;
          status?: AccountStatus;
          updatedAt: Date;
        } = {
          updatedAt: new Date(),
        };
        if (name) {
          updateValues.name = name;
        }
        if (hasAvatarUrl) {
          updateValues.avatarUrl = avatarUrl;
        }
        if (status) {
          updateValues.status = status;
        }

        await transaction.update(accounts).set(updateValues).where(eq(accounts.id, id));
        if (status === "disabled") {
          await transaction.delete(sessions).where(eq(sessions.accountId, id));
        }
      }

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

        const membershipRows = await transaction
          .select()
          .from(memberships)
          .where(and(eq(memberships.accountId, id), eq(memberships.organizationId, organizationId)))
          .limit(1);
        const membership = membershipRows[0];

        if (membership) {
          await transaction
            .update(memberships)
            .set({ roleId, status: "active", updatedAt: new Date() })
            .where(eq(memberships.id, membership.id));
        } else {
          await transaction.insert(memberships).values({
            accountId: id,
            organizationId,
            roleId,
            status: "active",
          });
        }
      }
    });
  } catch (error) {
    const reason = error instanceof Error ? error.message : "账号更新失败";
    return jsonFailure(reason, reason === "角色不存在" ? 404 : 400);
  }

  const updatedAccountRows = await database.select().from(accounts).where(eq(accounts.id, id)).limit(1);
  const updatedAccount = updatedAccountRows[0];
  if (!updatedAccount) {
    return jsonFailure("账号不存在", 404);
  }

  const membershipRows = organizationId
    ? await database
        .select({ membership: memberships, role: roles })
        .from(memberships)
        .innerJoin(roles, eq(roles.id, memberships.roleId))
        .where(and(eq(memberships.accountId, id), eq(memberships.organizationId, organizationId)))
        .limit(1)
    : [];
  const membership = membershipRows[0];
  const publicAccount = toPublicAccount(
    updatedAccount,
    membership?.role.key,
    organization ? toOrganization(organization) : undefined,
  );

  await recordAuditLog({
    actor: auth.context.account,
    organizationId,
    action: "account.update",
    targetType: "account",
    targetId: updatedAccount.id,
    result: "success",
    reason: `更新账号：${updatedAccount.email}`,
  });

  return jsonSuccess("账号已更新", { account: publicAccount });
}

export async function DELETE(_request: Request, context: RouteContext): Promise<Response> {
  const { id } = await context.params;
  const auth = await requirePermission("account:manage", {
    action: "account.disable",
    targetType: "account",
    targetId: id,
  });

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

  if (id === auth.context.account.id) {
    return jsonFailure("不能停用当前登录账号", 400);
  }

  const database = getDatabase();
  const rows = await database
    .update(accounts)
    .set({ status: "disabled", updatedAt: new Date() })
    .where(eq(accounts.id, id))
    .returning();
  const account = rows[0];
  if (!account) {
    return jsonFailure("账号不存在", 404);
  }
  await database.delete(sessions).where(eq(sessions.accountId, id));

  await recordAuditLog({
    actor: auth.context.account,
    organizationId: auth.context.organization?.id,
    action: "account.disable",
    targetType: "account",
    targetId: account.id,
    result: "success",
    reason: `停用账号：${account.email}`,
  });

  return jsonSuccess("账号已停用", { account: toPublicAccount(account) });
}
