<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Form;
use App\Models\FormSubmission;
use App\Notifications\FormSubmittedNotification;
use App\Services\Forms\FormSubmissionService;
use App\Services\HrmsNotificationService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\ValidationException;

class FormController extends Controller
{
    public function __construct(
        protected FormSubmissionService $submissionService,
        protected HrmsNotificationService $notifier
    ) {}

    public function index(Request $request): JsonResponse
    {
        $forms = Form::query()
            ->where('status', 'published')
            ->orderBy('name')
            ->paginate($request->integer('per_page', 15));

        return response()->json($forms);
    }

    public function show(Form $form): JsonResponse
    {
        $this->assertPublishedForm($form);

        return response()->json($form);
    }

    public function submit(Request $request, Form $form): JsonResponse
    {
        $this->assertPublishedForm($form);

        try {
            $responses = $this->submissionService->validateAndNormalize($form, $request->all());
        } catch (ValidationException $e) {
            return response()->json(['message' => 'Validation failed.', 'errors' => $e->errors()], 422);
        }

        $user = Auth::user();
        $submission = FormSubmission::create([
            'company_id' => $user->company_id,
            'form_id' => $form->id,
            'user_id' => $user->id,
            'responses' => $responses,
            'status' => 'submitted',
        ]);

        if ($form->company_id) {
            $this->notifier->notifyUsersWithAnyPermission(
                (int) $form->company_id,
                ['documents_view'],
                new FormSubmittedNotification($submission->load(['form', 'user'])),
                [(int) $user->id]
            );
        }

        return response()->json($submission->load(['form', 'user']), 201);
    }

    public function mySubmissions(Request $request): JsonResponse
    {
        $submissions = FormSubmission::with('form')
            ->where('user_id', Auth::id())
            ->orderByDesc('created_at')
            ->paginate($request->integer('per_page', 15));

        return response()->json($submissions);
    }

    public function submissionsIndex(Request $request): JsonResponse
    {
        abort_unless(Auth::user()?->hasPermission('documents_view'), 403);

        $query = FormSubmission::with(['form', 'user'])->orderByDesc('created_at');

        if ($request->filled('form_id')) {
            $query->where('form_id', $request->integer('form_id'));
        }

        return response()->json($query->paginate($request->integer('per_page', 15)));
    }

    public function submissionsShow(FormSubmission $formSubmission): JsonResponse
    {
        abort_unless(Auth::user()?->hasPermission('documents_view'), 403);
        $this->assertTenantSubmission($formSubmission);

        return response()->json($formSubmission->load(['form', 'user']));
    }

    protected function assertPublishedForm(Form $form): void
    {
        $companyId = Auth::user()?->company_id;
        if ($companyId && (int) $form->company_id !== (int) $companyId) {
            abort(403);
        }

        abort_unless($form->status === 'published', 404);
        abort_if(empty($form->fields), 422, 'This form has no fields configured yet.');
    }

    protected function assertTenantSubmission(FormSubmission $submission): void
    {
        $companyId = Auth::user()?->company_id;
        if ($companyId && (int) $submission->company_id !== (int) $companyId) {
            abort(403);
        }
    }
}
