import { randomUUID } from "node:crypto";

import { and, desc, 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 { admissions, beds, elders, rooms } from "@/modules/core/server/schema";
import { validateElderInput } from "@/modules/elders/types";
import type { Elder } from "@/modules/elders/types";

type ElderRow = typeof elders.$inferSelect;
type BedLabel = {
  room: string;
  bed: string;
  bedId: string;
};

type ElderCreateResult =
  | {
      success: true;
      elder: ElderRow;
      bedLabel?: BedLabel;
    }
  | {
      success: false;
      reason: string;
      status: number;
    };

function toElder(row: ElderRow, bedLabel?: BedLabel): Elder {
  return {
    id: row.id,
    organizationId: row.organizationId,
    name: row.name,
    gender: row.gender,
    age: row.age,
    careLevel: row.careLevel,
    room: bedLabel?.room ?? "",
    bed: bedLabel?.bed ?? "",
    bedId: bedLabel?.bedId,
    status: row.status,
    primaryContact: row.primaryContact,
    phone: row.phone,
    medicalNotes: row.medicalNotes,
    createdAt: row.createdAt.toISOString(),
    updatedAt: row.updatedAt.toISOString(),
  };
}

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

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

  const organizationId = auth.context.organization?.id;
  if (!organizationId) {
    return jsonFailure("请选择机构后查看老人档案", 400);
  }

  const database = getDatabase();
  const [rows, activeAdmissionRows] = await Promise.all([
    database
      .select()
      .from(elders)
      .where(eq(elders.organizationId, organizationId))
      .orderBy(desc(elders.createdAt)),
    database
      .select({
        elderId: admissions.elderId,
        bedId: admissions.bedId,
        bedCode: beds.code,
        roomName: rooms.name,
      })
      .from(admissions)
      .innerJoin(beds, eq(beds.id, admissions.bedId))
      .innerJoin(rooms, eq(rooms.id, beds.roomId))
      .where(and(eq(admissions.organizationId, organizationId), eq(admissions.status, "active"))),
  ]);
  const bedLabelByElderId = new Map(
    activeAdmissionRows.map((row) => [
      row.elderId,
      {
        room: row.roomName,
        bed: row.bedCode,
        bedId: row.bedId,
      },
    ]),
  );

  return jsonSuccess("老人档案已加载", { elders: rows.map((row) => toElder(row, bedLabelByElderId.get(row.id))) });
}

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

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

  const organizationId = auth.context.organization?.id;
  if (!organizationId) {
    return jsonFailure("请选择机构后新增老人档案", 400);
  }

  const input = validateElderInput(await readJsonBody(request));
  if (!input.success) {
    return jsonFailure(input.reason);
  }

  const database = getDatabase();
  const created = await database.transaction(async (transaction): Promise<ElderCreateResult> => {
    const elderId = randomUUID();
    const elderRows = await transaction
      .insert(elders)
      .values({
        id: elderId,
        organizationId,
        name: input.data.name,
        gender: input.data.gender,
        age: input.data.age,
        careLevel: input.data.careLevel,
        status: input.data.bedId ? "active" : input.data.status,
        primaryContact: input.data.primaryContact,
        phone: input.data.phone,
        medicalNotes: input.data.medicalNotes,
      })
      .returning();
    const elder = elderRows[0];
    if (!elder) {
      return { success: false, reason: "老人档案创建失败", status: 500 };
    }

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

      await transaction
        .insert(admissions)
        .values({
          organizationId,
          elderId: elder.id,
          bedId: bedRow.bed.id,
          status: "active",
          notes: "新增档案时办理入住",
        });
      await transaction
        .update(beds)
        .set({ status: "occupied", updatedAt: new Date() })
        .where(and(eq(beds.id, bedRow.bed.id), eq(beds.organizationId, organizationId)));

      return {
        success: true,
        elder,
        bedLabel: {
          room: bedRow.roomName,
          bed: bedRow.bed.code,
          bedId: bedRow.bed.id,
        },
      };
    }

    return { success: true, elder };
  });

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

  const elder = toElder(created.elder, created.bedLabel);
  await recordAuditLog({
    actor: auth.context.account,
    organizationId,
    action: "elder.create",
    targetType: "elder",
    targetId: elder.id,
    result: "success",
    reason: `新增老人档案：${elder.name}`,
  });

  return jsonSuccess("老人档案已创建", { elder }, 201);
}
