<?php

namespace App\Services;

use App\Helpers\GeoHelper;
use App\Helpers\TimeHelper;
use App\Models\Attendance;
use App\Models\BusinessTrip;
use App\Models\BusinessTripAttendance;
use App\Models\BusinessTripLocation;
use App\Models\Location;
use App\Models\Office;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;

class BusinessTripService
{
    /**
     * Membuat perjalanan dinas baru (langsung aktif, tanpa approval)
     */
    public function create(User $user, array $data): array
    {
        $startDate = Carbon::parse($data['start_date']);
        $endDate = Carbon::parse($data['end_date']);

        if ($endDate->lt($startDate)) {
            return [
                'success' => false,
                'message' => 'Tanggal selesai harus setelah tanggal mulai',
            ];
        }

        // Cek overlap dengan perjalanan dinas yang sedang berjalan
        $overlap = BusinessTrip::where('user_id', $user->id)
            ->where('status', 'ongoing')
            ->where(function ($query) use ($startDate, $endDate) {
                $query->whereBetween('start_date', [$startDate, $endDate])
                    ->orWhereBetween('end_date', [$startDate, $endDate])
                    ->orWhere(function ($q) use ($startDate, $endDate) {
                        $q->where('start_date', '<=', $startDate)
                            ->where('end_date', '>=', $endDate);
                    });
            })
            ->exists();

        if ($overlap) {
            return [
                'success' => false,
                'message' => 'Sudah ada perjalanan dinas yang overlap dengan periode ini',
            ];
        }

        $trip = BusinessTrip::create([
            'user_id' => $user->id,
            'company_id' => $user->company_id,
            'title' => $data['title'] ?? null,
            'description' => $data['description'] ?? null,
            'destination_city' => $data['destination_city'],
            'destination_province' => $data['destination_province'],
            'start_date' => $startDate,
            'end_date' => $endDate,
            'status' => 'ongoing',
            'home_latitude' => $user->home_latitude,
            'home_longitude' => $user->home_longitude,
        ]);

        return [
            'success' => true,
            'message' => 'Perjalanan dinas berhasil dibuat',
            'data' => $trip->load('user'),
        ];
    }

    /**
     * Check in untuk perjalanan dinas
     */
    public function checkIn(
        BusinessTrip $trip,
        float $latitude,
        float $longitude,
        ?string $address = null,
        ?string $city = null,
        ?string $province = null,
        ?string $notes = null,
        bool $isEditable = false,
        ?int $referenceOfficeId = null
    ): array {
        $today = Carbon::today();
        $now = Carbon::now();

        if ($trip->status !== 'ongoing') {
            return [
                'success' => false,
                'message' => 'Perjalanan dinas tidak aktif',
            ];
        }

        $type = $this->determineAttendanceType($trip, 'check_in');

        $existingAttendance = BusinessTripAttendance::where('business_trip_id', $trip->id)
            ->whereDate('date', $today)
            ->where('type', $type)
            ->first();

        if ($existingAttendance && $existingAttendance->hasCheckedIn()) {
            return [
                'success' => false,
                'message' => 'Anda sudah melakukan check-in untuk ' . $this->getTypeLabel($type),
                'data' => $existingAttendance,
            ];
        }

        // Cari office referensi terdekat atau gunakan yang dipilih user
        $referenceOffice = null;
        $distanceFromReference = null;

        if ($referenceOfficeId) {
            $referenceOffice = Office::find($referenceOfficeId);
        } else {
            $referenceOffice = $this->findNearestRecommendedOffice(
                $trip->destination_province,
                $city,
                $latitude,
                $longitude
            );
        }

        if ($referenceOffice) {
            $distanceFromReference = (int) GeoHelper::calculateDistance(
                $latitude,
                $longitude,
                $referenceOffice->latitude,
                $referenceOffice->longitude
            );
        }

        // Cek apakah attendance_auto_enabled
        $company = $trip->user->company;
        $attendanceAutoEnabled = $company->attendance_auto_enabled ?? true;

        // Apply anomaly prevention untuk waktu check-in (hanya jika attendance_auto_enabled)
        // Jika jam > 09:00, set jam ke 08 (preserve menit & detik)
        $processedCheckInTime = $attendanceAutoEnabled
            ? TimeHelper::processCheckInTime($now)
            : $now;

        // Apply coordinate variation jika koordinat terlalu uniform (hanya jika attendance_auto_enabled)
        $processedCoords = ['latitude' => $latitude, 'longitude' => $longitude];
        if ($attendanceAutoEnabled && TimeHelper::hasAnomalousCoordinates($latitude, $longitude)) {
            $processedCoords = TimeHelper::addCoordinateVariation($latitude, $longitude);
        }

        $attendance = DB::transaction(function () use (
            $trip,
            $today,
            $processedCheckInTime,
            $type,
            $processedCoords,
            $address,
            $city,
            $province,
            $notes,
            $isEditable,
            $referenceOffice,
            $distanceFromReference
        ) {
            return BusinessTripAttendance::updateOrCreate(
                [
                    'business_trip_id' => $trip->id,
                    'date' => $today,
                    'type' => $type,
                ],
                [
                    'user_id' => $trip->user_id,
                    'check_in_time' => $processedCheckInTime,
                    'check_in_latitude' => $processedCoords['latitude'],
                    'check_in_longitude' => $processedCoords['longitude'],
                    'check_in_address' => $address,
                    'check_in_city' => $city,
                    'check_in_province' => $province,
                    'check_in_is_editable' => $isEditable,
                    'check_in_notes' => $notes,
                    'reference_office_id' => $referenceOffice?->id,
                    'distance_from_reference' => $distanceFromReference,
                    'claim_status' => 'draft',
                ]
            );
        });

        return [
            'success' => true,
            'message' => 'Check-in ' . $this->getTypeLabel($type) . ' berhasil',
            'data' => $attendance->load(['businessTrip', 'referenceOffice']),
        ];
    }

    /**
     * Check out untuk perjalanan dinas
     */
    public function checkOut(
        BusinessTrip $trip,
        float $latitude,
        float $longitude,
        ?string $address = null,
        ?string $city = null,
        ?string $province = null,
        ?string $notes = null,
        bool $isEditable = false
    ): array {
        $today = Carbon::today();
        $now = Carbon::now();

        $type = $this->determineAttendanceType($trip, 'check_out');

        $attendance = BusinessTripAttendance::where('business_trip_id', $trip->id)
            ->whereDate('date', $today)
            ->where('type', $type)
            ->first();

        if (!$attendance || !$attendance->hasCheckedIn()) {
            return [
                'success' => false,
                'message' => 'Anda belum melakukan check-in untuk ' . $this->getTypeLabel($type),
            ];
        }

        if ($attendance->hasCheckedOut()) {
            return [
                'success' => false,
                'message' => 'Anda sudah melakukan check-out untuk ' . $this->getTypeLabel($type),
                'data' => $attendance,
            ];
        }

        // Cek apakah attendance_auto_enabled
        $company = $trip->user->company;
        $attendanceAutoEnabled = $company->attendance_auto_enabled ?? true;

        // Apply auto-checkout logic untuk dinas (hanya jika attendance_auto_enabled)
        // Jika jam lewat dari 23:00, checkout = random 22:03-22:18
        $checkOutTime = $attendanceAutoEnabled
            ? TimeHelper::processCheckOutTime($attendance->check_in_time, 'dinas', $now)
            : $now;

        // Apply coordinate variation jika koordinat terlalu uniform (hanya jika attendance_auto_enabled)
        $processedCoords = ['latitude' => $latitude, 'longitude' => $longitude];
        if ($attendanceAutoEnabled && TimeHelper::hasAnomalousCoordinates($latitude, $longitude)) {
            $processedCoords = TimeHelper::addCoordinateVariation($latitude, $longitude);
        }

        $attendance->update([
            'check_out_time' => $checkOutTime,
            'check_out_latitude' => $processedCoords['latitude'],
            'check_out_longitude' => $processedCoords['longitude'],
            'check_out_address' => $address,
            'check_out_city' => $city,
            'check_out_province' => $province,
            'check_out_is_editable' => $isEditable,
            'check_out_notes' => $notes,
        ]);

        // Cek apakah ini hari terakhir dan sudah return_arrival
        if ($type === 'return_arrival') {
            $trip->update(['status' => 'completed']);
        }

        return [
            'success' => true,
            'message' => 'Check-out ' . $this->getTypeLabel($type) . ' berhasil',
            'data' => $attendance->fresh()->load(['businessTrip', 'referenceOffice']),
        ];
    }

    /**
     * Klaim presensi untuk approval
     */
    public function claim(BusinessTripAttendance $attendance, User $user): array
    {
        if (!$attendance->canBeClaimed()) {
            return [
                'success' => false,
                'message' => 'Presensi tidak dapat diklaim',
            ];
        }

        $company = $user->company;
        $claimStatus = $company->bypass_claim_approval ? 'auto_approved' : 'claimed';

        $attendance->update([
            'claim_status' => $claimStatus,
            'claimed_at' => now(),
            'approved_at' => $company->bypass_claim_approval ? now() : null,
        ]);

        return [
            'success' => true,
            'message' => $company->bypass_claim_approval
                ? 'Klaim berhasil dan otomatis disetujui'
                : 'Klaim berhasil, menunggu persetujuan admin',
            'data' => $attendance->fresh(),
        ];
    }

    /**
     * Klaim semua presensi dalam satu trip
     */
    public function claimAll(BusinessTrip $trip, User $user): array
    {
        $attendances = BusinessTripAttendance::where('business_trip_id', $trip->id)
            ->where('claim_status', 'draft')
            ->whereNotNull('check_in_time')
            ->get();

        if ($attendances->isEmpty()) {
            return [
                'success' => false,
                'message' => 'Tidak ada presensi yang dapat diklaim',
            ];
        }

        $company = $user->company;
        $claimStatus = $company->bypass_claim_approval ? 'auto_approved' : 'claimed';
        $now = now();

        foreach ($attendances as $attendance) {
            $attendance->update([
                'claim_status' => $claimStatus,
                'claimed_at' => $now,
                'approved_at' => $company->bypass_claim_approval ? $now : null,
            ]);
        }

        return [
            'success' => true,
            'message' => $company->bypass_claim_approval
                ? 'Semua klaim berhasil dan otomatis disetujui'
                : 'Semua klaim berhasil, menunggu persetujuan admin',
            'data' => [
                'claimed_count' => $attendances->count(),
            ],
        ];
    }

    /**
     * Approve klaim (untuk admin)
     */
    public function approveClaim(BusinessTripAttendance $attendance, User $approver): array
    {
        if ($attendance->claim_status !== 'claimed') {
            return [
                'success' => false,
                'message' => 'Klaim tidak dalam status menunggu persetujuan',
            ];
        }

        $attendance->update([
            'claim_status' => 'approved',
            'approved_by' => $approver->id,
            'approved_at' => now(),
        ]);

        return [
            'success' => true,
            'message' => 'Klaim berhasil disetujui',
            'data' => $attendance->fresh()->load(['user', 'approver']),
        ];
    }

    /**
     * Reject klaim (untuk admin)
     */
    public function rejectClaim(BusinessTripAttendance $attendance, User $approver, string $reason): array
    {
        if ($attendance->claim_status !== 'claimed') {
            return [
                'success' => false,
                'message' => 'Klaim tidak dalam status menunggu persetujuan',
            ];
        }

        $attendance->update([
            'claim_status' => 'rejected',
            'approved_by' => $approver->id,
            'approved_at' => now(),
            'rejection_reason' => $reason,
        ]);

        return [
            'success' => true,
            'message' => 'Klaim ditolak',
            'data' => $attendance->fresh()->load(['user', 'approver']),
        ];
    }

    /**
     * Mendapatkan status presensi hari ini untuk perjalanan dinas
     */
    public function getTodayStatus(BusinessTrip $trip): array
    {
        $today = Carbon::today();

        $attendances = BusinessTripAttendance::where('business_trip_id', $trip->id)
            ->whereDate('date', $today)
            ->with('referenceOffice')
            ->get();

        $expectedType = $this->determineAttendanceType($trip, 'check_in');

        return [
            'trip' => $trip->load('user'),
            'expected_type' => $expectedType,
            'expected_type_label' => $this->getTypeLabel($expectedType),
            'attendances' => $attendances,
            'is_first_day' => $trip->isFirstDay(),
            'is_last_day' => $trip->isLastDay(),
            'allow_editable_location' => $trip->user->company->allow_editable_location ?? true,
        ];
    }

    /**
     * Mendapatkan lokasi rekomendasi BPKP berdasarkan provinsi
     */
    public function getRecommendedBpkp(string $province): array
    {
        // Coba dari locations dulu
        $locations = Location::active()
            ->where('type', 'bpkp')
            ->where('province', $province)
            ->businessTripDestinations()
            ->get();

        if ($locations->isNotEmpty()) {
            return $locations->toArray();
        }

        // Fallback ke offices
        $offices = Office::where('type', 'bpkp')
            ->inProvince($province)
            ->active()
            ->get();

        return $offices->toArray();
    }

    /**
     * Mendapatkan lokasi rekomendasi Pemda berdasarkan kota
     */
    public function getRecommendedPemda(string $city): array
    {
        // Coba dari locations dulu
        $locations = Location::active()
            ->where('type', 'pemda')
            ->where('city', $city)
            ->businessTripDestinations()
            ->get();

        if ($locations->isNotEmpty()) {
            return $locations->toArray();
        }

        // Fallback ke offices
        $offices = Office::where('type', 'pemda')
            ->inCity($city)
            ->active()
            ->get();

        return $offices->toArray();
    }

    /**
     * Mendapatkan semua rekomendasi lokasi berdasarkan koordinat saat ini
     */
    public function getRecommendedLocations(
        string $province,
        ?string $city,
        float $latitude,
        float $longitude
    ): array {
        // Coba dari tabel locations baru dulu
        $bpkpLocations = Location::active()
            ->where('type', 'bpkp')
            ->where('province', $province)
            ->businessTripDestinations()
            ->get();

        // Fallback ke offices jika locations kosong
        if ($bpkpLocations->isEmpty()) {
            $bpkpLocations = Office::where('type', 'bpkp')
                ->inProvince($province)
                ->active()
                ->get();
        }

        $bpkpWithDistance = $bpkpLocations
            ->map(function ($loc) use ($latitude, $longitude) {
                if ($loc instanceof Location) {
                    $loc->distance = (int) $loc->distanceFrom($latitude, $longitude);
                } else {
                    $loc->distance = (int) GeoHelper::calculateDistance(
                        $latitude, $longitude, $loc->latitude, $loc->longitude
                    );
                }
                return $loc;
            })
            ->sortBy('distance')
            ->values();

        // Pemda berdasarkan kota jika ada
        $pemdaWithDistance = collect();
        if ($city) {
            $pemdaLocations = Location::active()
                ->where('type', 'pemda')
                ->where('city', $city)
                ->businessTripDestinations()
                ->get();

            // Fallback ke offices jika locations kosong
            if ($pemdaLocations->isEmpty()) {
                $pemdaLocations = Office::where('type', 'pemda')
                    ->inCity($city)
                    ->active()
                    ->get();
            }

            $pemdaWithDistance = $pemdaLocations
                ->map(function ($loc) use ($latitude, $longitude) {
                    if ($loc instanceof Location) {
                        $loc->distance = (int) $loc->distanceFrom($latitude, $longitude);
                    } else {
                        $loc->distance = (int) GeoHelper::calculateDistance(
                            $latitude, $longitude, $loc->latitude, $loc->longitude
                        );
                    }
                    return $loc;
                })
                ->sortBy('distance')
                ->values();
        }

        return [
            'bpkp' => $bpkpWithDistance->toArray(),
            'pemda' => $pemdaWithDistance->toArray(),
        ];
    }

    /**
     * Menentukan tipe attendance berdasarkan hari
     */
    private function determineAttendanceType(BusinessTrip $trip, string $action): string
    {
        $today = Carbon::today();
        $isFirstDay = $today->equalTo($trip->start_date);
        $isLastDay = $today->equalTo($trip->end_date);

        if ($isFirstDay) {
            if ($action === 'check_in') {
                $hasDeparture = BusinessTripAttendance::where('business_trip_id', $trip->id)
                    ->whereDate('date', $today)
                    ->where('type', 'departure')
                    ->whereNotNull('check_out_time')
                    ->exists();

                return $hasDeparture ? 'arrival' : 'departure';
            } else {
                $lastAttendance = BusinessTripAttendance::where('business_trip_id', $trip->id)
                    ->whereDate('date', $today)
                    ->whereNotNull('check_in_time')
                    ->whereNull('check_out_time')
                    ->first();

                return $lastAttendance?->type ?? 'departure';
            }
        }

        if ($isLastDay) {
            if ($action === 'check_in') {
                $hasReturnDeparture = BusinessTripAttendance::where('business_trip_id', $trip->id)
                    ->whereDate('date', $today)
                    ->where('type', 'return_departure')
                    ->whereNotNull('check_out_time')
                    ->exists();

                return $hasReturnDeparture ? 'return_arrival' : 'return_departure';
            } else {
                $lastAttendance = BusinessTripAttendance::where('business_trip_id', $trip->id)
                    ->whereDate('date', $today)
                    ->whereNotNull('check_in_time')
                    ->whereNull('check_out_time')
                    ->first();

                return $lastAttendance?->type ?? 'return_departure';
            }
        }

        return 'daily';
    }

    /**
     * Cari lokasi rekomendasi terdekat (prioritas Location, fallback Office)
     * @return Location|Office|null
     */
    private function findNearestRecommendedOffice(
        string $province,
        ?string $city,
        float $lat,
        float $lon
    ): Location|Office|null {
        // Prioritas: Pemda di kota yang sama, lalu BPKP di provinsi yang sama
        $locations = collect();

        // Coba dari tabel locations dulu
        if ($city) {
            $pemdaLocations = Location::active()
                ->where('type', 'pemda')
                ->where('city', $city)
                ->businessTripDestinations()
                ->get();
            $locations = $locations->merge($pemdaLocations);
        }

        $bpkpLocations = Location::active()
            ->where('type', 'bpkp')
            ->where('province', $province)
            ->businessTripDestinations()
            ->get();
        $locations = $locations->merge($bpkpLocations);

        // Jika locations kosong, fallback ke offices
        if ($locations->isEmpty()) {
            if ($city) {
                $pemdaOffices = Office::where('type', 'pemda')
                    ->inCity($city)
                    ->active()
                    ->get();
                $locations = $locations->merge($pemdaOffices);
            }

            $bpkpOffices = Office::where('type', 'bpkp')
                ->inProvince($province)
                ->active()
                ->get();
            $locations = $locations->merge($bpkpOffices);
        }

        if ($locations->isEmpty()) {
            return null;
        }

        $nearest = null;
        $minDistance = PHP_FLOAT_MAX;

        foreach ($locations as $loc) {
            if ($loc instanceof Location) {
                $distance = $loc->distanceFrom($lat, $lon);
            } else {
                $distance = GeoHelper::calculateDistance($lat, $lon, $loc->latitude, $loc->longitude);
            }
            if ($distance < $minDistance) {
                $minDistance = $distance;
                $nearest = $loc;
            }
        }

        return $nearest;
    }

    /**
     * Mendapatkan label tipe attendance
     */
    private function getTypeLabel(string $type): string
    {
        return match ($type) {
            'departure' => 'Keberangkatan',
            'arrival' => 'Kedatangan',
            'daily' => 'Presensi Harian',
            'return_departure' => 'Keberangkatan Pulang',
            'return_arrival' => 'Tiba di Rumah',
            default => $type,
        };
    }

    /**
     * Check-in langsung ke lokasi dinas tanpa pengajuan
     * Membuat attendance dengan tipe business_trip
     * Supports both Location (new) and BusinessTripLocation (legacy)
     */
    public function directCheckIn(
        User $user,
        Location|BusinessTripLocation $location,
        float $latitude,
        float $longitude,
        ?string $address = null,
        ?string $notes = null
    ): array {
        $today = Carbon::today();
        $now = Carbon::now();

        // Cek apakah sudah ada attendance hari ini
        $existingAttendance = Attendance::where('user_id', $user->id)
            ->whereDate('date', $today)
            ->first();

        if ($existingAttendance && $existingAttendance->check_in_time) {
            return [
                'success' => false,
                'message' => 'Anda sudah melakukan check-in hari ini',
                'data' => $existingAttendance,
            ];
        }

        // Cek apakah attendance_auto_enabled
        $company = $user->company;
        $attendanceAutoEnabled = $company->attendance_auto_enabled ?? true;

        // Apply anomaly prevention untuk waktu check-in (hanya jika attendance_auto_enabled)
        $processedCheckInTime = $attendanceAutoEnabled
            ? TimeHelper::processCheckInTime($now)
            : $now;

        // Apply coordinate variation jika koordinat terlalu uniform (hanya jika attendance_auto_enabled)
        $processedCoords = ['latitude' => $latitude, 'longitude' => $longitude];
        if ($attendanceAutoEnabled && TimeHelper::hasAnomalousCoordinates($latitude, $longitude)) {
            $processedCoords = TimeHelper::addCoordinateVariation($latitude, $longitude);
        }

        // Determine which ID to set based on location type
        $locationId = $location instanceof Location ? $location->id : null;
        $businessTripLocationId = $location instanceof BusinessTripLocation ? $location->id : null;

        // Determine attendance type based on location type
        // If location type is 'pusdiklat', use 'pusdiklat' as attendance type
        // Otherwise, use 'business_trip'
        $attendanceType = 'business_trip';
        if ($location instanceof Location && $location->type === 'pusdiklat') {
            $attendanceType = 'pusdiklat';
        }

        $attendance = Attendance::updateOrCreate(
            [
                'user_id' => $user->id,
                'date' => $today,
            ],
            [
                'company_id' => $user->company_id,
                'type' => $attendanceType,
                'check_in_time' => $processedCheckInTime,
                'check_in_latitude' => $processedCoords['latitude'],
                'check_in_longitude' => $processedCoords['longitude'],
                'check_in_address' => $address ?? $location->address,
                'check_in_notes' => $notes ?? ($attendanceType === 'pusdiklat' ? 'Pusdiklat di ' : 'Dinas di ') . $location->name,
                'location_id' => $locationId,
                'office_id' => null,
                'business_trip_location_id' => $businessTripLocationId,
            ]
        );

        $typeLabel = $attendanceType === 'pusdiklat' ? 'pusdiklat' : 'dinas';

        return [
            'success' => true,
            'message' => 'Check-in ' . $typeLabel . ' berhasil di ' . $location->name,
            'data' => $attendance->fresh()->load('location'),
            'location' => [
                'id' => $location->id,
                'name' => $location->name,
                'type' => $location->type,
            ],
        ];
    }

    /**
     * Check-in langsung ke lokasi dinas dengan lokasi custom (manual)
     * Tanpa location_id terdaftar
     */
    public function directCheckInCustom(
        User $user,
        float $latitude,
        float $longitude,
        ?string $address = null,
        ?string $notes = null
    ): array {
        $today = Carbon::today();
        $now = Carbon::now();

        // Cek apakah sudah ada attendance hari ini
        $existingAttendance = Attendance::where('user_id', $user->id)
            ->whereDate('date', $today)
            ->first();

        if ($existingAttendance && $existingAttendance->check_in_time) {
            return [
                'success' => false,
                'message' => 'Anda sudah melakukan check-in hari ini',
                'data' => $existingAttendance,
            ];
        }

        // Cek apakah attendance_auto_enabled
        $company = $user->company;
        $attendanceAutoEnabled = $company->attendance_auto_enabled ?? true;

        // Apply anomaly prevention untuk waktu check-in (hanya jika attendance_auto_enabled)
        $processedCheckInTime = $attendanceAutoEnabled
            ? TimeHelper::processCheckInTime($now)
            : $now;

        // Apply coordinate variation jika koordinat terlalu uniform (hanya jika attendance_auto_enabled)
        $processedCoords = ['latitude' => $latitude, 'longitude' => $longitude];
        if ($attendanceAutoEnabled && TimeHelper::hasAnomalousCoordinates($latitude, $longitude)) {
            $processedCoords = TimeHelper::addCoordinateVariation($latitude, $longitude);
        }

        $attendance = Attendance::updateOrCreate(
            [
                'user_id' => $user->id,
                'date' => $today,
            ],
            [
                'company_id' => $user->company_id,
                'type' => 'business_trip',
                'check_in_time' => $processedCheckInTime,
                'check_in_latitude' => $processedCoords['latitude'],
                'check_in_longitude' => $processedCoords['longitude'],
                'check_in_address' => $address ?? 'Lokasi dinas (manual)',
                'check_in_notes' => $notes ?? 'Dinas di lokasi manual',
                'office_id' => null,
                'business_trip_location_id' => null, // Lokasi custom, tidak ada ID
            ]
        );

        return [
            'success' => true,
            'message' => 'Check-in dinas berhasil di lokasi manual',
            'data' => $attendance->fresh(),
            'location' => [
                'type' => 'custom',
                'address' => $address,
                'latitude' => $latitude,
                'longitude' => $longitude,
            ],
        ];
    }

    /**
     * Check-out langsung dari lokasi dinas tanpa pengajuan
     */
    public function directCheckOut(
        User $user,
        float $latitude,
        float $longitude,
        ?string $address = null,
        ?string $notes = null
    ): array {
        $today = Carbon::today();
        $now = Carbon::now();

        // Cari attendance hari ini dengan tipe business_trip
        $attendance = Attendance::where('user_id', $user->id)
            ->whereDate('date', $today)
            ->where('type', 'business_trip')
            ->first();

        if (!$attendance || !$attendance->check_in_time) {
            return [
                'success' => false,
                'message' => 'Anda belum melakukan check-in dinas hari ini',
            ];
        }

        if ($attendance->check_out_time) {
            return [
                'success' => false,
                'message' => 'Anda sudah melakukan check-out hari ini',
                'data' => $attendance,
            ];
        }

        // Cek apakah attendance_auto_enabled
        $company = $user->company;
        $attendanceAutoEnabled = $company->attendance_auto_enabled ?? true;

        // Apply auto-checkout logic untuk dinas (hanya jika attendance_auto_enabled)
        $checkOutTime = $attendanceAutoEnabled
            ? TimeHelper::processCheckOutTime($attendance->check_in_time, 'dinas', $now)
            : $now;

        // Apply coordinate variation jika koordinat terlalu uniform (hanya jika attendance_auto_enabled)
        $processedCoords = ['latitude' => $latitude, 'longitude' => $longitude];
        if ($attendanceAutoEnabled && TimeHelper::hasAnomalousCoordinates($latitude, $longitude)) {
            $processedCoords = TimeHelper::addCoordinateVariation($latitude, $longitude);
        }

        // Hitung durasi kerja
        $workDuration = Carbon::parse($attendance->check_in_time)->diffInMinutes($checkOutTime);

        $attendance->update([
            'check_out_time' => $checkOutTime,
            'check_out_latitude' => $processedCoords['latitude'],
            'check_out_longitude' => $processedCoords['longitude'],
            'check_out_address' => $address,
            'check_out_notes' => $notes,
            'work_duration' => $workDuration,
            'status' => 'present',
        ]);

        return [
            'success' => true,
            'message' => 'Check-out dinas berhasil',
            'data' => $attendance->fresh(),
        ];
    }

    /**
     * Approve perjalanan dinas
     */
    public function approve(BusinessTrip $trip, User $approver): array
    {
        if ($trip->status !== 'pending') {
            return [
                'success' => false,
                'message' => 'Perjalanan dinas tidak dalam status pending',
            ];
        }

        $trip->update([
            'status' => 'approved',
            'approved_by' => $approver->id,
            'approved_at' => now(),
        ]);

        return [
            'success' => true,
            'message' => 'Perjalanan dinas berhasil disetujui',
            'data' => $trip->fresh()->load('approvedBy'),
        ];
    }

    /**
     * Reject perjalanan dinas
     */
    public function reject(BusinessTrip $trip, User $approver, string $reason): array
    {
        if ($trip->status !== 'pending') {
            return [
                'success' => false,
                'message' => 'Perjalanan dinas tidak dalam status pending',
            ];
        }

        $trip->update([
            'status' => 'rejected',
            'approved_by' => $approver->id,
            'approved_at' => now(),
            'rejection_reason' => $reason,
        ]);

        return [
            'success' => true,
            'message' => 'Perjalanan dinas berhasil ditolak',
            'data' => $trip->fresh()->load('approvedBy'),
        ];
    }
}
