/**
 * Index phase: build media index, optional duplicate detection, write media_index_summary and duplicates_list.
 * Expects ctx: lakeHandle, lakeFiles, fileMap, outputHandle, options, writeFileToDir.
 * Sets ctx.index on completion.
 */
(function () {
  'use strict';

  var g = typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : this);
  g.GphotoPipelinePhases = g.GphotoPipelinePhases || {};

  g.GphotoPipelinePhases.runIndex = function (ctx, log) {
    log = log || function () {};
    var lakeHandle = ctx.lakeHandle;
    var lakeFiles = ctx.lakeFiles || [];
    var fileMap = ctx.fileMap;
    var outputHandle = ctx.outputHandle;
    var options = ctx.options || {};
    var writeFileToDir = ctx.writeFileToDir;

    var data = { lakeFiles: lakeFiles, lakeHandle: lakeHandle };
    if (typeof GphotoMediaIndex === 'undefined' || !GphotoMediaIndex.buildMediaIndex) {
      log('Media index: skipped (module not loaded).');
      ctx.index = null;
      return Promise.resolve();
    }
    var loadCachePromise = outputHandle
      ? outputHandle.getFileHandle('lake_index_cache.json').then(function (h) {
          return h.getFile().then(function (f) { return f.text(); }).then(function (t) {
            try { return JSON.parse(t); } catch (e) { return null; }
          });
        }).catch(function () { return null; })
      : Promise.resolve(null);
    return loadCachePromise.then(function (cachedJson) {
      var cached = (typeof GphotoMediaIndex.parseCachedIndex === 'function' && cachedJson)
        ? GphotoMediaIndex.parseCachedIndex(cachedJson)
        : null;
      if (cached && cached.remaining_file_names) log('Using cached Lake index for ' + cached.remaining_file_names.length + ' file(s); indexing new files only.');
      log('Building media/metadata index...');
      return GphotoMediaIndex.buildMediaIndex(lakeHandle, lakeFiles, fileMap, { computeHashes: true, extractExif: true }, log, cached);
    }).then(function (index) {
      log('Media/metadata index built. ' + index.stats.total_media_files + ' media, ' + index.stats.total_json_files + ' JSON, ' + index.stats.total_hash_groups + ' hash groups.');
      if (options.detectDuplicates && typeof GphotoMediaIndex.runDuplicateDetection === 'function') {
        log('Duplicate detection (Level 1)...');
        GphotoMediaIndex.runDuplicateDetection(index, options, log);
        log('Duplicate detection: ' + (index.stats.exact_duplicate_groups || 0) + ' exact groups, ' + (index.stats.exact_duplicate_count || 0) + ' duplicate files, ' + (index.stats.version_pairs_count || 0) + ' version pairs.');
      }
      ctx.index = index;
      data.index = index;
      if (!outputHandle) return Promise.resolve();
      var summary = {
        generated_at: new Date().toISOString(),
        extension_version: options.extensionVersion || 'Dev',
        stats: index.stats
      };
      return writeFileToDir(outputHandle, 'media_index_summary.json', new TextEncoder().encode(JSON.stringify(summary, null, 2))).then(function () {
        if (!options.detectDuplicates || !index.records) return Promise.resolve();
        var byCanonicalId = {};
        index.records.forEach(function (rec) {
          if (rec.is_duplicate && rec.duplicate_of != null) {
            var id = rec.duplicate_of;
            if (!byCanonicalId[id]) byCanonicalId[id] = { canonical: null, duplicates: [] };
            byCanonicalId[id].duplicates.push({ filename: rec.filename, id: rec.id, original_path: rec.original_path });
          }
        });
        index.records.forEach(function (rec) {
          if (!rec.is_duplicate && byCanonicalId[rec.id]) {
            byCanonicalId[rec.id].canonical = { filename: rec.filename, id: rec.id, original_path: rec.original_path };
          }
        });
        var groups = [];
        for (var id in byCanonicalId) {
          var grp = byCanonicalId[id];
          if (grp.canonical && grp.duplicates.length) groups.push({ canonical: grp.canonical.filename, duplicate_files: grp.duplicates.map(function (d) { return d.filename; }) });
        }
        var duplicatesList = {
          generated_at: new Date().toISOString(),
          extension_version: options.extensionVersion || 'Dev',
          exact_duplicate_groups: index.stats.exact_duplicate_groups || 0,
          exact_duplicate_count: index.stats.exact_duplicate_count || 0,
          version_pairs_count: index.stats.version_pairs_count || 0,
          duplicate_groups: groups
        };
        return writeFileToDir(outputHandle, 'duplicates_list.json', new TextEncoder().encode(JSON.stringify(duplicatesList, null, 2))).then(function () {
          var lines = ['Duplicates list', 'Generated: ' + duplicatesList.generated_at + ' | Extension: ' + duplicatesList.extension_version, 'Exact duplicate groups: ' + duplicatesList.exact_duplicate_groups, 'Duplicate files: ' + duplicatesList.exact_duplicate_count, 'Version pairs (-edited): ' + duplicatesList.version_pairs_count, ''];
          groups.forEach(function (grp, i) {
            lines.push('Group ' + (i + 1) + ' — canonical: ' + grp.canonical);
            grp.duplicate_files.forEach(function (f) { lines.push('  duplicate: ' + f); });
            lines.push('');
          });
          return writeFileToDir(outputHandle, 'duplicates_list.txt', new TextEncoder().encode(lines.join('\n')));
        });
      });
    }).catch(function (err) {
      log('Media index error: ' + (err.message || err));
      ctx.index = null;
      return Promise.resolve();
    });
  };
})();
