import { extractHarPhotos } from "../../web-automation/scripts/har-photos.js";
import { extractZillowPhotos } from "../../web-automation/scripts/zillow-photos.js";
import { withTimeout } from "./async-timeout.js";

export type PhotoSource = "zillow" | "har";

export interface PhotoExtractionResult {
  source: PhotoSource;
  requestedUrl: string;
  finalUrl?: string;
  expectedPhotoCount?: number | null;
  complete?: boolean;
  photoCount: number;
  imageUrls: string[];
  notes: string[];
}

export interface PhotoReviewResolution {
  review: Record<string, unknown>;
  discoveredListingUrls: Array<{ label: string; url: string }>;
}

interface PhotoReviewDeps {
  timeoutMs?: number;
  zillowTimeoutMs?: number;
  harTimeoutMs?: number;
  extractZillowPhotosFn?: typeof extractZillowPhotos;
  extractHarPhotosFn?: typeof extractHarPhotos;
}

const DEFAULT_PHOTO_EXTRACTION_TIMEOUT_MS = Number(
  process.env.PROPERTY_ASSESSOR_PHOTO_TIMEOUT_MS || 25_000
);
const DEFAULT_ZILLOW_PHOTO_EXTRACTION_TIMEOUT_MS = Number(
  process.env.PROPERTY_ASSESSOR_ZILLOW_PHOTO_TIMEOUT_MS || 60_000
);
const DEFAULT_HAR_PHOTO_EXTRACTION_TIMEOUT_MS = Number(
  process.env.PROPERTY_ASSESSOR_HAR_PHOTO_TIMEOUT_MS || DEFAULT_PHOTO_EXTRACTION_TIMEOUT_MS
);

export async function extractPhotoData(
  source: PhotoSource,
  url: string,
  deps: PhotoReviewDeps = {}
): Promise<PhotoExtractionResult> {
  const timeoutMs = deps.timeoutMs ?? DEFAULT_PHOTO_EXTRACTION_TIMEOUT_MS;
  const zillowTimeoutMs =
    deps.zillowTimeoutMs ??
    (deps.timeoutMs != null ? timeoutMs : DEFAULT_ZILLOW_PHOTO_EXTRACTION_TIMEOUT_MS);
  const harTimeoutMs =
    deps.harTimeoutMs ??
    (deps.timeoutMs != null ? timeoutMs : DEFAULT_HAR_PHOTO_EXTRACTION_TIMEOUT_MS);
  const extractZillowPhotosFn = deps.extractZillowPhotosFn || extractZillowPhotos;
  const extractHarPhotosFn = deps.extractHarPhotosFn || extractHarPhotos;

  if (source === "zillow") {
    const payload = await withTimeout(
      () => extractZillowPhotosFn(url, { timeoutMs: zillowTimeoutMs }),
      {
        operationName: "Zillow photo extraction",
        timeoutMs: zillowTimeoutMs
      }
    );
    return {
      source,
      requestedUrl: String(payload.requestedUrl || url),
      finalUrl: typeof payload.finalUrl === "string" ? payload.finalUrl : undefined,
      expectedPhotoCount: typeof payload.expectedPhotoCount === "number" ? payload.expectedPhotoCount : null,
      complete: Boolean(payload.complete),
      photoCount: Number(payload.photoCount || 0),
      imageUrls: Array.isArray(payload.imageUrls) ? payload.imageUrls.map(String) : [],
      notes: Array.isArray(payload.notes) ? payload.notes.map(String) : []
    };
  }

  const payload = await withTimeout(
    () => extractHarPhotosFn(url, { timeoutMs: harTimeoutMs }),
    {
      operationName: "HAR photo extraction",
      timeoutMs: harTimeoutMs
    }
  );
  return {
    source,
    requestedUrl: String(payload.requestedUrl || url),
    finalUrl: typeof payload.finalUrl === "string" ? payload.finalUrl : undefined,
    expectedPhotoCount: typeof payload.expectedPhotoCount === "number" ? payload.expectedPhotoCount : null,
    complete: Boolean(payload.complete),
    photoCount: Number(payload.photoCount || 0),
    imageUrls: Array.isArray(payload.imageUrls) ? payload.imageUrls.map(String) : [],
    notes: Array.isArray(payload.notes) ? payload.notes.map(String) : []
  };
}
