<?php

declare(strict_types=1);

namespace App\Mcp\Tool\Slot;

use App\Entity\ComposantPieceSlot;
use App\Entity\ComposantProductSlot;
use App\Entity\ComposantSubcomponentSlot;
use App\Entity\PieceProductSlot;
use App\Mcp\Tool\McpToolHelper;
use Doctrine\ORM\EntityManagerInterface;
use Mcp\Capability\Attribute\McpTool;
use Mcp\Schema\Result\CallToolResult;

#[McpTool(
    name: 'list_slots',
    description: 'List all slots for a composant or piece. Composants have piece/product/subcomponent slots. Pieces have product slots only.',
)]
class ListSlotsTool
{
    use McpToolHelper;

    public function __construct(
        private readonly EntityManagerInterface $em,
    ) {}

    public function __invoke(string $entityType, string $entityId): CallToolResult
    {
        if ('composant' === $entityType) {
            return $this->listComposantSlots($entityId);
        }

        if ('piece' === $entityType) {
            return $this->listPieceSlots($entityId);
        }

        $this->mcpError('validation', "entityType must be 'composant' or 'piece', got '{$entityType}'.");
    }

    private function listComposantSlots(string $composantId): CallToolResult
    {
        $pieceSlots = $this->em->createQueryBuilder()
            ->select(
                'ps.id',
                "'piece' AS slotType",
                'ps.position',
                'ps.quantity',
                'tp.name AS typeName',
                'sp.id AS selectedEntityId',
                'sp.name AS selectedEntityName',
            )
            ->from(ComposantPieceSlot::class, 'ps')
            ->leftJoin('ps.typePiece', 'tp')
            ->leftJoin('ps.selectedPiece', 'sp')
            ->where('IDENTITY(ps.composant) = :cid')
            ->setParameter('cid', $composantId)
            ->orderBy('ps.position', 'ASC')
            ->getQuery()
            ->getArrayResult()
        ;

        $productSlots = $this->em->createQueryBuilder()
            ->select(
                'prs.id',
                "'product' AS slotType",
                'prs.position',
                'tp.name AS typeName',
                'sp.id AS selectedEntityId',
                'sp.name AS selectedEntityName',
            )
            ->from(ComposantProductSlot::class, 'prs')
            ->leftJoin('prs.typeProduct', 'tp')
            ->leftJoin('prs.selectedProduct', 'sp')
            ->where('IDENTITY(prs.composant) = :cid')
            ->setParameter('cid', $composantId)
            ->orderBy('prs.position', 'ASC')
            ->getQuery()
            ->getArrayResult()
        ;

        $subSlots = $this->em->createQueryBuilder()
            ->select(
                'ss.id',
                "'subcomponent' AS slotType",
                'ss.position',
                'ss.alias',
                'tc.name AS typeName',
                'sc.id AS selectedEntityId',
                'sc.name AS selectedEntityName',
            )
            ->from(ComposantSubcomponentSlot::class, 'ss')
            ->leftJoin('ss.typeComposant', 'tc')
            ->leftJoin('ss.selectedComposant', 'sc')
            ->where('IDENTITY(ss.composant) = :cid')
            ->setParameter('cid', $composantId)
            ->orderBy('ss.position', 'ASC')
            ->getQuery()
            ->getArrayResult()
        ;

        $slots = array_merge($pieceSlots, $productSlots, $subSlots);

        return $this->jsonResponse([
            'entityType' => 'composant',
            'entityId'   => $composantId,
            'slots'      => $slots,
            'total'      => count($slots),
        ]);
    }

    private function listPieceSlots(string $pieceId): CallToolResult
    {
        $slots = $this->em->createQueryBuilder()
            ->select(
                'pps.id',
                "'product' AS slotType",
                'pps.position',
                'tp.name AS typeName',
                'sp.id AS selectedEntityId',
                'sp.name AS selectedEntityName',
            )
            ->from(PieceProductSlot::class, 'pps')
            ->leftJoin('pps.typeProduct', 'tp')
            ->leftJoin('pps.selectedProduct', 'sp')
            ->where('IDENTITY(pps.piece) = :pid')
            ->setParameter('pid', $pieceId)
            ->orderBy('pps.position', 'ASC')
            ->getQuery()
            ->getArrayResult()
        ;

        return $this->jsonResponse([
            'entityType' => 'piece',
            'entityId'   => $pieceId,
            'slots'      => $slots,
            'total'      => count($slots),
        ]);
    }
}
