<?php

namespace App\Doctor\Service\Repair;

use App\Doctor\Entity\Doctor;
use App\Specialty\Entity\Specialty;
use App\Specialty\Repository\SpecialtyRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

/**
 * پزشکانی که فقط تخصص فرزند دارند (مثلاً «گوارش و کبد» بدون «داخلی») تمام
 * تخصص‌های والد تا ریشهٔ درخت را می‌گیرند — وگرنه در فیلتر تخصصِ والد پیدا نمی‌شوند.
 *
 * برخلاف گام‌های دیگر روی هر منبعی اجرا می‌شود: درخت تخصص‌ها ربطی به irimc ندارد
 * و رکورد دستی هم می‌تواند همین نقص را داشته باشد.
 */
final class BackfillSpecialtyParentsStep implements DoctorRepairStep
{
    public function __construct(
        private readonly EntityManagerInterface $em,
        private readonly SpecialtyRepository $specialtyRepo,
    ) {
    }

    public function name(): string
    {
        return 'specialty-parents';
    }

    public function description(): string
    {
        return 'افزودن تخصص‌های والد به پزشکانی که فقط تخصص فرزند دارند';
    }

    public function run(RepairOptions $options, SymfonyStyle $io): RepairResult
    {
        /** @var Doctor[] $doctors */
        $doctors = $this->em->getRepository(Doctor::class)->findAll();

        $changed = 0;
        $added   = 0;
        foreach ($doctors as $doctor) {
            $current = array_map(
                static fn (Specialty $s) => $s->getId(),
                $doctor->getSpecialties()->toArray()
            );
            if ($current === []) {
                continue;
            }

            $missing = array_diff($this->specialtyRepo->expandWithAncestors($current), $current);
            if ($missing === []) {
                continue;
            }

            $io->text(sprintf('  #%d + تخصص %s', $doctor->getId(), implode(', ', $missing)));
            if (!$options->dryRun) {
                foreach ($missing as $id) {
                    $s = $this->specialtyRepo->find($id);
                    if ($s !== null) {
                        $doctor->getSpecialties()->add($s);
                    }
                }
            }

            $changed++;
            $added += count($missing);
        }

        return new RepairResult(
            scanned: count($doctors),
            changed: $changed,
            note: $added > 0 ? "$added پیوند تخصص افزوده شد" : null,
        );
    }
}
