<?php

declare(strict_types=1);

namespace App\Modules\Administration\Services;

use App\Modules\Administration\Repositories\EmployeeFamilyRepository;
use App\Modules\Administration\Repositories\EmployeeRepository;
use RuntimeException;

final class EmployeeFamilyService
{
    public function __construct(
        private EmployeeFamilyRepository $families,
        private EmployeeRepository $employees
    ) {
    }

    public function byEmployee(
        int $employeeId
    ): array {
        return $this->families
            ->byEmployee($employeeId);
    }

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

    public function create(
        int $employeeId,
        array $data
    ): void {
        $employee =
            $this->employees->find(
                $employeeId
            );

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

        $fullName = trim(
            (string) (
                $data['full_name'] ?? ''
            )
        );

        if ($fullName === '') {
            throw new RuntimeException(
                'Family member name is required.'
            );
        }

        $relationship =
            strtoupper(
                trim(
                    (string) (
                        $data[
                            'relationship_type'
                        ] ?? ''
                    )
                )
            );

        $allowedRelationships = [
            'SPOUSE',
            'FATHER',
            'MOTHER',
            'SON',
            'DAUGHTER',
            'BROTHER',
            'SISTER',
            'GUARDIAN',
            'OTHER'
        ];

        if (
            !in_array(
                $relationship,
                $allowedRelationships,
                true
            )
        ) {
            throw new RuntimeException(
                'Invalid relationship type.'
            );
        }

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

        if (
            $gender !== ''
            && !in_array(
                $gender,
                [
                    'MALE',
                    'FEMALE',
                    'OTHER'
                ],
                true
            )
        ) {
            throw new RuntimeException(
                'Invalid gender.'
            );
        }

        $this->families->create([
            'employee_id' =>
                $employeeId,

            'relationship_type' =>
                $relationship,

            'full_name' =>
                $fullName,

            'gender' =>
                $gender !== ''
                    ? $gender
                    : null,

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

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

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

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

            'is_emergency_contact' =>
                isset(
                    $data[
                        'is_emergency_contact'
                    ]
                )
                    ? 1
                    : 0,

            'status' => 1,

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

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

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

        if ($family === null) {
            throw new RuntimeException(
                'Family member not found.'
            );
        }

        $fullName = trim(
            (string) (
                $data['full_name'] ?? ''
            )
        );

        if ($fullName === '') {
            throw new RuntimeException(
                'Family member name is required.'
            );
        }

        $relationship =
            strtoupper(
                trim(
                    (string) (
                        $data[
                            'relationship_type'
                        ] ?? ''
                    )
                )
            );

        $allowedRelationships = [
            'SPOUSE',
            'FATHER',
            'MOTHER',
            'SON',
            'DAUGHTER',
            'BROTHER',
            'SISTER',
            'GUARDIAN',
            'OTHER'
        ];

        if (
            !in_array(
                $relationship,
                $allowedRelationships,
                true
            )
        ) {
            throw new RuntimeException(
                'Invalid relationship type.'
            );
        }

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

        $this->families->update(
            $id,
            [
                'relationship_type' =>
                    $relationship,

                'full_name' =>
                    $fullName,

                'gender' =>
                    $gender !== ''
                        ? $gender
                        : null,

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

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

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

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

                'is_emergency_contact' =>
                    isset(
                        $data[
                            'is_emergency_contact'
                        ]
                    )
                        ? 1
                        : 0,

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

    public function deactivate(
        int $id
    ): void {
        $family =
            $this->families->find($id);

        if ($family === null) {
            throw new RuntimeException(
                'Family member not found.'
            );
        }

        $this->families
            ->deactivate($id);
    }

    private function nullableString(
        mixed $value
    ): ?string {
        $value = trim(
            (string) $value
        );

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