<?php

declare(strict_types=1);

namespace App\Modules\Administration\Services;

use App\Modules\Administration\Repositories\DynamicFormRepository;
use RuntimeException;

final class DynamicFormService
{
    public function __construct(
        private DynamicFormRepository $forms
    ) {
    }

    public function all(): array
    {
        return $this->forms->all();
    }

    public function find(
        int $id
    ): ?array {
        return $this->forms->find($id);
    }

    public function create(
        array $data,
        ?int $createdBy = null
    ): void {
        $formName = trim(
            (string) (
                $data['form_name']
                ?? ''
            )
        );

        if ($formName === '') {
            throw new RuntimeException(
                'Form name is required.'
            );
        }

        $formCode = strtoupper(
            trim(
                (string) (
                    $data['form_code']
                    ?? ''
                )
            )
        );

        if ($formCode === '') {
            throw new RuntimeException(
                'Form code is required.'
            );
        }

        $formCode = preg_replace(
            '/[^A-Z0-9_-]/',
            '',
            $formCode
        );

        if (
            $formCode === null
            || $formCode === ''
        ) {
            throw new RuntimeException(
                'Invalid form code.'
            );
        }

        if (
            $this->forms
                ->findByCode($formCode)
            !== null
        ) {
            throw new RuntimeException(
                'Form code already exists.'
            );
        }

        $now = date(
            'Y-m-d H:i:s'
        );

        $this->forms->create([
            'form_code' =>
                $formCode,

            'form_name' =>
                $formName,

            'description' =>
                $this->nullableString(
                    $data['description']
                    ?? null
                ),

            'form_category' =>
                $this->nullableString(
                    $data['form_category']
                    ?? null
                ),

            'version' =>
                1,

            'status' =>
                'draft',

            'created_by' =>
                $createdBy,

            'published_at' =>
                null,

            'created_at' =>
                $now,

            'updated_at' =>
                $now
        ]);
    }

    public function update(
        int $id,
        array $data
    ): void {
        $form =
            $this->forms->find($id);

        if ($form === null) {
            throw new RuntimeException(
                'Dynamic form not found.'
            );
        }

        $formName = trim(
            (string) (
                $data['form_name']
                ?? ''
            )
        );

        if ($formName === '') {
            throw new RuntimeException(
                'Form name is required.'
            );
        }

        $this->forms->update(
            $id,
            [
                'form_name' =>
                    $formName,

                'description' =>
                    $this->nullableString(
                        $data['description']
                        ?? null
                    ),

                'form_category' =>
                    $this->nullableString(
                        $data['form_category']
                        ?? null
                    ),

                'updated_at' =>
                    date('Y-m-d H:i:s')
            ]
        );
    }

    public function publish(
        int $id
    ): void {
        $form =
            $this->forms->find($id);

        if ($form === null) {
            throw new RuntimeException(
                'Dynamic form not found.'
            );
        }

        $this->forms->update(
            $id,
            [
                'status' =>
                    'published',

                'published_at' =>
                    date('Y-m-d H:i:s'),

                'updated_at' =>
                    date('Y-m-d H:i:s')
            ]
        );
    }

    public function archive(
        int $id
    ): void {
        $form =
            $this->forms->find($id);

        if ($form === null) {
            throw new RuntimeException(
                'Dynamic form not found.'
            );
        }

        $this->forms->update(
            $id,
            [
                'status' =>
                    'archived',

                'updated_at' =>
                    date('Y-m-d H:i:s')
            ]
        );
    }
public function delete(
    int $id
): void {
    if ($id <= 0) {
        throw new RuntimeException(
            'Invalid dynamic form ID.'
        );
    }

    $form =
        $this->forms->find($id);

    if ($form === null) {
        throw new RuntimeException(
            'Dynamic form not found.'
        );
    }

    $status = strtolower(
        trim(
            (string) (
                $form['status']
                ?? ''
            )
        )
    );

    if ($status !== 'draft') {
        throw new RuntimeException(
            'Only draft forms can be deleted.'
        );
    }

    if (
        $this->forms
            ->hasSubmissions($id)
    ) {
        throw new RuntimeException(
            'This form already has submissions and cannot be deleted.'
        );
    }

    $this->forms
        ->deleteDraftForm($id);
}
    private function nullableString(
        mixed $value
    ): ?string {
        $value = trim(
            (string) $value
        );

        return $value !== ''
            ? $value
            : null;
    }
}