<?php

namespace App\Command;

use App\Utils\CustomEntityManager;
use phpseclib3\Net\SFTP;
use Psr\Log\LoggerInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use App\Entity\Adherent;
use App\Entity\Prestataire;
use App\Entity\Flux;

class ExportAndUploadDataCommand extends Command
{
    protected static $defaultName = 'kohinos:ssa:export-and-upload-data';

    protected $em;
    private LoggerInterface $logger;
    private string $host;
    private string $user;
    private string $password;
    private string $remotePath;
    private string $localPath;

    public function __construct(
        CustomEntityManager $em,
        LoggerInterface $logger,
        string $host,
        string $user,
        string $password,
        string $remotePath,
        string $localPath
    ) {
        parent::__construct();
        $this->em = $em;
        $this->logger = $logger;
        $this->host = $host;
        $this->user = $user;
        $this->password = $password;
        $this->remotePath = $remotePath;
        $this->localPath = $localPath;
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        try {
            // 1. Get data
            $data = [
                "adherents" => [],
                "prestataires" => [],
                "flux" => [],
            ];

            $adherents = $this->em->getRepository(Adherent::class)->findAllForSsaExport();
            foreach ($adherents as $a) {
                $adh = [
                    "lastname" => $a->getUser()->getLastname(),
                    "firstname" => $a->getUser()->getFirstname(),
                    "email" => $a->getUser()->getEmail(),
                    "id" => $a->getId(),
                    "phone" => $a->getUser()->getPhone(),
                    "address" => $a->getGeoloc() == null ? null : [
                        "address" => $a->getGeoloc()->getAdresse(),
                        "zip" => $a->getGeoloc()->getCpostal(),
                        "city" => $a->getGeoloc()->getVille(),
                    ],
                    "household_composition" => $a->getHouseholdCount(),
                    "cotisation_amount" => $a->getCotisationAmount(),
                    "allocation_amount" => $a->getAllocationAmount(),
                    "cohort" => $a->getExternalData() == null ? null : $a->getExternalData()->getCohort(),
                    "external_id" => $a->getExternalData() == null ? null : $a->getExternalData()->getExternalId(),
                    "dated_data" => [],
                ];

                foreach ($a->getExternalDatedDataCollection() as $dated_data) {
                    $adh["dated_data"][] = [
                        "year" => $dated_data->getYear(),
                        "annual_income" => $dated_data->getAnnualIncome(),
                        "monthly_income" => $dated_data->getMonthlyIncome(),
                    ];
                }

                $data["adherents"][] = $adh;
            }

            $prestataires = $this->em->getRepository(Prestataire::class)->findAllForSsaExport();
            foreach ($prestataires as $p) {
                $presta = [
                    "raison" => $p->getRaison(),
                    "addresses" => [],
                    "rubrics" => [],
                    "administrators" => $p->getGestionnairesEmailsArray(),
                ];

                foreach ($p->getGeolocs() as $g) {
                    $presta["addresses"][] = [
                        "address" => $a->getGeoloc()->getAdresse(),
                        "zip" => $a->getGeoloc()->getCpostal(),
                        "city" => $a->getGeoloc()->getVille(),
                    ];
                }

                foreach ($p->getRubriques() as $r) {
                    $presta["rubrics"][] = [
                        "name" => $r->getName()
                    ];
                }


                $data["prestataires"][] = $presta;
            }
            
            $flux = $this->em->getRepository(Flux::class)->findAll();
            foreach ($flux as $f) {
                $data["flux"][] = [
                    "date" => $f->getCreatedAt() ? $f->getCreatedAt()->format('Y-m-d H:i:s') : '',
                    "amount" => $f->getMontant(),
                    "type" => $f->getType(),
                    "sender_id" => empty($f->getExpediteur()) ? null : $f->getExpediteur()->getId(),
                    "recipient_id" => empty($f->getDestinataire()) ? null : $f->getDestinataire()->getId(),
                ];
            }

            // 2. Génération JSON
            if (!is_dir($this->localPath)) {
                mkdir($this->localPath, 0777, true);
            }

            if ('dev' == $_ENV['APP_ENV']) {
                $filename = 'test_export_' . date('Ymd_His') . '.json';
            } else if (true == $_ENV['PREPROD_ENV']) {
                $filename = 'preprod_export_' . date('Ymd_His') . '.json';
            } else {
                $filename = 'export_' . date('Ymd_His') . '.json';
            }
            $filePath = $this->localPath . '/' . $filename;
            file_put_contents($filePath, json_encode($data, JSON_PRETTY_PRINT));

            $output->writeln('Fichier exporté : ' . $filePath);

            // 3. Connexion SSH
            $sftp = new SFTP($this->host);

            if (!$sftp->login($this->user, $this->password)) {
                throw new \Exception('Échec authentification SSH');
            }

            // 4. Upload
            $remoteFile = rtrim($this->remotePath, '/') . '/' . $filename;

            if (!$sftp->put($remoteFile, $filePath, SFTP::SOURCE_LOCAL_FILE)) {
                throw new \Exception('Échec upload SFTP');
            }

            $output->writeln('Upload réussi');

            // 5. Delete local file
            unlink($filePath);
            $output->writeln('Fichier supprimé : ' . $filePath);

            $this->logger->info('Export données SSA réussi');

            return 0;
        } catch (\Throwable $e) {
            $this->logger->error('Erreur export', [
                'message' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);

            $output->writeln('<error>' . $e->getMessage() . '</error>');

            return 0;
        }
    }
}