import { Transaction } from "../generated/kysely-tailordb";
import { AttributeNotFoundError, MissingRequiredFieldError } from "../lib/errors.generated";
import { ok, err } from "@tailor-platform/erp-kit/module";

export type UpdateProductAttributeInput = (
  | {
      id: string;
    }
  | {
      code: string;
    }
) & {
  name?: string;
};

/**
 * Function: updateProductAttribute
 *
 * Updates the display name of an existing product attribute.
 * The attribute can be looked up by id or code.
 */
export async function run<CF extends Record<string, unknown>>(
  db: Transaction,
  input: UpdateProductAttributeInput & Omit<Partial<CF>, "status">,
) {
  const { name } = input;

  const KNOWN_KEYS = new Set(["id", "code", "name"]);
  const customFields: Record<string, unknown> = {};
  for (const [key, value] of Object.entries(input as Record<string, unknown>)) {
    if (!KNOWN_KEYS.has(key)) {
      customFields[key] = value;
    }
  }

  // 1. Check attribute exists (lookup by id or code)
  const attribute =
    "id" in input
      ? await db
          .selectFrom("ProductAttribute")
          .selectAll()
          .where("id", "=", (input as { id: string }).id)
          .forUpdate()
          .executeTakeFirst()
      : await db
          .selectFrom("ProductAttribute")
          .selectAll()
          .where("code", "=", (input as { code: string }).code)
          .forUpdate()
          .executeTakeFirst();

  if (!attribute) {
    const key = "id" in input ? (input as { id: string }).id : (input as { code: string }).code;
    return err(new AttributeNotFoundError(key));
  }

  const hasNameUpdate = name !== undefined;
  const hasCustomFields = Object.keys(customFields).length > 0;

  if (!hasNameUpdate && !hasCustomFields) {
    return err(new MissingRequiredFieldError(attribute.id));
  }

  if (hasNameUpdate && !name?.trim()) {
    return err(new MissingRequiredFieldError("name"));
  }

  const updates: Record<string, unknown> = {
    ...customFields,
    updatedAt: new Date(),
  };
  if (hasNameUpdate) updates.name = name;

  const updated = await db
    .updateTable("ProductAttribute")
    .set(updates)
    .where("id", "=", attribute.id)
    .returningAll()
    .executeTakeFirst();

  return ok({ attribute: updated! });
}
