<?php declare(strict_types = 1);

namespace idoit\Module\SyneticsJdisc\Controller;

use idoit\Module\SyneticsJdisc\Controller\Response\ArrayResponse;
use idoit\Module\SyneticsJdisc\Controller\Response\NotFoundResponse;
use idoit\Module\SyneticsJdisc\Controller\Table\SearchParams;
use idoit\Module\SyneticsJdisc\Model\JDiscProfileDao;
use isys_application;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Throwable;

class SyncProfileController
{
    private ?JDiscProfileDao $dao = null;

    /**
     * @return JDiscProfileDao
     * @throws \Exception
     */
    private function getDao(): JDiscProfileDao
    {
        if (null === $this->dao) {
            $this->dao = isys_application::instance()->container->get('idoit.jdisc.sync-profile.dao');
        }
        return $this->dao;
    }

    /**
     * @param Request $request
     * @return Response
     */
    public function find(Request $request): Response
    {
        $search = SearchParams::fromParams($request->get('params'));

        return new ArrayResponse(
            $this->getDao()->getData(null, $search),
            $this->getDao()->getCount(),
        );
    }

    /**
     * @param string $id
     * @return Response
     */
    public function get(string $id): Response
    {
        $result = $this->getDao()->get((int) $id);
        if ($result === null) {
            return new NotFoundResponse('SyncProfile');
        }
        return new JsonResponse($result);
    }

    /**
     * @param Request $request
     * @param int|null $id
     * @return Response
     */
    public function save(Request $request, ?int $id = null): Response
    {
        $data = json_decode($request->getContent(), true);
        if (empty($data)) {
            return new JsonResponse(['error' => 'No data provided'], Response::HTTP_BAD_REQUEST);
        }

        if (!empty($id)) {
            $data['id'] = $id;
        } else {
            unset($data['id']);
        }

        try {
            $profileId = $this->getDao()->saveProfile($data);
        } catch (Throwable $e) {
            return new JsonResponse(['error' => $e->getMessage()], Response::HTTP_INTERNAL_SERVER_ERROR);
        }
        if (empty($profileId)) {
            return new JsonResponse(['error' => 'Profile save error'], Response::HTTP_INTERNAL_SERVER_ERROR);
        }

        return new JsonResponse(['id' => $profileId]);
    }

    /**
     * @param int $id
     * @return Response
     */
    public function delete(int $id): Response
    {
        if ($this->getDao()->getProfile($id) === null) {
            return new NotFoundResponse('SyncProfile');
        }
        $result = $this->getDao()->delete([$id]);
        if (!$result) {
            return new JsonResponse(['error' => 'Pofile deletion error'], Response::HTTP_INTERNAL_SERVER_ERROR);
        }
        return new JsonResponse(['success' => true]);
    }

    /**
     * @param int $id
     * @return Response
     * @todo getProfile is deprecated, use get when its ready
     */
    public function getAssignments(int $id): Response
    {
        $profile = $this->getDao()->getProfile($id);
        if ($profile === null) {
            return new NotFoundResponse('SyncProfile');
        }
        $assignments = [];
        foreach ($profile['object_type_assignments'] as $assignment) {
            $assignments[$assignment['jdisc_type']] = $assignment['object_type'];
        }
        return new JsonResponse($assignments);
    }

    /**
     * @param Request $request
     * @return Response
     */
    public function export(Request $request): ?Response
    {
        $ids = $request->get('ids') ? explode(',', $request->get('ids')) : null;
        if (empty($ids) || !is_array($ids)) {
            return new JsonResponse(['error' => 'No data provided'], Response::HTTP_BAD_REQUEST);
        }

        return $this->getDao()->exportProfiles($ids);
    }

    /**
     * @param Request $request
     * @return Response
     */
    public function getFormOptions(Request $request): Response
    {
        $serverId = (int) $request->get('serverId');
        $serverDao = isys_application::instance()->container->get('idoit.jdisc.server.dao');
        $server = $serverDao->getConfiguration($serverId);
        if ($server === null) {
            return new NotFoundResponse('DiscoveryServer');
        }

        try {
            $result = $this->getDao()->getFormOptions($serverId);
            return new JsonResponse($result);
        } catch (Throwable $e) {
            return new JsonResponse(['error' => $e->getMessage()], Response::HTTP_INTERNAL_SERVER_ERROR);
        }
    }
}
