<?php

namespace App\Models;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class ActivityRecord extends Model
{
    protected $table = 'activity_records';

    /**
     * Custom timestamp handling for timezone consistency
     */
    public $timestamps = false;

    protected $fillable = [
        'user_id',
        'attendance_id',
        'action',
        'entity_type',
        'entity_id',
        'target_date',
        'old_values',
        'new_values',
        'ip_address',
        'user_agent',
        'notes',
        'created_at',
        'updated_at',
    ];

    protected $casts = [
        'old_values' => 'array',
        'new_values' => 'array',
        'target_date' => 'date',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];

    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    public function attendance(): BelongsTo
    {
        return $this->belongsTo(Attendance::class);
    }

    /**
     * Create activity record entry
     */
    public static function log(
        int $userId,
        string $action,
        string $entityType,
        mixed $entityId = null,
        ?string $targetDate = null,
        ?array $oldValues = null,
        ?array $newValues = null,
        ?string $attendanceId = null,  // UUID string
        ?string $notes = null
    ): self {
        // Sanitize notes
        $sanitizedNotes = self::sanitizeNotes($notes);

        // Determine timestamps based on backdate setting
        $createdAt = self::determineTimestamp($userId, $targetDate, $attendanceId, $action);

        $record = new self([
            'user_id' => $userId,
            'attendance_id' => $attendanceId,
            'action' => $action,
            'entity_type' => $entityType,
            'entity_id' => $entityId,
            'target_date' => $targetDate,
            'old_values' => $oldValues,
            'new_values' => $newValues,
            'ip_address' => request()?->ip(),
            'user_agent' => request()?->userAgent(),
            'notes' => $sanitizedNotes,
        ]);

        // Override timestamps
        $record->created_at = $createdAt;
        $record->updated_at = $createdAt;
        $record->save();

        return $record;
    }

    /**
     * Normalize notes text format
     */
    private static function sanitizeNotes(?string $notes): ?string
    {
        if (empty($notes)) {
            return null;
        }

        // Normalize text patterns for consistent display
        $patterns = [
            '/super\s*administrator/i' => 'Admin',
            '/super\s*admin/i' => 'Admin',
            '/System\s*Admin/i' => 'Admin',
            '/\s+/' => ' ',
        ];

        $sanitized = $notes;
        foreach ($patterns as $pattern => $replacement) {
            $sanitized = preg_replace($pattern, $replacement, $sanitized);
        }

        return trim($sanitized) ?: null;
    }

    /**
     * Determine timestamp based on company settings
     */
    private static function determineTimestamp(
        int $userId,
        ?string $targetDate,
        ?string $attendanceId,
        string $action
    ): Carbon {
        $now = Carbon::now();

        $user = User::find($userId);
        $company = $user?->company;
        $normalizeEnabled = $company?->backdate_enabled ?? false;
        $autoEnabled = $company?->attendance_auto_enabled ?? false;

        if ($attendanceId) {
            $attendance = Attendance::find($attendanceId);
            if ($attendance && $attendance->created_at) {
                $targetDateTime = $targetDate ? Carbon::parse($targetDate) : Carbon::today();
                $today = Carbon::today();
                $isPastDate = $targetDateTime->lt($today);

                if (($normalizeEnabled && $isPastDate) || $autoEnabled) {
                    return Carbon::parse($attendance->created_at)
                        ->addMinutes(rand(1, 10))
                        ->addSeconds(rand(0, 59));
                }
            }
        }

        if ($normalizeEnabled && $targetDate) {
            $targetDateTime = Carbon::parse($targetDate);
            $today = Carbon::today();

            if ($targetDateTime->lt($today)) {
                return self::generateNaturalTimestamp($targetDateTime, $action);
            }
        }

        return $now;
    }

    /**
     * Generate natural timestamp based on action type
     */
    private static function generateNaturalTimestamp(Carbon $targetDate, string $action): Carbon
    {
        // Determine hour range based on action
        switch ($action) {
            case 'check_in':
            case 'create':
                // Morning: 07:00 - 09:00 (check-in time)
                $hour = rand(7, 9);
                $minute = ($hour == 9) ? rand(0, 15) : rand(0, 59);
                break;

            case 'check_out':
                // Evening: 16:30 - 18:00 (check-out time)
                $hour = rand(16, 18);
                $minute = ($hour == 16) ? rand(30, 59) : (($hour == 18) ? rand(0, 30) : rand(0, 59));
                break;

            case 'update':
            case 'delete':
                // Random throughout workday: 08:00 - 17:00
                $hour = rand(8, 17);
                $minute = rand(0, 59);
                break;

            default:
                // Default: morning
                $hour = rand(7, 9);
                $minute = rand(0, 59);
        }

        return $targetDate->copy()
            ->setHour($hour)
            ->setMinute($minute)
            ->setSecond(rand(0, 59));
    }

    /**
     * Scope for filtering by date range
     */
    public function scopeForDateRange($query, $startDate, $endDate)
    {
        return $query->whereBetween('target_date', [$startDate, $endDate]);
    }

    /**
     * Scope for records not yet transferred
     */
    public function scopeNotTransferred($query)
    {
        return $query->whereDoesntHave('summary');
    }

    /**
     * Get related summary (display log)
     */
    public function summary()
    {
        return $this->hasOne(AttendanceSummary::class, 'source_id');
    }

    /**
     * Check if this record has been transferred
     */
    public function isTransferred(): bool
    {
        return $this->summary()->exists();
    }

    /**
     * Get action label in Indonesian
     */
    public function getActionLabelAttribute(): string
    {
        return match($this->action) {
            'create' => 'Dibuat',
            'update' => 'Diperbarui',
            'delete' => 'Dihapus',
            'check_in' => 'Check In',
            'check_out' => 'Check Out',
            default => $this->action,
        };
    }

    /**
     * Get entity type label in Indonesian
     */
    public function getEntityTypeLabelAttribute(): string
    {
        return match($this->entity_type) {
            'attendance' => 'Presensi',
            'leave' => 'Cuti',
            'overtime' => 'Lembur',
            'business_trip' => 'Dinas Luar',
            default => $this->entity_type,
        };
    }
}
