<?php

namespace App\Domain\HR\Services;

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

class TrainerService
{
    private const VALID_TRANSITIONS = [
        'active' => ['inactive', 'on_leave', 'suspended'],
        'inactive' => ['active'],
        'on_leave' => ['active', 'suspended'],
        'suspended' => ['active', 'inactive'],
    ];

    public function create(Employee $employee, array $data, User $actor): Trainer
    {
        return DB::transaction(function () use ($employee, $data) {
            $data['academy_id'] = $employee->academy_id;
            $data['employee_id'] = $employee->id;
            $data['trainer_number'] = $this->generateTrainerNumber($employee->academy_id);

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

    public function update(Trainer $trainer, array $data, User $actor): Trainer
    {
        return DB::transaction(function () use ($trainer, $data) {
            $trainer->update($data);

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

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

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

        return DB::transaction(function () use ($trainer, $newStatus) {
            $trainer->update(['status' => $newStatus]);

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

    public function addQualification(Trainer $trainer, array $data): TrainerQualification
    {
        $data['trainer_id'] = $trainer->id;
        $data['created_at'] = now();

        return TrainerQualification::create($data);
    }

    public function removeQualification(TrainerQualification $qualification): void
    {
        $qualification->delete();
    }

    public function verifyQualification(TrainerQualification $qualification, User $verifier): void
    {
        $qualification->update([
            'is_verified' => true,
            'verified_by' => $verifier->id,
            'verified_at' => now(),
        ]);
    }

    public function setAvailability(Trainer $trainer, array $slots): void
    {
        DB::transaction(function () use ($trainer, $slots) {
            $trainer->availabilities()->delete();

            $now = now();
            $records = array_map(fn (array $slot) => [
                'trainer_id' => $trainer->id,
                'type' => $slot['type'],
                'day_of_week' => $slot['day_of_week'] ?? null,
                'specific_date' => $slot['specific_date'] ?? null,
                'start_time' => $slot['start_time'],
                'end_time' => $slot['end_time'],
                'reason' => $slot['reason'] ?? null,
                'created_at' => $now,
            ], $slots);

            if (! empty($records)) {
                TrainerAvailability::insert($records);
            }
        });
    }

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

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

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