// src/services/flyerDataTransformer.ts
import path from 'path';
import type { z } from 'zod';
import type { Logger } from 'pino';
import type { FlyerInsert, FlyerItemInsert } from '../types';
import type { AiProcessorResult } from './flyerAiProcessor.server'; // Keep this import for AiProcessorResult
import { AiFlyerDataSchema } from '../types/ai'; // Import consolidated schema
import { generateFlyerIcon } from '../utils/imageProcessor';

/**
 * This class is responsible for transforming the validated data from the AI service
 * into the structured format required for database insertion (FlyerInsert and FlyerItemInsert).
 */
export class FlyerDataTransformer {
  /**
   * Normalizes a single raw item from the AI, providing default values for nullable fields.
   * @param item The raw item object from the AI.
   * @returns A normalized item object ready for database insertion.
   */
  private _normalizeItem(
    item: z.infer<typeof AiFlyerDataSchema>['items'][number],
  ): FlyerItemInsert {
    return {
      ...item,
      // Use logical OR to default falsy values (null, undefined, '') to a fallback.
      // The trim is important for cases where the AI returns only whitespace.
      item: String(item.item || '').trim() || 'Unknown Item',
      // Use nullish coalescing to default only null/undefined to an empty string.
      price_display: String(item.price_display ?? ''),
      quantity: String(item.quantity ?? ''),
      // Use logical OR to default falsy category names (null, undefined, '') to a fallback.
      category_name: String(item.category_name || 'Other/Miscellaneous'),
      // Use nullish coalescing to convert null to undefined for the database.
      master_item_id: item.master_item_id ?? undefined,
      view_count: 0,
      click_count: 0,
    };
  }

  /**
   * Transforms AI-extracted data into database-ready flyer and item records.
   * @param extractedData The validated data from the AI.
   * @param imagePaths The paths to the flyer images.
   * @param originalFileName The original name of the uploaded file.
   * @param checksum The checksum of the file.
   * @param userId The ID of the user who uploaded the file, if any.
   * @param logger The request-scoped or job-scoped logger instance.
   * @returns A promise that resolves to an object containing the prepared flyer and item data.
   */
  async transform(
    aiResult: AiProcessorResult,
    imagePaths: { path: string; mimetype: string }[],
    originalFileName: string,
    checksum: string,
    userId: string | undefined,
    logger: Logger,
  ): Promise<{ flyerData: FlyerInsert; itemsForDb: FlyerItemInsert[] }> {
    logger.info('Starting data transformation from AI output to database format.');

    const { data: extractedData, needsReview } = aiResult;

    const firstImage = imagePaths[0].path;
    const iconFileName = await generateFlyerIcon(
      firstImage,
      path.join(path.dirname(firstImage), 'icons'),
      logger,
    );

    const itemsForDb: FlyerItemInsert[] = extractedData.items.map((item) => this._normalizeItem(item));

    const storeName = extractedData.store_name || 'Unknown Store (auto)';
    if (!extractedData.store_name) {
      logger.warn('AI did not return a store name. Using fallback "Unknown Store (auto)".');
    }

    const flyerData: FlyerInsert = {
      file_name: originalFileName,
      image_url: `/flyer-images/${path.basename(firstImage)}`,
      icon_url: `/flyer-images/icons/${iconFileName}`,
      checksum,
      store_name: storeName,
      valid_from: extractedData.valid_from,
      valid_to: extractedData.valid_to,
      store_address: extractedData.store_address, // The number of items is now calculated directly from the transformed data.
      item_count: itemsForDb.length,
      uploaded_by: userId,
      status: needsReview ? 'needs_review' : 'processed',
    };

    logger.info(
      { itemCount: itemsForDb.length, storeName: flyerData.store_name },
      'Data transformation complete.',
    );

    return { flyerData, itemsForDb };
  }
}
