<?php

namespace App\Domain\HR\Services;

use App\Domain\HR\Models\Employee;
use App\Models\User;
use App\Domain\Shared\Exceptions\DomainException;
use App\Domain\Shared\Exceptions\InvalidStatusTransitionException;
use Illuminate\Support\Facades\DB;

class EmployeeService
{
    private const VALID_TRANSITIONS = [
        'active' => ['on_leave', 'suspended', 'terminated', 'resigned'],
        'on_leave' => ['active', 'terminated', 'resigned'],
        'suspended' => ['active', 'terminated', 'resigned'],
        'terminated' => [],
        'resigned' => [],
    ];

    public function create(array $data, User $actor): Employee
    {
        return DB::transaction(function () use ($data, $actor) {
            $data['employee_number'] = $this->generateEmployeeNumber($data['academy_id'], $data['branch_id'] ?? null);
            $data['created_by'] = $actor->id;

            return Employee::create($data);
        });
    }

    public function update(Employee $employee, array $data, User $actor): Employee
    {
        return DB::transaction(function () use ($employee, $data, $actor) {
            $data['updated_by'] = $actor->id;
            $employee->update($data);

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

    public function changeStatus(Employee $employee, string $newStatus, ?string $reason, User $actor): Employee
    {
        $currentStatus = $employee->status->value;
        $allowed = self::VALID_TRANSITIONS[$currentStatus] ?? [];

        if (! in_array($newStatus, $allowed)) {
            throw new InvalidStatusTransitionException(
                "لا يمكن تغيير حالة الموظف من '{$currentStatus}' إلى '{$newStatus}'"
            );
        }

        return DB::transaction(function () use ($employee, $newStatus, $reason, $actor) {
            $updateData = [
                'status' => $newStatus,
                'updated_by' => $actor->id,
            ];

            if (in_array($newStatus, ['terminated', 'resigned'])) {
                $updateData['end_date'] = now()->toDateString();
                $updateData['termination_reason'] = $reason;
            }

            $employee->update($updateData);

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

    private function generateEmployeeNumber(int $academyId, ?int $branchId): string
    {
        $lastNumber = Employee::withoutGlobalScopes()
            ->where('academy_id', $academyId)
            ->max('id') ?? 0;

        $seq = str_pad($lastNumber + 1, 4, '0', STR_PAD_LEFT);

        return "EMP-{$seq}";
    }
}
