<?php

namespace Database\Seeders\Dummy;

use App\Models\Tenants\Attendance;
use Database\Seeders\DummyDataSeeder;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;

class DummyAttendanceSeeder extends Seeder
{
    public function run(): void
    {
        $tenantId = DummyDataSeeder::TENANT_ID;
        $userId = DummyDataSeeder::USER_ID;

        // 테넌트 소속 사용자 조회
        $userIds = DB::table('user_tenants')
            ->where('tenant_id', $tenantId)
            ->pluck('user_id')
            ->toArray();

        if (empty($userIds)) {
            $this->command->warn('   ⚠ attendances: 사용자가 없습니다');

            return;
        }

        // 최근 30일간의 근태 데이터 생성
        $startDate = now()->subDays(30);
        $endDate = now();
        $count = 0;

        // 상태 분포 (enum: onTime, late, absent, vacation, businessTrip, fieldWork, overtime, remote)
        $statuses = [
            'onTime' => 60,      // 정시 출근 60%
            'late' => 10,        // 지각 10%
            'vacation' => 10,    // 휴가 10%
            'absent' => 5,       // 결근 5%
            'businessTrip' => 5, // 출장 5%
            'remote' => 5,       // 재택 5%
            'overtime' => 5,     // 초과근무 5%
        ];

        foreach ($userIds as $uId) {
            $currentDate = clone $startDate;

            while ($currentDate <= $endDate) {
                // 주말 제외
                if ($currentDate->isWeekend()) {
                    $currentDate->addDay();

                    continue;
                }

                $baseDate = $currentDate->format('Y-m-d');

                // 이미 존재하는지 확인
                $exists = Attendance::where('tenant_id', $tenantId)
                    ->where('user_id', $uId)
                    ->where('base_date', $baseDate)
                    ->exists();

                if ($exists) {
                    $currentDate->addDay();

                    continue;
                }

                // 상태 결정 (가중치 기반 랜덤)
                $status = $this->getRandomStatus($statuses);

                // 출퇴근 시간 생성
                $jsonDetails = $this->generateTimeDetails($status);

                Attendance::create([
                    'tenant_id' => $tenantId,
                    'user_id' => $uId,
                    'base_date' => $baseDate,
                    'status' => $status,
                    'json_details' => $jsonDetails,
                    'remarks' => $this->getRemarks($status),
                    'created_by' => $userId,
                ]);

                $count++;
                $currentDate->addDay();
            }
        }

        $this->command->info('   ✓ attendances: '.$count.'건 생성');
    }

    private function getRandomStatus(array $weights): string
    {
        $total = array_sum($weights);
        $rand = rand(1, $total);
        $cumulative = 0;

        foreach ($weights as $status => $weight) {
            $cumulative += $weight;
            if ($rand <= $cumulative) {
                return $status;
            }
        }

        return 'normal';
    }

    private function generateTimeDetails(string $status): array
    {
        $checkIn = null;
        $checkOut = null;
        $workMinutes = 0;
        $lateMinutes = 0;
        $earlyLeaveMinutes = 0;
        $overtimeMinutes = 0;

        $standardStart = 9 * 60; // 09:00 in minutes
        $standardEnd = 18 * 60;  // 18:00 in minutes
        $breakMinutes = 60;

        switch ($status) {
            case 'onTime':
                $startVariance = rand(-10, 10); // ±10분
                $endVariance = rand(-5, 30);    // -5분 ~ +30분
                $checkIn = sprintf('%02d:%02d:00', 9, max(0, $startVariance));
                $checkOut = sprintf('%02d:%02d:00', 18 + intdiv($endVariance, 60), abs($endVariance) % 60);
                $workMinutes = ($standardEnd - $standardStart - $breakMinutes) + $endVariance;
                break;

            case 'late':
                $lateMinutes = rand(10, 60); // 10분 ~ 1시간 지각
                $checkIn = sprintf('%02d:%02d:00', 9 + intdiv($lateMinutes, 60), $lateMinutes % 60);
                $checkOut = '18:00:00';
                $workMinutes = ($standardEnd - $standardStart - $breakMinutes) - $lateMinutes;
                break;

            case 'overtime':
                $checkIn = '09:00:00';
                $overtimeMinutes = rand(60, 180); // 1시간 ~ 3시간 초과근무
                $endTime = $standardEnd + $overtimeMinutes;
                $checkOut = sprintf('%02d:%02d:00', intdiv($endTime, 60), $endTime % 60);
                $workMinutes = ($standardEnd - $standardStart - $breakMinutes) + $overtimeMinutes;
                break;

            case 'remote':
                $checkIn = sprintf('%02d:%02d:00', 9, rand(0, 10));
                $checkOut = sprintf('%02d:%02d:00', 18, rand(0, 30));
                $workMinutes = ($standardEnd - $standardStart - $breakMinutes);
                break;

            case 'businessTrip':
            case 'fieldWork':
                $checkIn = sprintf('%02d:%02d:00', 8, rand(0, 30)); // 출장은 일찍 시작
                $checkOut = sprintf('%02d:%02d:00', 19, rand(0, 60)); // 늦게 종료
                $workMinutes = 10 * 60 - $breakMinutes; // 10시간 근무
                break;

            case 'vacation':
            case 'absent':
                // 출퇴근 기록 없음
                break;
        }

        return [
            'check_in' => $checkIn,
            'check_out' => $checkOut,
            'work_minutes' => max(0, $workMinutes),
            'late_minutes' => $lateMinutes,
            'early_leave_minutes' => $earlyLeaveMinutes,
            'overtime_minutes' => $overtimeMinutes,
            'vacation_type' => $status === 'vacation' ? 'annual' : null,
            'gps_data' => $checkIn ? [
                'check_in' => ['lat' => 37.5012 + (rand(-10, 10) / 10000), 'lng' => 127.0396 + (rand(-10, 10) / 10000)],
                'check_out' => $checkOut ? ['lat' => 37.5012 + (rand(-10, 10) / 10000), 'lng' => 127.0396 + (rand(-10, 10) / 10000)] : null,
            ] : null,
        ];
    }

    private function getRemarks(string $status): ?string
    {
        return match ($status) {
            'late' => '지각 - 교통 체증',
            'vacation' => '연차 휴가',
            'absent' => '결근',
            'businessTrip' => '출장 - 외부 미팅',
            'fieldWork' => '외근 - 현장 방문',
            'overtime' => '초과근무 - 프로젝트 마감',
            'remote' => '재택근무',
            default => null,
        };
    }
}
