<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;

class SyncPoliFromJson extends Command
{
    protected $signature = 'poli:sync-json {--path= : Path file JSON poli, default database/seeders/data/poli.json} {--dry-run : Cek data tanpa menulis ke database}';

    protected $description = 'Update atau create data poli dari file JSON berdasarkan id tanpa truncate.';

    public function handle(): int
    {
        $path = $this->resolvePath($this->option('path') ?: database_path('seeders/data/poli.json'));
        $data = $this->readJson($path);

        $updated = 0;
        $created = 0;
        $unchanged = 0;

        DB::transaction(function () use ($data, &$updated, &$created, &$unchanged) {
            foreach ($data as $row) {
                $id = (int) $row['id'];
                $payload = [
                    'poli' => $row['poli'] ?? null,
                    'subpoli' => $row['subpoli'] ?? null,
                    'subsubpoli' => $row['subsubpoli'] ?? null,
                    'modaliti' => $row['modaliti'] ?? null,
                    'kelompok' => $row['kelompok'] ?? null,
                    'modaliti2' => isset($row['modaliti2']) ? (string) $row['modaliti2'] : null,
                    'created_at' => $row['created_at'] ?? now(),
                    'updated_at' => $row['updated_at'] ?? now(),
                ];

                $existing = DB::table('poli')->where('id', $id)->first();

                if ($existing === null) {
                    $created++;

                    if (!$this->option('dry-run')) {
                        DB::table('poli')->insert(array_merge(['id' => $id], $payload));
                    }

                    continue;
                }

                if ($this->isSameRow($existing, $payload)) {
                    $unchanged++;
                    continue;
                }

                $updated++;

                if (!$this->option('dry-run')) {
                    DB::table('poli')->where('id', $id)->update($payload);
                }
            }
        });

        $mode = $this->option('dry-run') ? 'DRY RUN' : 'DONE';
        $this->info("{$mode}: {$created} created, {$updated} updated, {$unchanged} unchanged.");

        return self::SUCCESS;
    }

    private function resolvePath(string $path): string
    {
        if ($path !== '' && $path[0] === '/') {
            return $path;
        }

        return base_path($path);
    }

    private function readJson(string $path): array
    {
        if (!is_file($path)) {
            throw new \RuntimeException("File JSON poli tidak ditemukan: {$path}");
        }

        $json = file_get_contents($path);

        if ($json === false) {
            throw new \RuntimeException("Gagal membaca file JSON poli: {$path}");
        }

        $data = json_decode($json, true);

        if (!is_array($data)) {
            throw new \RuntimeException("Format JSON poli tidak valid: {$path}");
        }

        $ids = [];

        foreach ($data as $index => $row) {
            if (!is_array($row) || !isset($row['id'])) {
                throw new \RuntimeException('Data poli baris '.($index + 1).' tidak memiliki id.');
            }

            $id = (int) $row['id'];

            if (isset($ids[$id])) {
                throw new \RuntimeException("Duplikasi id poli pada JSON: {$id}");
            }

            $ids[$id] = true;
        }

        return $data;
    }

    private function isSameRow(object $existing, array $payload): bool
    {
        foreach ($payload as $key => $value) {
            if ((string) ($existing->{$key} ?? '') !== (string) ($value ?? '')) {
                return false;
            }
        }

        return true;
    }
}
