<?php

namespace App\Controller\Dashboard;

use App\Entity\AuditLog;
use App\Logger\AppLogger;
use App\Repository\AccountRepository;
use App\Repository\AuditLogRepository;
use Doctrine\ORM\EntityManagerInterface;
use Knp\Component\Pager\PaginatorInterface;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;

#[Route('/crm/logs')]
class LogsController extends AbstractController
{
    public function __construct(
        private readonly EntityManagerInterface $em,
        private readonly AuditLogRepository $auditLogRepository,
        private readonly AccountRepository $accountRepository,
        private readonly PaginatorInterface $paginator,
        private readonly AppLogger $appLogger
    ) {
    }

    #[Route('', name: 'app_crm_audit_logs', methods: ['GET'])]
    public function index(Request $request): Response
    {
        $this->appLogger->record('VIEW', 'Consultation des journaux d\'audit');

        $filterAccountId = $request->query->get('account');
        $query = $this->auditLogRepository->getQueryForUser($this->getUser(), (int)$filterAccountId);

        // Export Excel
        if ($request->query->has('extract')) {
            return $this->generateExcelExport($query->getResult());
        }

        $pagination = $this->paginator->paginate(
            $query,
            $request->query->getInt('page', 1),
            25
        );

        $users = $this->isGranted('ROLE_ROOT')
            ? $this->accountRepository->findAll()
            : $this->accountRepository->findAdmin();

        return $this->render('dashboard/audit_logs.twig', [
            'logs' => $pagination,
            'users_list' => $users
        ]);
    }

    #[Route('/delete/{id}', name: 'app_crm_audit_logs_delete', methods: ['POST'])]
    #[IsGranted('ROLE_ROOT')]
    public function delete(AuditLog $log, Request $request): Response
    {
        if ($this->isCsrfTokenValid('delete' . $log->getId(), $request->request->get('_token'))) {
            $this->em->remove($log);
            $this->em->flush();

            $this->appLogger->record('DELETE', "Suppression manuelle d'une entrée de log (ID: {$log->getId()})");
            $this->addFlash('success', 'L\'entrée du journal a été supprimée.');
        } else {
            $this->addFlash('error', 'Action non autorisée (Token invalide).');
        }

        return $this->redirectToRoute('app_crm_audit_logs');
    }

    // --- PRIVATE HELPERS ---

    private function generateExcelExport(array $logs): StreamedResponse
    {
        $spreadsheet = new Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();
        $sheet->setTitle('Logs Audit');

        // Génération d'un mot de passe robuste pour le fichier
        $password = bin2hex(random_bytes(32));

        $headers = ['Date', 'Heure', 'Admin', 'Email', 'Action', 'Message', 'URL', 'Navigateur/OS', 'Signature', 'État'];
        $columns = range('A', 'J');

        foreach ($columns as $i => $col) {
            $sheet->setCellValue($col . '1', $headers[$i]);
            $sheet->getStyle($col . '1')->getFont()->setBold(true);
            $sheet->getStyle($col . '1')->getFill()->setFillType(Fill::FILL_SOLID)->getStartColor()->setARGB('F1F5F9');
        }

        $row = 2;
        /** @var AuditLog $log */
        foreach ($logs as $log) {
            $isValid = ($log->getHashCode() === $log->generateSignature());
            $account = $log->getAccount();

            $sheet->setCellValue('A' . $row, $log->getActionAt()->format('d/m/Y'));
            $sheet->setCellValue('B' . $row, $log->getActionAt()->format('H:i:s'));
            $sheet->setCellValue('C' . $row, $account ? $account->getFirstName() . ' ' . $account->getName() : 'Système');
            $sheet->setCellValue('D' . $row, $account ? $account->getEmail() : 'N/A');
            $sheet->setCellValue('E' . $row, $log->getType());
            $sheet->setCellValue('F' . $row, $log->getMessage());
            $sheet->setCellValue('G' . $row, $log->getPath());
            $sheet->setCellValue('H' . $row, $log->getUserAgent());
            $sheet->setCellValue('I' . $row, $log->getHashCode());
            $sheet->setCellValue('J' . $row, $isValid ? 'VALIDE' : 'CORROMPU');

            $sheet->getStyle('J' . $row)->getFont()->setBold(true)->getColor()->setARGB($isValid ? '059669' : 'DC2626');

            $row++;
        }

        foreach ($columns as $col) {
            $sheet->getColumnDimension($col)->setAutoSize(true);
        }

        // Protection du fichier
        $sheet->getProtection()->setPassword($password);
        $sheet->getProtection()->setSheet(true);
        $sheet->getProtection()->setSelectLockedCells(true);
        $sheet->getProtection()->setSort(false);
        $sheet->getProtection()->setInsertRows(false);

        $spreadsheet->getSecurity()->setLockStructure(true);
        $spreadsheet->getSecurity()->setWorkbookPassword($password);

        $writer = new Xlsx($spreadsheet);

        $response = new StreamedResponse(function() use ($writer) {
            $writer->save('php://output');
        });

        $fileName = 'audit_ludikevent_' . date('d-m-Y_H-i') . '.xlsx';
        $response->headers->set('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        $response->headers->set('Content-Disposition', 'attachment;filename="' . $fileName . '"');
        $response->headers->set('Cache-Control', 'max-age=0');

        return $response;
    }
}
