import {
  buildPaginatedResult,
  DEFAULT_PAGE_SIZE,
  ok,
  type ReadonlyDB,
} from "@tailor-platform/erp-kit/core";
import type { TransferOrderStatus } from "../generated/enums";
import type { DB } from "../generated/kysely-tailordb";
import {
  getTransferOrderReceivingStatus,
  getTransferOrderShippingStatus,
} from "../internal/transferOrderProgress";

export interface ListTransferOrdersInput {
  status?: TransferOrderStatus;
  sourceSiteId?: string;
  destinationSiteId?: string;
  limit?: number;
  offset?: number;
}

export async function run(db: ReadonlyDB<DB>, input: ListTransferOrdersInput) {
  const limit = input.limit ?? DEFAULT_PAGE_SIZE;
  const offset = input.offset ?? 0;

  let query = db.selectFrom("TransferOrder").selectAll();
  if (input.status) query = query.where("status", "=", input.status);
  if (input.sourceSiteId) {
    query = query.where("sourceSiteId", "=", input.sourceSiteId);
  }
  if (input.destinationSiteId) {
    query = query.where("destinationSiteId", "=", input.destinationSiteId);
  }

  const transferOrders = await query
    .orderBy("createdAt", "desc")
    .limit(limit + 1)
    .offset(offset)
    .execute();

  const paginatedResult = buildPaginatedResult(transferOrders, limit);
  const transferOrderIds = paginatedResult.items.map((transferOrder) => transferOrder.id);
  const lines =
    transferOrderIds.length > 0
      ? await db
          .selectFrom("TransferOrderLine")
          .selectAll()
          .where("transferOrderId", "in", transferOrderIds)
          .execute()
      : [];

  const linesByTransferOrderId = new Map<string, typeof lines>();
  for (const line of lines) {
    const current = linesByTransferOrderId.get(line.transferOrderId) ?? [];
    current.push(line);
    linesByTransferOrderId.set(line.transferOrderId, current);
  }

  return ok({
    items: paginatedResult.items.map((transferOrder) => {
      const transferOrderLines = linesByTransferOrderId.get(transferOrder.id) ?? [];
      return {
        transferOrder,
        transferOrderLines,
        shippingStatus: getTransferOrderShippingStatus(transferOrderLines),
        receivingStatus: getTransferOrderReceivingStatus(transferOrderLines),
      };
    }),
    hasNextPage: paginatedResult.hasNextPage,
  });
}
