<?php

namespace App\Support;

use App\Models\AttendanceDevice;
use App\Models\AttendanceEnrollment;
use App\Models\AttendanceLeaveApplication;
use App\Models\AttendancePunch;
use App\Models\Designation;
use App\Models\PermanentEmployee;
use App\Models\PermanentEmployeeAdvance;
use App\Models\PermanentEmployeePunishment;
use App\Models\PermanentEmployeeSalaryPayment;
use App\Models\TemporaryEmployee;
use App\Models\TemporaryEmployeeContract;
use Illuminate\Filesystem\FilesystemAdapter;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;

class ClearStaffManagementData
{
    /**
     * Remove designations, permanent and temporary staff, salaries, advances,
     * punishments, contracts, and all attendance data. Users are kept.
     *
     * @return array<string, int>
     */
    public static function run(): array
    {
        return DB::transaction(function (): array {
            $counts = [
                'salary_payments' => PermanentEmployeeSalaryPayment::query()->count(),
                'advances' => PermanentEmployeeAdvance::query()->count(),
                'punishments' => PermanentEmployeePunishment::query()->count(),
                'attendance_punches' => AttendancePunch::query()->count(),
                'attendance_leaves' => AttendanceLeaveApplication::query()->count(),
                'attendance_enrollments' => AttendanceEnrollment::query()->count(),
                'attendance_devices' => AttendanceDevice::query()->count(),
                'temporary_contracts' => TemporaryEmployeeContract::query()->count(),
                'permanent_employees' => PermanentEmployee::query()->count(),
                'temporary_employees' => TemporaryEmployee::query()->count(),
                'designations' => Designation::query()->count(),
            ];

            self::deleteEmployeeFiles();
            self::deleteContractFiles();

            PermanentEmployeeSalaryPayment::query()->delete();

            PermanentEmployeeAdvance::query()
                ->where('type', StaffAdvanceType::PRODUCT)
                ->orderBy('id')
                ->get()
                ->each(fn (PermanentEmployeeAdvance $advance) => StaffAdvanceStock::restoreForAdvance($advance));

            PermanentEmployeeAdvance::query()->delete();
            PermanentEmployeePunishment::query()->delete();

            AttendancePunch::query()->delete();
            AttendanceLeaveApplication::query()->delete();
            AttendanceEnrollment::query()->delete();
            AttendanceDevice::query()->delete();

            TemporaryEmployeeContract::query()->delete();
            PermanentEmployee::query()->delete();
            TemporaryEmployee::query()->delete();
            Designation::query()->delete();

            return $counts;
        });
    }

    private static function deleteEmployeeFiles(): void
    {
        /** @var FilesystemAdapter $disk */
        $disk = Storage::disk('public');

        PermanentEmployee::query()
            ->get(['image_path', 'national_card_path', 'health_card_path', 'labor_card_path', 'contract_path'])
            ->each(function (PermanentEmployee $employee) use ($disk): void {
                foreach ([
                    $employee->image_path,
                    $employee->national_card_path,
                    $employee->health_card_path,
                    $employee->labor_card_path,
                    $employee->contract_path,
                ] as $path) {
                    if ($path !== null && $path !== '' && $disk->exists($path)) {
                        $disk->delete($path);
                    }
                }
            });

        TemporaryEmployee::query()
            ->get(['image_path', 'health_card_path'])
            ->each(function (TemporaryEmployee $employee) use ($disk): void {
                foreach ([$employee->image_path, $employee->health_card_path] as $path) {
                    if ($path !== null && $path !== '' && $disk->exists($path)) {
                        $disk->delete($path);
                    }
                }
            });
    }

    private static function deleteContractFiles(): void
    {
        /** @var FilesystemAdapter $disk */
        $disk = Storage::disk('public');

        TemporaryEmployeeContract::query()
            ->whereNotNull('contract_path')
            ->pluck('contract_path')
            ->each(function (string $path) use ($disk): void {
                if ($path !== '' && $disk->exists($path)) {
                    $disk->delete($path);
                }
            });
    }
}
