import { eq, and } from 'drizzle-orm';
import type { DrizzleClient } from '../client.js';
import { vendorAddresses, dealItemConfig } from '../schema.js';

export async function getByVendorId(db: DrizzleClient, vendorId: string) {
  const [row] = await db
    .select()
    .from(vendorAddresses)
    .where(and(eq(vendorAddresses.vendorId, vendorId), eq(vendorAddresses.isPublic, true)))
    .limit(1);
  return row ?? null;
}

export async function listByVendorId(db: DrizzleClient, vendorId: string) {
  return db
    .select()
    .from(vendorAddresses)
    .where(eq(vendorAddresses.vendorId, vendorId))
    .orderBy(vendorAddresses.label);
}

export interface AddressInput {
  label: string;
  fullAddress: string;
  city: string;
  cityCode?: string;
  streetCode?: string;
  streetName?: string;
  houseNumber?: string;
  apt?: string;
  lat: number | null;
  lng: number | null;
  isPublic?: boolean;
}

export async function insertAddress(db: DrizzleClient, vendorId: string, input: AddressInput) {
  const [inserted] = await db
    .insert(vendorAddresses)
    .values({
      vendorId,
      label: input.label,
      fullAddress: input.fullAddress,
      city: input.city,
      cityCode: input.cityCode ?? '',
      streetCode: input.streetCode ?? '',
      streetName: input.streetName ?? '',
      houseNumber: input.houseNumber ?? '',
      apt: input.apt ?? '',
      lat: input.lat !== null ? String(input.lat) : '31.0461',
      lng: input.lng !== null ? String(input.lng) : '34.8516',
      isPublic: input.isPublic ?? false,
    })
    .returning();
  return inserted ?? null;
}

export async function setPublicAddress(db: DrizzleClient, vendorId: string, id: string) {
  await db
    .update(vendorAddresses)
    .set({ isPublic: false })
    .where(eq(vendorAddresses.vendorId, vendorId));
  await db
    .update(vendorAddresses)
    .set({ isPublic: true })
    .where(and(eq(vendorAddresses.vendorId, vendorId), eq(vendorAddresses.id, id)));
}

export async function replacePublicAddress(
  db: DrizzleClient,
  vendorId: string,
  input: Omit<AddressInput, 'isPublic'>,
) {
  await db
    .update(vendorAddresses)
    .set({ isPublic: false })
    .where(eq(vendorAddresses.vendorId, vendorId));
  return insertAddress(db, vendorId, { ...input, isPublic: true });
}

export async function updateAddressLabel(
  db: DrizzleClient,
  vendorId: string,
  id: string,
  label: string,
): Promise<boolean> {
  const result = await db
    .update(vendorAddresses)
    .set({ label })
    .where(and(eq(vendorAddresses.id, id), eq(vendorAddresses.vendorId, vendorId)))
    .returning({ id: vendorAddresses.id });
  return result.length > 0;
}

export async function getAddressActiveReferenceCount(
  db: DrizzleClient,
  addressId: string,
): Promise<string[]> {
  const rows = await db
    .select({ dealId: dealItemConfig.dealId })
    .from(dealItemConfig)
    .where(eq(dealItemConfig.pickupAddressId, addressId));
  return rows.map((r) => r.dealId);
}

export async function deleteAddress(
  db: DrizzleClient,
  vendorId: string,
  id: string,
): Promise<boolean> {
  const result = await db
    .delete(vendorAddresses)
    .where(and(eq(vendorAddresses.id, id), eq(vendorAddresses.vendorId, vendorId)))
    .returning({ id: vendorAddresses.id });
  return result.length > 0;
}
