<?php

declare(strict_types=1);

namespace App\Http\Controllers\Api\NovaCards;

use App\Http\Controllers\Controller;
use App\Models\NovaCard;
use App\Models\NovaCardCreatorPreset;
use App\Services\NovaCards\NovaCardCreatorPresetService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class NovaCardPresetController extends Controller
{
    public function __construct(
        private readonly NovaCardCreatorPresetService $presets,
    ) {
    }

    public function index(Request $request): JsonResponse
    {
        $type = $request->query('type');
        $items = $this->presets->listForUser(
            $request->user(),
            is_string($type) && in_array($type, NovaCardCreatorPreset::TYPES, true) ? $type : null,
        );

        return response()->json([
            'data' => $items->map(fn ($p) => $this->presets->toArray($p))->values()->all(),
        ]);
    }

    public function store(Request $request): JsonResponse
    {
        $data = $request->validate([
            'name' => ['required', 'string', 'max:120'],
            'preset_type' => ['required', 'string', 'in:' . implode(',', NovaCardCreatorPreset::TYPES)],
            'config_json' => ['required', 'array'],
            'is_default' => ['sometimes', 'boolean'],
        ]);

        $preset = $this->presets->create($request->user(), $data);

        return response()->json([
            'data' => $this->presets->toArray($preset),
        ], Response::HTTP_CREATED);
    }

    public function update(Request $request, int $id): JsonResponse
    {
        $preset = NovaCardCreatorPreset::query()
            ->where('user_id', $request->user()->id)
            ->findOrFail($id);

        $data = $request->validate([
            'name' => ['sometimes', 'string', 'max:120'],
            'config_json' => ['sometimes', 'array'],
            'is_default' => ['sometimes', 'boolean'],
        ]);

        $preset = $this->presets->update($request->user(), $preset, $data);

        return response()->json([
            'data' => $this->presets->toArray($preset),
        ]);
    }

    public function destroy(Request $request, int $id): JsonResponse
    {
        $preset = NovaCardCreatorPreset::query()->findOrFail($id);

        $this->presets->delete($request->user(), $preset);

        return response()->json([
            'ok' => true,
        ]);
    }

    /**
     * Capture a preset from an existing published card.
     */
    public function captureFromCard(Request $request, int $cardId): JsonResponse
    {
        $card = NovaCard::query()
            ->where('user_id', $request->user()->id)
            ->findOrFail($cardId);

        $data = $request->validate([
            'name' => ['required', 'string', 'max:120'],
            'preset_type' => ['required', 'string', 'in:' . implode(',', NovaCardCreatorPreset::TYPES)],
        ]);

        $preset = $this->presets->captureFromCard(
            $request->user(),
            $card,
            $data['name'],
            $data['preset_type'],
        );

        return response()->json([
            'data' => $this->presets->toArray($preset),
        ], Response::HTTP_CREATED);
    }

    /**
     * Apply a saved preset to a draft card, returning a project_json patch.
     */
    public function applyToCard(Request $request, int $presetId, int $cardId): JsonResponse
    {
        $preset = NovaCardCreatorPreset::query()
            ->where('user_id', $request->user()->id)
            ->findOrFail($presetId);

        $card = NovaCard::query()
            ->where('user_id', $request->user()->id)
            ->whereIn('status', [NovaCard::STATUS_DRAFT, NovaCard::STATUS_PUBLISHED])
            ->findOrFail($cardId);

        $currentProject = is_array($card->project_json) ? $card->project_json : [];
        $patch = $this->presets->applyToProjectPatch($preset, $currentProject);

        return response()->json([
            'data' => [
                'preset' => $this->presets->toArray($preset),
                'project_patch' => $patch,
            ],
        ]);
    }
}
