<?php

namespace App\Modules\Addon\MigrateWhmcs\Importers;

use App\Modules\Addon\MigrateWhmcs\Services\ImportReport;
use App\Modules\Addon\MigrateWhmcs\Services\MigrationLedger;
use App\Modules\Addon\MigrateWhmcs\Services\WhmcsSourceConnection;
use Illuminate\Support\Facades\Log;

/**
 * PRC-1113 — Tüm WHMCS importer'larının tabanı.
 *
 * Sözleşme: sourceType() (ledger anahtarı) + sourceTable() (WHMCS tbl adı) +
 * importRow($row) (tek kaydı map+persist; dönüş = procp target id veya null=skip).
 * Taban chunk'lama, idempotency (ledger has()), dry-run guard ve hata izolasyonunu
 * yönetir → importer alt-sınıfı yalnız alan-eşleme mantığına odaklanır.
 */
abstract class AbstractWhmcsImporter
{
    public function __construct(
        protected MigrationLedger $ledger,
        protected ImportReport $report,
        protected bool $dryRun = false,
        protected ?string $runId = null,
    ) {}

    /** Ledger/rapor anahtarı: client|domain|service|invoice|order|ticket */
    abstract public function sourceType(): string;

    /** Okunacak WHMCS tablosu (ör. 'tblclients'). */
    abstract protected function sourceTable(): string;

    /**
     * Tek WHMCS satırını procp'ye map+persist et. Dönüş: yeni/eşleşen procp target id
     * (ledger'a kaydedilir) veya null (skip — importRow uyarı/skip'i kendi raporlar).
     * DRY-RUN'da bu metod çağrılMAZ (taban yalnız sayar).
     */
    abstract protected function importRow(object $row): ?int;

    /**
     * Ana döngü: WHMCS tablosunu chunk'la; her satır için idempotency + dry-run +
     * hata-izolasyonu uygula. importRow'daki bir exception TÜM göçü durdurmaz —
     * o satır 'failed' sayılır, log'lanır, döngü devam eder.
     */
    public function run(): void
    {
        $type = $this->sourceType();

        WhmcsSourceConnection::table($this->sourceTable())
            ->orderBy('id')
            ->chunk(500, function ($rows) use ($type) {
                foreach ($rows as $row) {
                    // Zaten import edildi → skip (resumable/idempotent).
                    if ($this->ledger->has($type, $row->id)) {
                        $this->report->skipped($type);

                        continue;
                    }

                    // Dry-run: yazma, yalnız "import edilecek" say.
                    if ($this->dryRun) {
                        $this->report->imported($type);

                        continue;
                    }

                    try {
                        $targetId = $this->importRow($row);
                        if ($targetId === null) {
                            $this->report->skipped($type);

                            continue;
                        }
                        $this->ledger->record($type, $row->id, $this->targetType(), $targetId, $this->runId);
                        $this->report->imported($type);
                    } catch (\Throwable $e) {
                        $this->report->failed($type);
                        $this->report->warn($type, "Satır #{$row->id} import hatası: ".$e->getMessage());
                        Log::error('WHMCS import row failed', [
                            'type' => $type,
                            'source_id' => $row->id,
                            'error' => $e->getMessage(),
                        ]);
                    }
                }
            });
    }

    /** Ledger'a yazılan hedef tip (default = sourceType; override edilebilir). */
    protected function targetType(): string
    {
        return $this->sourceType();
    }
}
