<?php

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\MainBundle\Controller;

use Chill\MainBundle\Repository\UserRepositoryInterface;
use League\Csv\Writer;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Security;
use Symfony\Contracts\Translation\TranslatorInterface;

final readonly class UserExportController
{
    public function __construct(
        private UserRepositoryInterface $userRepository,
        private Security $security,
        private TranslatorInterface $translator,
    ) {}

    /**
     * @throws \League\Csv\CannotInsertRecord
     * @throws \League\Csv\Exception
     * @throws \League\Csv\UnavailableStream
     */
    #[Route(path: '/{_locale}/admin/main/users/export/list.{_format}', requirements: ['_format' => 'csv'], name: 'chill_main_users_export_list')]
    public function userList(Request $request, string $_format = 'csv'): StreamedResponse
    {
        if (!$this->security->isGranted('ROLE_ADMIN')) {
            throw new AccessDeniedHttpException('Only ROLE_ADMIN can export this list');
        }

        $users = $this->userRepository->findAllAsArray($request->getLocale());

        $csv = Writer::from('php://temp', 'r+');
        $csv->insertOne(
            array_map(
                fn (string $e) => $this->translator->trans('admin.users.export.'.$e),
                [
                    'id',
                    //  'username',
                    'email',
                    'enabled',
                    'civility_id',
                    'civility_abbreviation',
                    'civility_name',
                    'label',
                    'mainCenter_id',
                    'mainCenter_name',
                    'mainScope_id',
                    'mainScope_name',
                    'userJob_id',
                    'userJob_name',
                    'currentLocation_id',
                    'currentLocation_name',
                    'mainLocation_id',
                    'mainLocation_name',
                    'absenceStart',
                ]
            )
        );
        $csv->addFormatter(fn (array $row) => null !== ($row['absenceStart'] ?? null) ? array_merge($row, ['absenceStart' => $row['absenceStart']->format('Y-m-d')]) : $row);
        /* @phpstan-ignore-next-line as phpstan seem to ignore that we transform datetime into string */
        $csv->insertAll($users);

        return new StreamedResponse(
            function () use ($csv) {
                foreach ($csv->chunk(1024) as $chunk) {
                    echo $chunk;
                    flush();
                }
            },
            Response::HTTP_OK,
            [
                'Content-Encoding' => 'none',
                'Content-Type' => 'text/csv; charset=UTF-8',
                'Content-Disposition' => 'attachment; users.csv',
            ]
        );
    }

    /**
     * @throws \League\Csv\CannotInsertRecord
     * @throws \League\Csv\Exception
     * @throws \League\Csv\UnavailableStream
     */
    #[Route(path: '/{_locale}/admin/main/users/export/permissions.{_format}', requirements: ['_format' => 'csv'], name: 'chill_main_users_export_permissions')]
    public function userPermissionsList(string $_format = 'csv'): StreamedResponse
    {
        if (!$this->security->isGranted('ROLE_ADMIN')) {
            throw new AccessDeniedHttpException('Only ROLE_ADMIN can export this list');
        }

        $userPermissions = $this->userRepository->findAllUserACLAsArray();

        $csv = Writer::from('php://temp', 'r+');
        $csv->insertOne(
            array_map(
                fn (string $e) => $this->translator->trans('admin.users.export.'.$e),
                [
                    'id',
                    'username',
                    'email',
                    'label',
                    'enabled',
                    'center_id',
                    'center_name',
                    'permissionsGroup_id',
                    'permissionsGroup_name',
                ]
            )
        );
        $csv->insertAll($userPermissions);

        return new StreamedResponse(
            function () use ($csv) {
                foreach ($csv->chunk(1024) as $chunk) {
                    echo $chunk;
                    flush();
                }
            },
            Response::HTTP_OK,
            [
                'Content-Encoding' => 'none',
                'Content-Type' => 'text/csv; charset=UTF-8',
                'Content-Disposition' => 'attachment; users.csv',
            ]
        );
    }
}
