<?php

namespace App\Http\Controllers\Api\Badges;

use App\Http\Controllers\Controller;
use App\Services\Badges\BadgeFormDataService;
use App\Services\Badges\BadgePdfService;
use App\Services\Badges\BadgePrintLogService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Throwable;

class BadgeController extends Controller
{
    public function __construct(
        protected BadgePdfService $badgePdfService,
        protected BadgePrintLogService $badgePrintLogService,
        protected BadgeFormDataService $badgeFormDataService
    ) {
    }

    public function generatePdf(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'user_ids' => ['required', 'array', 'min:1'],
            'user_ids.*' => ['integer', 'min:1'],
            'school_year' => ['nullable', 'string', 'max:50'],
            'roles' => ['nullable', 'array'],
            'classes' => ['nullable', 'array'],
        ]);

        if ($validator->fails()) {
            return response()->json([
                'message' => 'Validation failed.',
                'errors' => $validator->errors(),
            ], 422);
        }

        $data = $validator->validated();

        return $this->badgePdfService->generate(
            userIds: $data['user_ids'] ?? [],
            schoolYear: $data['school_year'] ?? null,
            rolesMap: $data['roles'] ?? [],
            classesMap: $data['classes'] ?? [],
            actorId: optional($request->user())->id
        );
    }

    public function printStatus(Request $request): JsonResponse
    {
        try {
            return response()->json([
                'ok' => true,
                'data' => $this->badgePrintLogService->getStatus(
                    $this->parseUserIds($request),
                    $request->input('school_year')
                ),
            ]);
        } catch (Throwable) {
            return response()->json([
                'ok' => false,
                'error' => 'Failed to query status',
            ], 500);
        }
    }

    public function logPrint(Request $request): JsonResponse
    {
        try {
            $validator = Validator::make($request->all(), [
                'user_ids' => ['required', 'array', 'min:1'],
                'user_ids.*' => ['integer', 'min:1'],
                'school_year' => ['nullable', 'string', 'max:50'],
                'roles' => ['nullable', 'array'],
                'classes' => ['nullable', 'array'],
            ]);

            if ($validator->fails()) {
                return response()->json([
                    'message' => 'Validation failed.',
                    'errors' => $validator->errors(),
                ], 422);
            }

            $data = $validator->validated();

            $inserted = $this->badgePrintLogService->log(
                userIds: $data['user_ids'] ?? [],
                actorId: optional($request->user())->id,
                schoolYear: $data['school_year'] ?? null,
                rolesMap: $data['roles'] ?? [],
                classesMap: $data['classes'] ?? []
            );

            return response()->json([
                'ok' => true,
                'inserted' => $inserted,
            ]);
        } catch (Throwable $e) {
            return response()->json([
                'ok' => false,
                'error' => $e->getMessage(),
            ], 500);
        }
    }

    public function formData(Request $request): JsonResponse
    {
        return response()->json([
            'ok' => true,
            'data' => $this->badgeFormDataService->build(
                schoolYear: $request->input('school_year'),
                selectedUserIds: $this->parseUserIds($request),
                activeRole: $request->input('active_role')
            ),
        ]);
    }

    private function parseUserIds(Request $request): array
    {
        $userIds = $request->input('user_ids', $request->query('user_ids', []));

        if (is_string($userIds)) {
            $userIds = array_filter(array_map('trim', explode(',', $userIds)), 'strlen');
        } elseif (!is_array($userIds)) {
            $userIds = $userIds ? [$userIds] : [];
        }

        $userIds = array_values(array_unique(array_map(static fn ($v) => (int) $v, $userIds)));

        return array_values(array_filter($userIds, static fn ($v) => $v > 0));
    }
}
