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

import { jsonFailure, jsonSuccess, readJsonBody } from "@/modules/core/server/api";
import { recordAuditLog } from "@/modules/core/server/audit";
import { requirePermission } from "@/modules/core/server/auth";
import { getDatabase } from "@/modules/core/server/db";
import { listOperationalAdmissions } from "@/modules/core/server/operations";
import { admissions, beds, elders } from "@/modules/core/server/schema";

type AdmissionRow = typeof admissions.$inferSelect;

type AdmissionMutationResult =
  | {
      success: true;
      admission: AdmissionRow;
    }
  | {
      success: false;
      reason: string;
      status: number;
    };

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("admission:read", {
    action: "admission.list",
    targetType: "admission",
  });

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

  const admissionsData = await listOperationalAdmissions(auth.context.organization?.id);
  return jsonSuccess("入住记录已加载", { admissions: admissionsData });
}

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

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

  const organizationId = auth.context.organization?.id;
  if (!organizationId) {
    return jsonFailure("请选择机构后办理入住", 400);
  }

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

  const elderId = readString(body, "elderId");
  const bedId = readString(body, "bedId");
  if (!elderId || !bedId) {
    return jsonFailure("老人和床位不能为空");
  }

  const database = getDatabase();
  const mutation = await database.transaction(async (transaction): Promise<AdmissionMutationResult> => {
    const elderRows = await transaction
      .select()
      .from(elders)
      .where(and(eq(elders.id, elderId), eq(elders.organizationId, organizationId)))
      .limit(1);
    const elder = elderRows[0];
    if (!elder) {
      return { success: false, reason: "老人档案不存在", status: 404 };
    }

    const bedRows = await transaction
      .select()
      .from(beds)
      .where(and(eq(beds.id, bedId), eq(beds.organizationId, organizationId)))
      .limit(1);
    const bed = bedRows[0];
    if (!bed) {
      return { success: false, reason: "床位不存在", status: 404 };
    }
    if (bed.status !== "available") {
      return { success: false, reason: "床位不可分配", status: 409 };
    }

    const activeAdmissions = await transaction
      .select()
      .from(admissions)
      .where(
        and(
          eq(admissions.elderId, elderId),
          eq(admissions.organizationId, organizationId),
          eq(admissions.status, "active"),
        ),
      );
    await Promise.all(
      activeAdmissions.map((activeAdmission) =>
        transaction
          .update(admissions)
          .set({ status: "transferred", dischargedAt: new Date(), updatedAt: new Date() })
          .where(eq(admissions.id, activeAdmission.id)),
      ),
    );
    await Promise.all(
      activeAdmissions.map((activeAdmission) =>
        transaction.update(beds).set({ status: "available", updatedAt: new Date() }).where(eq(beds.id, activeAdmission.bedId)),
      ),
    );

    const rows = await transaction
      .insert(admissions)
      .values({
        organizationId,
        elderId,
        bedId,
        status: "active",
        notes: readString(body, "notes"),
      })
      .returning();
    const row = rows[0];
    if (!row) {
      return { success: false, reason: "入住记录创建失败", status: 500 };
    }

    await transaction.update(beds).set({ status: "occupied", updatedAt: new Date() }).where(eq(beds.id, bedId));
    await transaction.update(elders).set({ status: "active", updatedAt: new Date() }).where(eq(elders.id, elderId));
    return { success: true, admission: row };
  });

  if (!mutation.success) {
    return jsonFailure(mutation.reason, mutation.status);
  }

  await recordAuditLog({
    actor: auth.context.account,
    organizationId,
    action: "admission.create",
    targetType: "admission",
    targetId: mutation.admission.id,
    result: "success",
    reason: "办理入住/换床",
  });

  return jsonSuccess("入住记录已创建", { admission: mutation.admission }, 201);
}
