<?php

namespace App\Command\Migration;

use App\Entity\Hardware;
use App\Entity\HardwareProfile;
use App\Entity\HardwareType;
use App\Entity\OrganizationalUnit;
use App\Model\OrganizationalUnitTypes;
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:hardware-profile', description: 'Migrate hardware and hardware profile data')]
class MigrateHardwareAndHardwareProfileCommand extends Command
{
    public function __construct(
        private readonly EntityManagerInterface $entityManager,
        private readonly ManagerRegistry $doctrine
    )
    {
        parent::__construct();
    }


    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        /** @var EntityManagerInterface $oldDatabaseEntityManager */
        $oldDatabaseEntityManager = $this->doctrine->getManager('og_1');

        $organizationalUnitRepository = $this->entityManager->getRepository(OrganizationalUnit::class);
        $hardwareProfileRepository = $this->entityManager->getRepository(HardwareProfile::class);
        $hardwareTypeRepository = $this->entityManager->getRepository(HardwareType::class);
        $hardwareRepository = $this->entityManager->getRepository(Hardware::class);

        /** Obtener los perfiles hardware de la base de datos antigua **/
        $rsmHardwareTypes = new ResultSetMapping();
        $rsmHardwareTypes->addScalarResult('idtipohardware', 'idtipohardware');
        $rsmHardwareTypes->addScalarResult('descripcion', 'descripcion');

        $hardwareTypesQuery = $oldDatabaseEntityManager->createNativeQuery('SELECT idtipohardware, descripcion FROM tipohardwares', $rsmHardwareTypes);
        $hardwareTypes = $hardwareTypesQuery->getResult();

        $output->writeln("TIPOS HARDWARE TOTAL: ". count($hardwareTypes));
        foreach ($hardwareTypes as $hardwareType){
            $hardwareProfileEntity = null;
            $hardwareProfileEntity = $hardwareTypeRepository->findOneBy(['migrationId' => $hardwareType['idtipohardware']]);
            if(!$hardwareProfileEntity){
                $hardwareProfileEntity = new HardwareType();
                $hardwareProfileEntity->setMigrationId($hardwareType['idtipohardware']);
                $hardwareProfileEntity->setName($hardwareType['descripcion']);
            }

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

        /** Obtener los hardware de la base de datos antigua **/
        $rsmHardware = new ResultSetMapping();
        $rsmHardware->addScalarResult('idhardware', 'idhardware');
        $rsmHardware->addScalarResult('idtipohardware', 'hardwares.idtipohardware');
        $rsmHardware->addScalarResult('descripcion', 'descripcion');
        $rsmHardware->addScalarResult('grupoid', 'hardwares.grupoid');
        $rsmHardware->addScalarResult('idcentro', 'hardwares.idcentro');

        $hardwareQuery = $oldDatabaseEntityManager->createNativeQuery('SELECT idhardware, hardwares.idtipohardware, hardwares.descripcion, hardwares.grupoid, hardwares.idcentro FROM hardwares LEFT JOIN tipohardwares ON hardwares.idtipohardware = tipohardwares.idtipohardware', $rsmHardware);
        $hardwareCollection = $hardwareQuery->getResult();

        $output->writeln("HARDWARE TOTAL: ". count($hardwareCollection));
        foreach ($hardwareCollection as $hardware){
            $hardwareEntity = null;
            $hardwareEntity = $hardwareRepository->findOneBy(['migrationId' => $hardware['idhardware']]);
            if(!$hardwareEntity){
                $hardwareEntity = new Hardware();
                $hardwareEntity->setMigrationId($hardware['idhardware']);
                $hardwareEntity->setDescription($hardware['descripcion']);
                $hardwareEntity->setName($hardware['descripcion']);
            }

            $hardwareType = $hardwareTypeRepository->findOneBy(['migrationId' => $hardware['hardwares.idtipohardware']]);
            if ($hardwareType){
                $hardwareEntity->setType($hardwareType);
            }

            $migrationId = $hardware['hardwares.grupoid'] === 0 ? $hardware['hardwares.idcentro'] : $hardware['hardwares.grupoid'];
            $organizationalUnit = $organizationalUnitRepository->findOneBy(['migrationId' => $migrationId]);

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

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

        /** Obtener los perfiles hardware de la base de datos antigua **/
        $rsmHardwareProfiles = new ResultSetMapping();
        $rsmHardwareProfiles->addScalarResult('idperfilhard', 'idperfilhard');
        $rsmHardwareProfiles->addScalarResult('descripcion', 'descripcion');
        $rsmHardwareProfiles->addScalarResult('comentarios', 'perfilhard.comentarios');
        $rsmHardwareProfiles->addScalarResult('grupoid', 'perfilhard.grupoid');
        $rsmHardwareProfiles->addScalarResult('idcentro', 'perfilhard.idcentro');

        $hardwareProfilesQuery = $oldDatabaseEntityManager->createNativeQuery('SELECT idperfilhard, descripcion, grupos.comentarios, perfileshard.grupoid, perfileshard.idcentro FROM perfileshard LEFT JOIN grupos ON perfileshard.grupoid = grupos.idgrupo', $rsmHardwareProfiles);
        $hardwareProfiles = $hardwareProfilesQuery->getResult();

        /** Perfiles hardware **/
        $output->writeln("PERFILES HARDWARE TOTAL: ". count($hardwareProfiles));
        foreach ($hardwareProfiles as $hardwareProfile){
            $hardwareProfileEntity = null;
            $hardwareProfileEntity = $hardwareProfileRepository->findOneBy(['migrationId' => $hardwareProfile['idperfilhard']]);
            if(!$hardwareProfileEntity){
                $hardwareProfileEntity = new HardwareProfile();
                $hardwareProfileEntity->setMigrationId($hardwareProfile['idperfilhard']);
                $hardwareProfileEntity->setDescription($hardwareProfile['descripcion']);
                $hardwareProfileEntity->setComments($hardwareProfile['perfilhard.comentarios']);
            }

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

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

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

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

        /** Obtener los hardware, y asignarselos a los perfiles hardware **/
        $rsmHardwareProfilesRelation = new ResultSetMapping();
        $rsmHardwareProfilesRelation->addScalarResult('idperfilhard', 'idperfilhard');
        $rsmHardwareProfilesRelation->addScalarResult('idhardware', 'idhardware');

        $hardwareProfilesQuery = $oldDatabaseEntityManager->createNativeQuery('SELECT idperfilhard, idhardware FROM perfileshard_hardwares', $rsmHardwareProfilesRelation);
        $hardwareProfileRelations = $hardwareProfilesQuery->getResult();

        $output->writeln("PERFILES HARDWARE RELACIONES TOTAL: ". count($hardwareProfileRelations));
        foreach ($hardwareProfileRelations as $hardwareProfileRelation){
            $hardwareProfileEntity = $hardwareProfileRepository->findOneBy(['migrationId' => $hardwareProfileRelation['idperfilhard']]);
            $hardwareEntity = $hardwareRepository->findOneBy(['migrationId' => $hardwareProfileRelation['idhardware']]);

            if ($hardwareProfileEntity && $hardwareEntity){
                $hardwareProfileEntity->addHardwareCollection($hardwareEntity);
                $this->entityManager->persist($hardwareProfileEntity);
            }
        }


        $this->entityManager->flush();

        return Command::SUCCESS;
    }
}
