import { and, eq } from "drizzle-orm";
import dayjs from "dayjs";
import { useDrizzle } from "@/lib/db.js";
import { chargePoint, connector, meterValue } from "@/db/schema.js";
import type { MeterValuesRequest, MeterValuesResponse, OcppConnectionContext } from "../types.ts";

export async function handleMeterValues(
  payload: MeterValuesRequest,
  ctx: OcppConnectionContext,
): Promise<MeterValuesResponse> {
  const db = useDrizzle();

  const [cp] = await db
    .select({ id: chargePoint.id })
    .from(chargePoint)
    .where(eq(chargePoint.chargePointIdentifier, ctx.chargePointIdentifier))
    .limit(1);

  if (!cp) throw new Error(`ChargePoint not found: ${ctx.chargePointIdentifier}`);

  const [conn] = await db
    .select({ id: connector.id })
    .from(connector)
    .where(and(eq(connector.chargePointId, cp.id), eq(connector.connectorId, payload.connectorId)))
    .limit(1);

  if (!conn) {
    console.warn(
      `[OCPP] MeterValues: connector ${payload.connectorId} not found for ${ctx.chargePointIdentifier}`,
    );
    return {};
  }

  const records = payload.meterValue
    .filter((mv) => mv.sampledValue?.length)
    .map((mv) => ({
      id: crypto.randomUUID(),
      transactionId: payload.transactionId ?? null,
      connectorId: conn.id,
      chargePointId: cp.id,
      connectorNumber: payload.connectorId,
      timestamp: dayjs(mv.timestamp).toDate(),
      sampledValues:
        mv.sampledValue as unknown as (typeof meterValue.$inferInsert)["sampledValues"],
    }));

  if (records.length) {
    await db.insert(meterValue).values(records);
  }

  return {};
}
