<?php

namespace App\Command\Migration;

use App\Entity\OperativeSystem;
use App\Entity\OrganizationalUnit;
use App\Entity\Software;
use App\Entity\SoftwareProfile;
use App\Model\OrganizationalUnitTypes;
use App\Model\SoftwareTypes;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Query\ResultSetMapping;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

#[AsCommand(name: 'opengnsys:migration:software-profile', description: 'Migrate software and software profile data')]
class MigrateSoftwareAndSoftwareProfileCommand extends Command
{
    public function __construct(
        private readonly EntityManagerInterface $entityManager,
        private readonly ManagerRegistry $doctrine
    )
    {
        parent::__construct();
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        ini_set('memory_limit', '-1');


        /** @var EntityManagerInterface $oldDatabaseEntityManager */
        $oldDatabaseEntityManager = $this->doctrine->getManager('og_1');

        $organizationalUnitRepository = $this->entityManager->getRepository(OrganizationalUnit::class);
        $operativeSystemRepository = $this->entityManager->getRepository(OperativeSystem::class);
        $softwareProfileRepository = $this->entityManager->getRepository(SoftwareProfile::class);
        $softwareRepository = $this->entityManager->getRepository(Software::class);

        /** Obtener los software de la base de datos antigua **/
        $rsmSoftware = new ResultSetMapping();
        $rsmSoftware->addScalarResult('idsoftware', 'idsoftware');
        $rsmSoftware->addScalarResult('descripcion', 'descripcion');
        $rsmSoftware->addScalarResult('grupoid', 'softwares.grupoid');
        $rsmSoftware->addScalarResult('idcentro', 'softwares.idcentro');
        $rsmSoftware->addScalarResult('idtiposoftware', 'softwares.idtiposoftware');

        $softwareQuery = $oldDatabaseEntityManager->createNativeQuery('SELECT idsoftware, softwares.idtiposoftware, softwares.descripcion, softwares.grupoid, softwares.idcentro FROM softwares ', $rsmSoftware);
        $softwareCollection = $softwareQuery->getResult();

        $output->writeln("SOFTWARE TOTAL: ". count($softwareCollection));
        foreach ($softwareCollection as $software){
            $softwareEntity = null;
            $softwareEntity = $softwareRepository->findOneBy(['migrationId' => $software['idsoftware']]);
            if(!$softwareEntity){

                $type = match ($software['softwares.idtiposoftware']) {
                    1 => SoftwareTypes::OPERATIVE_SYSTEM,
                    2 => SoftwareTypes::APPLICATION,
                    3 => SoftwareTypes::FILE,
                    default => SoftwareTypes::APPLICATION,
                };

                $softwareEntity = new Software();
                $softwareEntity->setMigrationId($software['idsoftware']);
                $softwareEntity->setDescription($software['descripcion']);
                $softwareEntity->setName($software['descripcion']);
                $softwareEntity->setType($type);
            }

            $migrationId = match ($software['softwares.grupoid']) {
                0 => OrganizationalUnitTypes::ORGANIZATIONAL_UNIT . '-' . $software['softwares.idcentro'],
                default => OrganizationalUnitTypes::CLASSROOMS_GROUP . '-' . $software['softwares.grupoid'],
            };

            $organizationalUnit = $organizationalUnitRepository->findOneBy(['migrationId' => $migrationId]);

            /*
            if ($organizationalUnit){
                $softwareEntity->setOrganizationalUnit($organizationalUnit);
            }*/

            $this->entityManager->persist($softwareEntity);
        }

        /** Obtener los perfiles software de la base de datos antigua **/
        $rsmSoftwareProfiles = new ResultSetMapping();
        $rsmSoftwareProfiles->addScalarResult('idperfilsoft', 'idperfilsoft');
        $rsmSoftwareProfiles->addScalarResult('descripcion', 'descripcion');
        $rsmSoftwareProfiles->addScalarResult('comentarios', 'perfilessoft.comentarios');
        $rsmSoftwareProfiles->addScalarResult('grupoid', 'perfilessoft.grupoid');
        $rsmSoftwareProfiles->addScalarResult('idcentro', 'perfilessoft.idcentro');
        $rsmSoftwareProfiles->addScalarResult('idnombreso', 'perfilessoft.idnombreso');


        $softwareProfilesQuery = $oldDatabaseEntityManager->createNativeQuery('SELECT idperfilsoft, descripcion, grupos.comentarios, perfilessoft.grupoid, perfilessoft.idcentro, perfilessoft.idnombreso FROM perfilessoft LEFT JOIN grupos ON perfilessoft.grupoid = grupos.idgrupo', $rsmSoftwareProfiles);
        $softwareProfiles = $softwareProfilesQuery->getResult();

        /** Perfiles software **/
        $output->writeln("PERFILES SOFTWARE TOTAL: ". count($softwareProfiles));
        foreach ($softwareProfiles as $softwareProfile){
            $softwareProfileEntity = null;
            $softwareProfileEntity = $softwareProfileRepository->findOneBy(['migrationId' => $softwareProfile['idperfilsoft']]);
            if(!$softwareProfileEntity){
                $softwareProfileEntity = new SoftwareProfile();
                $softwareProfileEntity->setMigrationId($softwareProfile['idperfilsoft']);
                $softwareProfileEntity->setDescription($softwareProfile['descripcion']);
                $softwareProfileEntity->setComments($softwareProfile['perfilessoft.comentarios']);
            }

            $migrationId = match ($softwareProfile['perfilessoft.grupoid']) {
                0 => OrganizationalUnitTypes::ORGANIZATIONAL_UNIT . '-' . $softwareProfile['perfilessoft.idcentro'],
                default => OrganizationalUnitTypes::CLASSROOMS_GROUP . '-' . $softwareProfile['perfilessoft.grupoid'],
            };

            $organizationalUnit = $organizationalUnitRepository->findOneBy(['migrationId' => $migrationId]);

            if ($organizationalUnit){
                $softwareProfileEntity->setOrganizationalUnit($organizationalUnit);
            }

            $operativeSystem = $operativeSystemRepository->findOneBy(['migrationId' => $softwareProfile['perfilessoft.idnombreso']]);

            if ($operativeSystem){
                $softwareProfileEntity->setOperativeSystem($operativeSystem);
            }

            $this->entityManager->persist($softwareProfileEntity);
        }

        /** Obtener los software, y asignarselos a los perfiles software **/
        $rsmSoftwareProfilesRelation = new ResultSetMapping();
        $rsmSoftwareProfilesRelation->addScalarResult('idperfilsoft', 'idperfilsoft');
        $rsmSoftwareProfilesRelation->addScalarResult('idsoftware', 'idsoftware');

        $softwareProfilesQuery = $oldDatabaseEntityManager->createNativeQuery('SELECT idperfilsoft, idsoftware FROM perfilessoft_softwares', $rsmSoftwareProfilesRelation);
        $softwareProfileRelations = $softwareProfilesQuery->getResult();

        $output->writeln("PERFILES SOFTWARE RELACIONES TOTAL: ". count($softwareProfileRelations));
        foreach ($softwareProfileRelations as $softwareProfileRelation){
            $softwareProfileEntity = $softwareProfileRepository->findOneBy(['migrationId' => $softwareProfileRelation['idperfilsoft']]);
            $softwareEntity = $softwareRepository->findOneBy(['migrationId' => $softwareProfileRelation['idsoftware']]);

            if ($softwareProfileEntity && $softwareEntity){
                $softwareProfileEntity->addSoftwareCollection($softwareEntity);
                $this->entityManager->persist($softwareProfileEntity);
            }
        }

        $this->entityManager->flush();

        return Command::SUCCESS;
    }
}