<?php

namespace App\Shared\Command;

use App\Clinic\Entity\Clinic;
use App\Doctor\Entity\Doctor;
use App\Shared\Util\DisplayName;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

/**
 * پزشکان/کلینیک‌هایی که نام واقعی ندارند (شماره‌تلفن، «test») در نتایج عمومی و در
 * <title> صفحات سایت منتشر می‌شوند. این فرمان آن‌ها را پیدا و دسته‌بندی می‌کند.
 *
 * گزارش‌محور است: بدون --force هیچ چیزی نوشته نمی‌شود.
 *
 *   php bin/console app:audit-polluted-records            # فقط گزارش
 *   php bin/console app:audit-polluted-records --force    # اعمال تغییرات
 *
 * حذف انجام نمی‌دهد. رکورد دارای رابطهٔ واقعی (نوبت/پرداخت) هرگز خودکار دست نمی‌خورد؛
 * برای بقیه فقط انتشار عمومی را می‌بندد (active=false / is_active=false) تا تصمیمِ
 * حذف با تیم بماند و برگشت‌پذیر باشد.
 */
#[AsCommand(
    name: 'app:audit-polluted-records',
    description: 'Find doctors/clinics whose name is a phone number or a placeholder; optionally unpublish them',
)]
class AuditPollutedRecordsCommand extends Command
{
    public function __construct(private readonly EntityManagerInterface $em)
    {
        parent::__construct();
    }

    protected function configure(): void
    {
        $this->addOption('force', null, InputOption::VALUE_NONE, 'Apply changes. Without it nothing is written.');
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io    = new SymfonyStyle($input, $output);
        $force = (bool) $input->getOption('force');

        $doctors = $this->auditDoctors($io);
        $clinics = $this->auditClinics($io);

        $unpublishable = array_merge(
            array_filter($doctors, fn(array $r) => !$r['hasRelations'] && $r['published']),
            array_filter($clinics, fn(array $r) => !$r['hasRelations'] && $r['published']),
        );

        if ($doctors === [] && $clinics === []) {
            $io->success('هیچ رکورد آلوده‌ای یافت نشد.');

            return Command::SUCCESS;
        }

        if (!$force) {
            $io->warning(sprintf(
                'حالت گزارش. %d رکورد قابل خارج‌کردن از انتشار است. برای اعمال: --force',
                count($unpublishable)
            ));

            return Command::SUCCESS;
        }

        foreach ($unpublishable as $row) {
            $row['entity'] instanceof Doctor
                ? $row['entity']->setActiveDoctorAppointment(false)
                : $row['entity']->setIsActive(false);
        }
        $this->em->flush();

        $io->success(sprintf('%d رکورد از انتشار عمومی خارج شد (حذف نشد).', count($unpublishable)));

        return Command::SUCCESS;
    }

    /** @return array<int, array{entity: Doctor, hasRelations: bool, published: bool}> */
    private function auditDoctors(SymfonyStyle $io): array
    {
        $rows = [];
        $table = [];

        /** @var Doctor $doctor */
        foreach ($this->em->getRepository(Doctor::class)->findAll() as $doctor) {
            if (!DisplayName::isPlaceholder($doctor->getName())) {
                continue;
            }

            $appointments = (int) $this->em->createQuery(
                'SELECT COUNT(a.id) FROM App\Appointment\Entity\Appointment a WHERE a.doctor = :d'
            )->setParameter('d', $doctor)->getSingleScalarResult();

            $rows[] = [
                'entity'       => $doctor,
                'hasRelations' => $appointments > 0,
                'published'    => $doctor->isActiveDoctorAppointment(),
            ];
            $table[] = [
                $doctor->getId(),
                $doctor->getName(),
                $doctor->getOwnerStatus(),
                $appointments,
                $doctor->isActiveDoctorAppointment() ? 'بله' : 'خیر',
            ];
        }

        if ($table !== []) {
            $io->section(sprintf('پزشکان با نام نامعتبر (%d)', count($table)));
            $io->table(['id', 'name', 'owner_status', 'نوبت‌ها', 'منتشر شده'], $table);
        }

        return $rows;
    }

    /** @return array<int, array{entity: Clinic, hasRelations: bool, published: bool}> */
    private function auditClinics(SymfonyStyle $io): array
    {
        $rows  = [];
        $table = [];

        /** @var Clinic $clinic */
        foreach ($this->em->getRepository(Clinic::class)->findAll() as $clinic) {
            if (!DisplayName::isPlaceholder($clinic->getName())) {
                continue;
            }

            $doctorCount = $clinic->getDoctors()->count();

            $rows[] = [
                'entity'       => $clinic,
                'hasRelations' => $doctorCount > 0,
                'published'    => $clinic->isActive(),
            ];
            $table[] = [
                $clinic->getId(),
                $clinic->getName(),
                $doctorCount,
                $clinic->isActive() ? 'بله' : 'خیر',
            ];
        }

        if ($table !== []) {
            $io->section(sprintf('کلینیک‌ها با نام نامعتبر (%d)', count($table)));
            $io->table(['id', 'name', 'پزشکان', 'فعال'], $table);
        }

        return $rows;
    }
}
