<?php

namespace App\Http\Controllers\Web;

use App\Http\Controllers\Controller;
use App\Models\Form;
use App\Services\AuditService;
use App\Support\FormTextRules;
use Illuminate\Http\Request;

class FormController extends Controller
{
    public function __construct(
        protected AuditService $audit
    ) {}

    public function index()
    {
        $forms = Form::orderBy('name')->paginate(15);

        return view('forms.index', compact('forms'));
    }

    public function create()
    {
        return view('forms.create');
    }

    public function store(Request $request)
    {
        $validated = $request->validate($this->rules(), FormTextRules::messages());
        $validated['status'] = $validated['status'] ?? 'draft';
        $validated['company_id'] = auth()->user()->company_id;
        $validated['fields'] = $this->normalizeFields($request->input('fields', []));

        $form = Form::create($validated);
        $this->audit->log('form.created', $form);

        return redirect()->route('forms.index')->with('success', 'Form created successfully.');
    }

    public function edit(Form $form)
    {
        $this->assertTenantRecord($form);

        return view('forms.edit', compact('form'));
    }

    public function update(Request $request, Form $form)
    {
        $this->assertTenantRecord($form);

        $validated = $request->validate($this->rules(), FormTextRules::messages());
        $validated['fields'] = $this->normalizeFields($request->input('fields', $form->fields ?? []));
        $form->update($validated);
        $this->audit->log('form.updated', $form);

        return redirect()->route('forms.index')->with('success', 'Form updated successfully.');
    }

    public function updateStatus(Request $request, Form $form)
    {
        $this->assertTenantRecord($form);

        $request->validate(['status' => 'required|in:draft,published,archived']);
        $form->update(['status' => $request->status]);
        $this->audit->log('form.status_changed', $form, ['status' => $request->status]);

        return redirect()->route('forms.index')->with('success', 'Form status updated.');
    }

    public function destroy(Form $form)
    {
        $this->assertTenantRecord($form);
        $form->submissions()->delete();
        $formId = $form->id;
        $form->delete();
        $this->audit->log('form.deleted', null, ['form_id' => $formId]);

        return redirect()->route('forms.index')->with('success', 'Form deleted.');
    }

    /**
     * @return array<string, mixed>
     */
    protected function rules(): array
    {
        return [
            'name' => FormTextRules::notNumericOnly(true, 191),
            'description' => FormTextRules::notNumericOnly(false, 1000),
            'status' => 'nullable|in:draft,published,archived',
            'fields' => 'nullable|array',
            'fields.*.label' => array_merge(
                ['required_with:fields'],
                array_slice(FormTextRules::notNumericOnly(true, 191), 1)
            ),
            'fields.*.type' => 'required_with:fields|in:text,textarea,number,date,select,checkbox',
            'fields.*.required' => 'nullable|boolean',
            'fields.*.options' => 'nullable|string|max:500',
        ];
    }

    /**
     * @param  array<int, array<string, mixed>>  $raw
     * @return list<array{label: string, type: string, required: bool, options: list<string>}>
     */
    protected function normalizeFields(array $raw): array
    {
        $fields = [];
        foreach ($raw as $field) {
            if (empty($field['label']) || empty($field['type'])) {
                continue;
            }
            $options = [];
            if (! empty($field['options'])) {
                $options = array_values(array_filter(array_map('trim', explode(',', (string) $field['options']))));
            }
            $fields[] = [
                'label' => (string) $field['label'],
                'type' => (string) $field['type'],
                'required' => (bool) ($field['required'] ?? false),
                'options' => $options,
            ];
        }

        return $fields;
    }

    protected function assertTenantRecord(Form $form): void
    {
        $companyId = auth()->user()?->company_id;
        if ($companyId && (int) $form->company_id !== (int) $companyId) {
            abort(403);
        }
    }
}
