<?php

namespace App\Appointment\Plan\Command;

use App\Appointment\Plan\Entity\SegmentRequirement;
use App\Appointment\Plan\Entity\SegmentTemplate;
use App\Appointment\Plan\Repository\SegmentTemplateRepository;
use App\ClinicService\Repository\ServiceItemRepository;
use App\Resource\Repository\ResourceTypeRepository;
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;

/**
 * الگوی نمونهٔ بخش‌ها برای یک سرویس — نقطهٔ شروع، نه پیکربندی نهایی.
 *
 * ساختنِ چهار بخش با نیازمندی‌هایشان از صفر، اولین کاری است که کلینیک تازه باید بکند و
 * بی‌حوصله‌کننده‌ترینش. این دستور همان را در یک خط می‌سازد تا کلینیک از روی چیزی که
 * می‌بیند ویرایش کند، نه از روی صفحهٔ خالی.
 *
 * روی سرویسی که از قبل بخش دارد **کاری نمی‌کند** مگر `--force`: بازنویسی خاموشِ چیزی که
 * کلینیک خودش ساخته، بدترین رفتار ممکن است.
 */
#[AsCommand(
    name: 'app:segment:seed-templates',
    description: 'Create a starter set of appointment segments for a service.',
)]
class SeedSegmentTemplatesCommand extends Command
{
    /**
     * سه الگو از سه حوزهٔ واقعی. `items` یعنی مدت از خودِ سرویس‌های انتخاب‌شده می‌آید.
     *
     * @var array<string, list<array{name: string, minutes: int, source: string, present: bool, mergeable: bool, roles: list<string>}>>
     */
    private const PRESETS = [
        'beauty' => [
            ['name' => 'آماده‌سازی',   'minutes' => 10, 'source' => 'fixed', 'present' => true,  'mergeable' => true,  'roles' => ['room', 'operator']],
            ['name' => 'بی‌حسی موضعی', 'minutes' => 15, 'source' => 'fixed', 'present' => true,  'mergeable' => true,  'roles' => ['room']],
            ['name' => 'انتظار اثر',   'minutes' => 20, 'source' => 'fixed', 'present' => true,  'mergeable' => false, 'roles' => []],
            ['name' => 'کار اصلی',     'minutes' => 0,  'source' => 'items', 'present' => true,  'mergeable' => false, 'roles' => ['room', 'operator']],
            ['name' => 'تمیزکاری',     'minutes' => 10, 'source' => 'fixed', 'present' => false, 'mergeable' => false, 'roles' => ['room']],
        ],
        'dental' => [
            ['name' => 'معاینه',       'minutes' => 10, 'source' => 'fixed', 'present' => true,  'mergeable' => true,  'roles' => ['room', 'doctor']],
            ['name' => 'درمان',        'minutes' => 0,  'source' => 'items', 'present' => true,  'mergeable' => false, 'roles' => ['room', 'doctor']],
            ['name' => 'ضدعفونی یونیت', 'minutes' => 15, 'source' => 'fixed', 'present' => false, 'mergeable' => false, 'roles' => ['room']],
        ],
        'physio' => [
            ['name' => 'ارزیابی',      'minutes' => 15, 'source' => 'fixed', 'present' => true,  'mergeable' => true,  'roles' => ['doctor']],
            ['name' => 'جلسهٔ درمان',  'minutes' => 0,  'source' => 'items', 'present' => true,  'mergeable' => false, 'roles' => ['room', 'operator']],
            ['name' => 'استراحت',      'minutes' => 10, 'source' => 'fixed', 'present' => true,  'mergeable' => false, 'roles' => []],
        ],
    ];

    public function __construct(
        private readonly ServiceItemRepository     $services,
        private readonly SegmentTemplateRepository $templates,
        private readonly ResourceTypeRepository    $types,
        private readonly EntityManagerInterface    $em,
    ) {
        parent::__construct();
    }

    protected function configure(): void
    {
        $this
            ->addOption('service', null, InputOption::VALUE_REQUIRED, 'Service item uuid')
            ->addOption('preset', null, InputOption::VALUE_REQUIRED, 'beauty | dental | physio', 'beauty')
            ->addOption('force', null, InputOption::VALUE_NONE, 'Replace segments the service already has');
    }

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

        if (!isset(self::PRESETS[$preset])) {
            $io->error(sprintf('الگوی «%s» وجود ندارد. یکی از: %s', $preset, implode('، ', array_keys(self::PRESETS))));

            return Command::INVALID;
        }

        $uuid    = (string) $input->getOption('service');
        $service = $uuid === '' ? null : $this->services->findOneBy(['uuid' => $uuid]);

        if ($service === null) {
            $io->error('سرویس یافت نشد؛ `--service=<uuid>` را بدهید.');

            return Command::INVALID;
        }

        $existing = $this->templates->findForService($service);

        if ($existing !== [] && !$input->getOption('force')) {
            $io->warning(sprintf(
                'این سرویس از قبل %d بخش دارد. برای جایگزینی `--force` بدهید.',
                count($existing),
            ));

            return Command::SUCCESS;
        }

        foreach ($existing as $template) {
            $this->em->remove($template);
        }

        $entityType = $service->getSection()->getEntityType();
        $entityId   = $service->getSection()->getEntityId();
        $missing    = [];
        $sequence   = 0;

        foreach (self::PRESETS[$preset] as $row) {
            $template = new SegmentTemplate($service, ++$sequence, $row['name']);
            $template->setDuration($row['source'], $row['minutes']);
            $template->setPatientPresent($row['present']);
            $template->setMergeable($row['mergeable']);

            $this->em->persist($template);

            foreach ($row['roles'] as $code) {
                $type = $this->types->findOneBy(['entityType' => $entityType, 'entityId' => $entityId, 'code' => $code]);

                // نقشی که این محیط ندارد **ساخته نمی‌شود**: نوع منبع تصمیم کلینیک است و
                // ساختن خاموشش یعنی فهرست نوع‌ها پر شود از چیزهایی که کسی نخواسته.
                if ($type === null) {
                    $missing[$code] = true;
                    continue;
                }

                $this->em->persist(new SegmentRequirement($template, $type));
            }
        }

        $this->em->flush();

        $io->success(sprintf('%d بخش برای «%s» ساخته شد.', $sequence, $service->getName()));

        if ($missing !== []) {
            $io->note(sprintf(
                'این نقش‌ها در این محیط تعریف نشده‌اند و نیازمندی‌شان ساخته نشد: %s',
                implode('، ', array_keys($missing)),
            ));
        }

        return Command::SUCCESS;
    }
}
