/**
 * Prompt Training Data
 * 
 * 900+ prompt kütüphanesinden eğitim örnekleri çıkarır.
 * AI prompt generator'a örnek olarak gönderilir.
 */

import { createModuleLogger } from '../../utils/logger.js';
import { readJSON } from '../data-store/file-ops.js';
import { resolve } from 'path';
import { config } from '../../utils/config.js';

const log = createModuleLogger('prompt-training-data');

export interface TrainingExample {
  id: string;
  category: string;
  flatPrompt: string;
  aspectRatio: string;
  outfit: string;
  scene: string;
}

interface BasePrompt {
  id: string;
  category: string;
  json: Record<string, unknown>;
}

let cachedExamples: TrainingExample[] | null = null;

/**
 * 900+ prompt kütüphanesinden eğitim örnekleri yükler.
 * Opsiyonel kategori filtresi ile belirli kategoriden örnekler alır.
 */
export async function loadTrainingExamples(category?: string): Promise<TrainingExample[]> {
  if (!cachedExamples) {
    cachedExamples = await buildTrainingExamples();
  }

  let filtered = cachedExamples;
  if (category) {
    // Kategori eşleştirme
    const categoryMap: Record<string, string[]> = {
      'selfie-casual': ['casual-everyday', 'selfie'],
      'lifestyle-glamour': ['lifestyle-glamour', 'lifestyle', 'luxury'],
      'nightlife': ['nightlife'],
      'fitness': ['fitness', 'wellness'],
      'beach-pool': ['beach'],
      'intimate-morning': ['intimate-boudoir'],
      'fashion-editorial': ['fashion-editorial', 'fashion'],
      'outdoor-adventure': ['outdoor-adventure', 'travel', 'urban', 'nature'],
    };
    const matchCategories = categoryMap[category] || [category];
    filtered = cachedExamples.filter(ex => matchCategories.includes(ex.category));
  }

  // Rastgele 8 örnek seç
  return shuffleAndPick(filtered.length > 0 ? filtered : cachedExamples, 8);
}


async function buildTrainingExamples(): Promise<TrainingExample[]> {
  try {
    const promptsPath = resolve(config.dataDir, 'prompt-library', 'base-prompts.json');
    const basePrompts = await readJSON<BasePrompt[]>(promptsPath);
    if (!basePrompts || !Array.isArray(basePrompts)) return [];

    const examples: TrainingExample[] = [];

    for (const bp of basePrompts) {
      try {
        const json = bp.json;
        if (!json) continue;

        const flat = flattenForTraining(json);
        if (!flat.prompt || flat.prompt.length < 50) continue;

        examples.push({
          id: bp.id,
          category: bp.category,
          flatPrompt: flat.prompt,
          aspectRatio: flat.aspectRatio,
          outfit: flat.outfit,
          scene: flat.scene,
        });
      } catch {
        // skip malformed prompts
      }
    }

    log.info({ totalExamples: examples.length }, 'Training examples loaded from prompt library');
    return examples;
  } catch (err: any) {
    log.error({ error: err.message }, 'Failed to load training examples');
    return [];
  }
}

/**
 * JSON prompt'u düz eğitim string'ine çevirir.
 * Karakter bilgisi yerine [CHARACTER] placeholder kullanır.
 */
function flattenForTraining(json: Record<string, unknown>): {
  prompt: string;
  aspectRatio: string;
  outfit: string;
  scene: string;
} {
  const parts: string[] = [];

  // Scene
  const scene = extractStr(json, ['scene_type', 'scene', 'setting']);
  if (scene) parts.push(scene);

  // Subject placeholder
  parts.push('[CHARACTER]');

  // Action/pose
  const action = extractStr(json, ['subject.action', 'action', 'pose']);
  if (action) parts.push(action);

  // Outfit - detaylı çıkar
  const outfit = extractOutfit(json);
  if (outfit) parts.push(outfit);

  // Expression
  const expression = extractNested(json, 'expression') || extractNested(json, 'subject.expression');
  if (expression) parts.push(expression);

  // Environment
  const env = extractNested(json, 'environment') || extractNested(json, 'setting');
  if (env) parts.push(env);

  // Lighting
  const lighting = extractStr(json, ['environment.lighting', 'lighting', 'light']);
  if (lighting) parts.push(lighting);

  // Camera/style
  const style = extractStr(json, ['style', 'camera_style', 'aesthetic']);
  if (style) parts.push(style);

  // Aspect ratio
  const ar = extractStr(json, ['aspect_ratio', 'camera.aspect_ratio', 'meta.aspect_ratio']) || '9:16';

  return {
    prompt: parts.filter(Boolean).join(', '),
    aspectRatio: ar,
    outfit: outfit || '',
    scene: scene || '',
  };
}

function extractOutfit(json: Record<string, unknown>): string {
  // Try multiple paths for outfit info
  const paths = ['outfit', 'subject.outfit', 'clothing', 'subject.clothing'];
  for (const path of paths) {
    const val = getNestedValue(json, path);
    if (val && typeof val === 'object') {
      return collectStrings(val).join(', ');
    }
    if (typeof val === 'string' && val.length > 10) return val;
  }
  return '';
}

function extractStr(obj: Record<string, unknown>, paths: string[]): string | null {
  for (const path of paths) {
    const val = getNestedValue(obj, path);
    if (typeof val === 'string' && val.length > 0) return val;
  }
  return null;
}

function extractNested(obj: Record<string, unknown>, key: string): string | null {
  const val = getNestedValue(obj, key);
  if (!val) return null;
  if (typeof val === 'string') return val;
  if (typeof val === 'object') {
    const strings = collectStrings(val);
    return strings.length > 0 ? strings.join(', ') : null;
  }
  return null;
}

function getNestedValue(obj: Record<string, unknown>, path: string): unknown {
  const keys = path.split('.');
  let current: unknown = obj;
  for (const key of keys) {
    if (!current || typeof current !== 'object') return undefined;
    current = (current as Record<string, unknown>)[key];
  }
  return current;
}

function collectStrings(obj: unknown): string[] {
  const results: string[] = [];
  if (typeof obj === 'string' && obj.length > 3) {
    results.push(obj);
  } else if (Array.isArray(obj)) {
    for (const item of obj) {
      results.push(...collectStrings(item));
    }
  } else if (obj && typeof obj === 'object') {
    for (const val of Object.values(obj)) {
      results.push(...collectStrings(val));
    }
  }
  return results;
}

function shuffleAndPick<T>(arr: T[], count: number): T[] {
  const shuffled = [...arr];
  for (let i = shuffled.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
  }
  return shuffled.slice(0, count);
}
