<?php

namespace App\Appointment\Command;

use App\Appointment\Repository\WeeklyScheduleRepository;
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;

/**
 * Converts legacy weekly-schedule settings to the canonical shape.
 *
 * Canonical: keys 0..6 (0 = Saturday), each {"sessions": [...]}, plus a "meta"
 * key. Legacy rows are either a bare JSON list ([{"sessions": ...}]) or miss
 * some day keys entirely; readers treat the absent days as day-off, which does
 * not match what the owner configured and hides the row from per-day tooling.
 */
#[AsCommand(name: 'app:schedule:normalize-format', description: 'Report (and optionally rewrite) weekly schedules stored in a legacy setting format')]
class NormalizeScheduleFormatCommand extends Command
{
    private const DAY_COUNT = 7;

    public function __construct(
        private readonly WeeklyScheduleRepository $scheduleRepo,
        private readonly EntityManagerInterface   $em,
    ) {
        parent::__construct();
    }

    protected function configure(): void
    {
        $this->addOption('fix', null, InputOption::VALUE_NONE, 'Rewrite offending rows to the canonical 7-day format');
    }

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

        $rows    = [];
        $touched = 0;

        foreach ($this->scheduleRepo->findAll() as $schedule) {
            $setting = $schedule->getDaySchedule();
            // json_decode کلیدهای "0".."6" را به int تبدیل می‌کند؛ ردیف canonical کامل
            // هم list سرراست است. تنها نشانهٔ قابل‌اتکای فرمت legacy، غیبت روزهاست.
            $missing = [];
            for ($i = 0; $i < self::DAY_COUNT; $i++) {
                if (!isset($setting[$i]['sessions'])) {
                    $missing[] = $i;
                }
            }

            if ($missing === []) {
                continue;
            }

            $clinic = $schedule->getClinic();
            $rows[] = [
                $schedule->getDoctor()->getUuid(),
                $clinic === null ? 'personal' : ($clinic->getName() ?? 'clinic'),
                implode(',', $missing),
            ];

            if (!$fix) {
                continue;
            }

            $normalized = [];
            for ($i = 0; $i < self::DAY_COUNT; $i++) {
                $day = $setting[$i] ?? null;
                $normalized[$i] = is_array($day) && isset($day['sessions'])
                    ? $day
                    : ['sessions' => []];
            }

            // setSetting جای meta موجود را حفظ می‌کند؛ setMeta آن را (در نبودش با
            // DEFAULT_META) صریح در ردیف می‌نویسد تا فرمت canonical کامل شود.
            $schedule->setSetting($normalized);
            $schedule->setMeta($schedule->getMeta());
            $touched++;
        }

        if ($rows === []) {
            $io->success('All weekly schedules already use the canonical 7-day format.');

            return Command::SUCCESS;
        }

        $io->table(['doctor', 'context', 'missing days'], $rows);

        if (!$fix) {
            $io->warning(sprintf('%d legacy row(s). Re-run with --fix to rewrite them.', count($rows)));

            return Command::SUCCESS;
        }

        $this->em->flush();
        $io->success(sprintf('Rewrote %d schedule(s) to the canonical format.', $touched));

        return Command::SUCCESS;
    }
}
