<?php

namespace App\Services\Staff;

use App\Models\Staff;
use App\Models\User;
use App\Services\System\GlobalConfigService;
use Illuminate\Support\Facades\DB;
use RuntimeException;

class StaffCommandService
{
    public function __construct(private GlobalConfigService $configService)
    {
    }

    public function create(array $payload): Staff
    {
        return DB::transaction(function () use ($payload) {
            $userId = $this->resolveUserId($payload);

            $roleName = (string) ($payload['role_name'] ?? '');
            $activeRole = strtolower($roleName);
            if (!empty($payload['status']) && strtolower((string) $payload['status']) === 'inactive') {
                $activeRole = 'inactive';
            }

            $schoolYear = (string) ($payload['school_year'] ?? $this->configService->getSchoolYear() ?? '');

            $staff = Staff::query()->create([
                'user_id' => $userId,
                'firstname' => (string) $payload['firstname'],
                'lastname' => (string) $payload['lastname'],
                'email' => (string) $payload['email'],
                'phone' => $payload['phone'] ?? null,
                'role_name' => $roleName,
                'active_role' => $activeRole,
                'school_year' => $schoolYear,
                'created_at' => now(),
                'updated_at' => now(),
            ]);

            if (!$staff) {
                throw new RuntimeException('Failed to create staff member.');
            }

            return $staff;
        });
    }

    public function update(Staff $staff, array $payload): Staff
    {
        return DB::transaction(function () use ($staff, $payload) {
            $updates = [];
            foreach (['firstname', 'lastname', 'email', 'phone', 'role_name', 'school_year'] as $field) {
                if (array_key_exists($field, $payload) && $payload[$field] !== '') {
                    $updates[$field] = $payload[$field];
                }
            }

            if (array_key_exists('role_name', $updates)) {
                $updates['active_role'] = strtolower((string) $updates['role_name']);
            }
            if (!empty($payload['status']) && strtolower((string) $payload['status']) === 'inactive') {
                $updates['active_role'] = 'inactive';
            }

            $updates['updated_at'] = now();

            if (!empty($updates)) {
                $staff->fill($updates);
                $staff->save();
            }

            return $staff->fresh();
        });
    }

    public function delete(Staff $staff): bool
    {
        return (bool) $staff->delete();
    }

    private function resolveUserId(array $payload): int
    {
        if (!empty($payload['user_id'])) {
            return (int) $payload['user_id'];
        }

        $email = $payload['email'] ?? null;
        if ($email) {
            $userId = User::query()->where('email', $email)->value('id');
            if ($userId) {
                return (int) $userId;
            }
        }

        throw new RuntimeException('A valid user_id or existing email is required.');
    }
}
