#!/usr/bin/env php
<?php
declare(strict_types=1);

$root = dirname(__DIR__);
require $root . '/app/Services/DB.php';
require $root . '/app/Services/BackupService.php';
require $root . '/app/Services/ImageService.php';
require $root . '/app/Services/Asm3Analyzer.php';

$apply = in_array('--apply', $argv, true);
$positional = array_values(
    array_filter(array_slice($argv, 1), static fn($arg) => !str_starts_with((string) $arg, '--')),
);
$dump = $positional[0] ?? '';
$sourceDir = $positional[1] ?? '';
if ($dump === '' || $sourceDir === '') {
    fwrite(STDERR, "Usage : php scripts/import-asm3-photos.php <dump.sql> <dossier-photos> [--apply]\n");
    exit(2);
}
if (!is_file($dump) || !is_dir($sourceDir)) {
    throw new RuntimeException('Dump ASM3 ou dossier des photos introuvable.');
}
$hash = hash_file('sha256', $dump);
$source = Asm3Analyzer::rows($dump, ['media', 'dbfs']);
$db = DB::pdo();
$links = [];
$q = $db->prepare("SELECT source_id,target_id FROM asm3_import_links WHERE source_sha256=? AND entity_type='animal'");
$q->execute([$hash]);
foreach ($q as $row) {
    $links[(int) $row['source_id']] = (int) $row['target_id'];
}
$dbfs = [];
foreach ($source['dbfs'] ?? [] as $row) {
    $dbfs[(int) $row['ID']] = $row;
}
$items = [];
$errors = [];
foreach ($source['media'] ?? [] as $media) {
    if ((int) $media['LINKTYPEID'] !== 0 || !str_starts_with((string) $media['MEDIAMIMETYPE'], 'image/')) {
        continue;
    }
    $sourceAnimal = (int) $media['LINKID'];
    $targetAnimal = $links[$sourceAnimal] ?? 0;
    $physical = $dbfs[(int) $media['DBFSID']] ?? null;
    $filename = $physical ? basename(str_replace('file:', '', (string) $physical['URL'])) : '';
    $path = $sourceDir . '/' . $filename;
    if (!$targetAnimal) {
        $errors[] = 'Animal ASM3 non relié : ' . $sourceAnimal;
    } elseif ($filename === '' || !is_file($path)) {
        $errors[] = 'Fichier absent pour le média ASM3 ' . $media['ID'];
    } else {
        $inspection = ImageService::inspect($path);
        $items[] = [
            'media' => $media,
            'animal' => $targetAnimal,
            'path' => $path,
            'physical' => $filename,
            'inspection' => $inspection,
        ];
    }
}
if ($errors) {
    throw new RuntimeException(implode("\n", $errors));
}
$targets = array_values(array_unique(array_column($items, 'animal')));
$primaryCount = count(array_filter($items, static fn(array $i): bool => (int) $i['media']['WEBSITEPHOTO'] === 1));
$summary = [
    'mode' => $apply ? 'APPLIQUE' : 'SIMULATION',
    'photos_found' => count($items),
    'animals' => count($targets),
    'primary_photos' => $primaryCount,
    'public_photos' => count($items),
    'already_imported' => 0,
    'created' => 0,
    'optimized' => 0,
    'backup' => null,
];
foreach ($items as $item) {
    $original = 'ASM3-' . (int) $item['media']['ID'] . '-' . (string) $item['media']['MEDIANAME'];
    $s = $db->prepare('SELECT 1 FROM animal_photos WHERE animal_id=? AND original_name=?');
    $s->execute([$item['animal'], $original]);
    if ($s->fetchColumn()) {
        $summary['already_imported']++;
    }
}
if (!$apply) {
    echo json_encode($summary, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
    exit();
}
$backup = BackupService::create('avant-import-photos-asm3');
$summary['backup'] = $backup['name'] ?? null;
$written = [];
$db->beginTransaction();
try {
    $db->prepare(
        "INSERT INTO asm3_import_runs(source_name,source_sha256,status,summary_json,backup_name) VALUES(?,?,'completed','{}',?)",
    )->execute([basename($dump) . ' · photos', $hash, $summary['backup']]);
    $run = (int) $db->lastInsertId();
    $reset = $db->prepare('UPDATE animal_photos SET is_primary=0 WHERE animal_id=?');
    foreach ($targets as $animalId) {
        $reset->execute([$animalId]);
    }
    $insert = $db->prepare(
        'INSERT INTO animal_photos(animal_id,filename,original_name,mime,size_bytes,is_primary,is_public,caption,created_at) VALUES(?,?,?,?,?,?,1,?,COALESCE(?,datetime(\'now\')))',
    );
    $link = $db->prepare(
        "INSERT OR IGNORE INTO asm3_import_links(source_sha256,entity_type,source_id,target_id,import_run_id) VALUES(?,'media',?,?,?)",
    );
    foreach ($items as $item) {
        $media = $item['media'];
        $original = 'ASM3-' . (int) $media['ID'] . '-' . (string) $media['MEDIANAME'];
        $existing = $db->prepare('SELECT id FROM animal_photos WHERE animal_id=? AND original_name=?');
        $existing->execute([$item['animal'], $original]);
        $photoId = (int) $existing->fetchColumn();
        if (!$photoId) {
            $stored = ImageService::storeLocal(
                $item['path'],
                $root . '/public/media/animals/' . $item['animal'],
                'asm3_' . (int) $media['ID'],
                'photo',
            );
            $written[] = $stored['path'];
            $caption = trim((string) ($media['MEDIANOTES'] ?? ''));
            $caption = $caption !== '' ? 'Archive ASM3 · ' . $caption : 'Archive ASM3';
            $insert->execute([
                $item['animal'],
                $stored['filename'],
                $original,
                $stored['mime'],
                $stored['size'],
                (int) $media['WEBSITEPHOTO'] === 1 ? 1 : 0,
                $caption,
                substr((string) $media['CREATEDDATE'], 0, 19) ?: null,
            ]);
            $photoId = (int) $db->lastInsertId();
            $summary['created']++;
            if ($stored['optimized']) {
                $summary['optimized']++;
            }
        } elseif ((int) $media['WEBSITEPHOTO'] === 1) {
            $db->prepare('UPDATE animal_photos SET is_primary=1,is_public=1 WHERE id=?')->execute([$photoId]);
        } else {
            $db->prepare('UPDATE animal_photos SET is_public=1 WHERE id=?')->execute([$photoId]);
        }
        $link->execute([$hash, (int) $media['ID'], $photoId, $run]);
    }
    $db->prepare('UPDATE asm3_import_runs SET summary_json=? WHERE id=?')->execute([
        json_encode($summary, JSON_UNESCAPED_UNICODE),
        $run,
    ]);
    if ($db->query('PRAGMA foreign_key_check')->fetchAll()) {
        throw new RuntimeException('Violation de clé étrangère après import.');
    }
    $db->commit();
} catch (Throwable $e) {
    if ($db->inTransaction()) {
        $db->rollBack();
    }
    foreach ($written as $path) {
        @unlink($path);
    }
    throw $e;
}
echo json_encode($summary, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
