<?php

use App\Models\Forms\Form;
use App\Models\Forms\FormSubmission;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;

it('can submit form partially and complete it later using submission hash', function () {
    $user = $this->actingAsProUser();
    $workspace = $this->createUserWorkspace($user);
    $form = $this->createForm($user, $workspace, [
        'enable_partial_submissions' => true
    ]);

    // Initial partial submission
    $formData = $this->generateFormSubmissionData($form, ['text' => 'Initial Text']);
    $formData['is_partial'] = true;

    $partialResponse = $this->postJson(route('forms.answer', $form->slug), $formData)
        ->assertSuccessful()
        ->assertJson([
            'type' => 'success',
        ]);

    $submissionHash = $partialResponse->json('submission_hash');
    expect($submissionHash)->not->toBeEmpty();

    // Complete the submission using the hash
    $completeData = $this->generateFormSubmissionData($form, [
        'text' => 'Complete Text',
        'email' => 'test@example.com'
    ]);
    $completeData['submission_hash'] = $submissionHash;

    $this->postJson(route('forms.answer', $form->slug), $completeData)
        ->assertSuccessful()
        ->assertJson([
            'type' => 'success',
            'message' => 'Form submission saved.',
        ]);

    // Verify final submission state
    $submission = FormSubmission::first();
    expect($submission->status)->toBe(FormSubmission::STATUS_COMPLETED);
    expect($submission->data)->toHaveKey(array_key_first($completeData));
});

it('can update partial submission multiple times', function () {
    $user = $this->actingAsProUser();
    $workspace = $this->createUserWorkspace($user);
    $form = $this->createForm($user, $workspace, [
        'enable_partial_submissions' => true
    ]);
    $targetField = collect($form->properties)->where('name', 'Name')->first();

    // First partial submission
    $formData = $this->generateFormSubmissionData($form, [$targetField['id'] => 'First Draft']);
    $formData['is_partial'] = true;

    $firstResponse = $this->postJson(route('forms.answer', $form->slug), $formData)
        ->assertSuccessful();

    $submissionHash = $firstResponse->json('submission_hash');

    // Second partial update
    $secondData = $this->generateFormSubmissionData($form, [$targetField['id'] => 'Second Draft']);
    $secondData['is_partial'] = true;
    $secondData['submission_hash'] = $submissionHash;

    $this->postJson(route('forms.answer', $form->slug), $secondData)
        ->assertSuccessful();

    // Verify submission was updated
    $submission = FormSubmission::first();
    expect($submission->status)->toBe(FormSubmission::STATUS_PARTIAL);
    expect($submission->data)->toHaveKey(array_key_first($secondData));
    expect($submission->data[array_key_first($secondData)])->toBe('Second Draft');
});

it('calculates stats correctly for partial vs completed submissions', function () {
    $user = $this->actingAsProUser();
    $workspace = $this->createUserWorkspace($user);
    $form = $this->createForm($user, $workspace, [
        'enable_partial_submissions' => true
    ]);

    // Create partial submission
    $partialData = $this->generateFormSubmissionData($form, ['text' => 'Partial']);
    $partialData['is_partial'] = true;
    $this->postJson(route('forms.answer', $form->slug), $partialData);

    // Create completed submission
    $completeData = $this->generateFormSubmissionData($form, ['text' => 'Complete']);
    $this->postJson(route('forms.answer', $form->slug), $completeData);

    // Verify stats
    $form->refresh();
    expect($form->submissions()->where('status', FormSubmission::STATUS_PARTIAL)->count())->toBe(1);
    expect($form->submissions()->where('status', FormSubmission::STATUS_COMPLETED)->count())->toBe(1);
});

it('handles file uploads in partial submissions', function () {
    Storage::fake();

    $user = $this->actingAsProUser();
    $workspace = $this->createUserWorkspace($user);
    $form = $this->createForm($user, $workspace, [
        'enable_partial_submissions' => true
    ]);

    // Create a fake file
    $file = UploadedFile::fake()->create('test.pdf', 100);

    // First partial submission with file
    $formData = $this->generateFormSubmissionData($form);
    $fileFieldId = collect($form->properties)->where('type', 'files')->first()['id'];
    $formData[$fileFieldId] = $file;
    $formData['is_partial'] = true;

    $response = $this->postJson(route('forms.answer', $form->slug), $formData)
        ->assertSuccessful();

    $submissionHash = $response->json('submission_hash');

    // Complete the submission
    $completeData = $this->generateFormSubmissionData($form, ['text' => 'Complete']);
    $completeData['submission_hash'] = $submissionHash;

    $this->postJson(route('forms.answer', $form->slug), $completeData)
        ->assertSuccessful();

    // Verify file was preserved
    $submission = FormSubmission::first();
    expect($submission->data)->toHaveKey($fileFieldId);
    $filePath = str_replace('storage/', '', $submission->data[$fileFieldId]);
    expect(Storage::disk('local')->exists($filePath))->toBeTrue();
});

it('handles signature field in partial submissions', function () {
    Storage::fake();

    $user = $this->actingAsProUser();
    $workspace = $this->createUserWorkspace($user);
    $form = $this->createForm($user, $workspace, [
        'enable_partial_submissions' => true
    ]);

    // Create partial submission with signature
    $formData = $this->generateFormSubmissionData($form);
    $signatureFieldId = collect($form->properties)->where('type', 'files')->first()['id'];
    $formData[$signatureFieldId] = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...'; // Base64 signature data
    $formData['is_partial'] = true;

    $response = $this->postJson(route('forms.answer', $form->slug), $formData)
        ->assertSuccessful();

    $submissionHash = $response->json('submission_hash');

    // Complete the submission
    $completeData = $this->generateFormSubmissionData($form, ['text' => 'Complete']);
    $completeData['submission_hash'] = $submissionHash;

    $this->postJson(route('forms.answer', $form->slug), $completeData)
        ->assertSuccessful();

    // Verify signature was preserved
    $submission = FormSubmission::first();
    expect($submission->data)->toHaveKey($signatureFieldId);
    $filePath = str_replace('storage/', '', $submission->data[$signatureFieldId]);
    expect(Storage::disk('local')->exists($filePath))->toBeTrue();
});

it('requires at least one field with value for partial submission', function () {
    $user = $this->actingAsProUser();
    $workspace = $this->createUserWorkspace($user);
    $form = $this->createForm($user, $workspace, [
        'enable_partial_submissions' => true
    ]);

    // Try to submit with empty data
    $formData = ['is_partial' => true];

    $this->postJson(route('forms.answer', $form->slug), $formData)
        ->assertStatus(422)
        ->assertJson([
            'message' => 'At least one field must have a value for partial submissions.'
        ]);
});

it('submits as completed when partial feature is disabled', function () {
    $user = $this->actingAsProUser();
    $workspace = $this->createUserWorkspace($user);

    // Create form with partial submissions disabled
    $form = $this->createForm($user, $workspace, [
        'enable_partial_submissions' => false
    ]);

    $formData = $this->generateFormSubmissionData($form, ['text' => 'Test']);
    $formData['is_partial'] = true;

    $this->postJson(route('forms.answer', $form->slug), $formData)
        ->assertSuccessful()
        ->assertJson([
            'type' => 'success',
            'message' => 'Form submission saved.',
        ]);

    // Verify submission was saved as completed
    $submission = FormSubmission::first();
    expect($submission->status)->toBe(FormSubmission::STATUS_COMPLETED);
});

it('submits as completed on non-pro forms', function () {
    $user = $this->actingAsUser();
    $workspace = $this->createUserWorkspace($user);

    // Create non-pro form with partial submissions enabled
    $form = $this->createForm($user, $workspace, [
        'enable_partial_submissions' => true
    ]);

    $formData = $this->generateFormSubmissionData($form, ['text' => 'Test']);
    $formData['is_partial'] = true;

    $this->postJson(route('forms.answer', $form->slug), $formData)
        ->assertSuccessful()
        ->assertJson([
            'type' => 'success',
            'message' => 'Form submission saved.',
        ]);

    // Verify submission was saved as completed
    $submission = FormSubmission::first();
    expect($submission->status)->toBe(FormSubmission::STATUS_COMPLETED);
});
