<?php

declare(strict_types=1);

namespace Ost\OstCapabilityDataExport\Controller;

use Ost\OstCapabilityDataExport\Service\EntityExportService;
use Ost\OstCapabilityDataExport\Service\EntityMetadataService;
use Ost\OstCapabilityDataExport\Service\ExportRequestFactory;
use Shopware\Core\Framework\Context;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;

#[Route(defaults: ['_routeScope' => ['api']])]
final class DataExportController extends AbstractController
{
    public function __construct(
        private readonly EntityMetadataService $metadataService,
        private readonly ExportRequestFactory $requestFactory,
        private readonly EntityExportService $exportService
    ) {
    }

    #[Route(path: '/api/_action/ost-capability-data-export/entities', name: 'api.action.ost-capability-data-export.entities', methods: ['GET'])]
    public function entities(): JsonResponse
    {
        return new JsonResponse([
            'entities' => $this->metadataService->listEntities(),
        ]);
    }

    #[Route(path: '/api/_action/ost-capability-data-export/fields/{entity}', name: 'api.action.ost-capability-data-export.fields', methods: ['GET'])]
    public function fields(string $entity): JsonResponse
    {
        return new JsonResponse([
            'entity' => $entity,
            'fields' => $this->metadataService->listExportableFields($entity),
        ]);
    }

    #[Route(path: '/api/_action/ost-capability-data-export/preview', name: 'api.action.ost-capability-data-export.preview', methods: ['POST'])]
    public function preview(Request $request, Context $context): JsonResponse
    {
        $payload = $this->decodePayload($request);
        $entity = $this->resolveEntity($payload);
        $allowedFields = $this->metadataService->listExportableFields($entity);

        $exportRequest = $this->requestFactory->fromPayload($payload, $allowedFields, 'ost-capability-data-export');
        $result = $this->exportService->preview($exportRequest, $context);

        return new JsonResponse($result);
    }

    #[Route(path: '/api/_action/ost-capability-data-export/download', name: 'api.action.ost-capability-data-export.download', methods: ['POST'])]
    public function download(Request $request, Context $context): Response
    {
        $payload = $this->decodePayload($request);
        $entity = $this->resolveEntity($payload);
        $allowedFields = $this->metadataService->listExportableFields($entity);

        $exportRequest = $this->requestFactory->fromPayload($payload, $allowedFields, 'ost-capability-data-export');
        $result = $this->exportService->export($exportRequest, $context);

        return new Response(
            $result['csv'],
            Response::HTTP_OK,
            [
                'Content-Type' => 'text/csv; charset=UTF-8',
                'Content-Disposition' => sprintf('attachment; filename="%s"', $result['fileName']),
                'Cache-Control' => 'no-store, max-age=0',
            ]
        );
    }

    /** @return array<string, mixed> */
    private function decodePayload(Request $request): array
    {
        $content = trim($request->getContent());
        if ($content === '') {
            return [];
        }

        $decoded = json_decode($content, true);

        return is_array($decoded) ? $decoded : [];
    }

    /** @param array<string, mixed> $payload */
    private function resolveEntity(array $payload): string
    {
        $entityValue = $payload['entity'] ?? null;
        if (!is_scalar($entityValue)) {
            throw new \InvalidArgumentException('Missing required field: entity');
        }

        $entity = trim((string) $entityValue);
        if ($entity === '') {
            throw new \InvalidArgumentException('Missing required field: entity');
        }

        return $entity;
    }
}
