<?php

namespace App\Jobs;

use App\Models\Employee;
use App\Models\TerminationLog;
use Carbon\Carbon;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;

class CleanupDismissedEmployeeRecords implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, SerializesModels;

    protected int $daysToKeep;
    protected bool $sendNotifications;

    /**
     * Create a new job instance.
     *
     * @param int $daysToKeep Number of days to keep dismissed employee records before cleanup
     * @param bool $sendNotifications Whether to send email notifications to HR
     */
    public function __construct(int $daysToKeep = 90, bool $sendNotifications = true)
    {
        $this->daysToKeep = $daysToKeep;
        $this->sendNotifications = $sendNotifications;
    }

    /**
     * Execute the job.
     */
    public function handle(): void
    {
        Log::info('Starting cleanup of dismissed employee records', [
            'days_to_keep' => $this->daysToKeep,
            'executed_at' => now()
        ]);

        $cutoffDate = Carbon::now()->subDays($this->daysToKeep);
        
        // Find employees dismissed before cutoff date
        $dismissedEmployees = Employee::whereNotNull('dismissed_at')
            ->where('dismissed_at', '<', $cutoffDate)
            ->whereDoesntHave('terminationLogs', function ($query) {
                $query->where('is_reversed', true);
            })
            ->get();

        if ($dismissedEmployees->isEmpty()) {
            Log::info('No dismissed employees found for cleanup');
            return;
        }

        $cleanupResults = [
            'employees_processed' => [],
            'records_archived' => 0,
            'errors' => []
        ];

        foreach ($dismissedEmployees as $employee) {
            try {
                $result = $this->cleanupEmployeeRecords($employee);
                $cleanupResults['employees_processed'][] = [
                    'id' => $employee->id,
                    'name' => $employee->name,
                    'dismissed_at' => $employee->dismissed_at,
                    'records_archived' => $result['archived_count']
                ];
                $cleanupResults['records_archived'] += $result['archived_count'];
            } catch (\Exception $e) {
                $cleanupResults['errors'][] = [
                    'employee_id' => $employee->id,
                    'error' => $e->getMessage()
                ];
                Log::error('Failed to cleanup employee records', [
                    'employee_id' => $employee->id,
                    'error' => $e->getMessage()
                ]);
            }
        }

        // Send notification to HR/Admin
        if ($this->sendNotifications) {
            $this->sendCleanupReport($cleanupResults);
        }

        Log::info('Completed cleanup of dismissed employee records', $cleanupResults);
    }

    /**
     * Cleanup records for a single dismissed employee
     */
    protected function cleanupEmployeeRecords(Employee $employee): array
    {
        return DB::transaction(function () use ($employee) {
            $archivedCount = 0;

            // 1. Archive old deductions (older than 1 year)
            $oldDeductions = DB::table('employee_deductions')
                ->where('employee_id', $employee->id)
                ->where('created_at', '<', Carbon::now()->subYear())
                ->whereNull('archived_at')
                ->update([
                    'archived_at' => now(),
                    'archived_reason' => 'Auto-cleanup post-dismissal'
                ]);
            $archivedCount += $oldDeductions;

            // 2. Archive old payment schedules
            $oldSchedules = DB::table('salary_payment_schedules')
                ->where('employee_id', $employee->id)
                ->where('scheduled_date', '<', Carbon::now()->subMonths(6))
                ->whereNull('archived_at')
                ->update([
                    'archived_at' => now(),
                    'archived_reason' => 'Auto-cleanup post-dismissal'
                ]);
            $archivedCount += $oldSchedules;

            // 3. Anonymize personal data if configured (GDPR compliance)
            if (config('hr.anonymize_dismissed_employees', false)) {
                $this->anonymizeEmployeeData($employee);
            }

            // 4. Remove from active caches
            $this->clearEmployeeCaches($employee);

            // 5. Create archival record in termination log
            $terminationLog = TerminationLog::where('employee_id', $employee->id)
                ->where('is_reversed', false)
                ->latest()
                ->first();

            if ($terminationLog) {
                $metadata = $terminationLog->metadata ?? [];
                $metadata['cleanup_performed_at'] = now();
                $metadata['archived_records_count'] = $archivedCount;
                $terminationLog->update(['metadata' => $metadata]);
            }

            return ['archived_count' => $archivedCount];
        });
    }

    /**
     * Anonymize employee personal data for privacy compliance
     */
    protected function anonymizeEmployeeData(Employee $employee): void
    {
        $employee->update([
            'name' => 'REDACTED_' . $employee->id,
            'email' => null,
            'phone' => null,
            'address' => null,
            'id_number' => 'REDACTED_' . $employee->id,
            'bank_account' => null,
            'emergency_contact' => null,
        ]);
        
        Log::info('Anonymized dismissed employee data', ['employee_id' => $employee->id]);
    }

    /**
     * Clear employee from various caches
     */
    protected function clearEmployeeCaches(Employee $employee): void
    {
        // Clear Redis/Memcached keys
        if (config('cache.default') === 'redis') {
            cache()->forget("employee:{$employee->id}");
            cache()->forget("employee:{$employee->id}:permissions");
            cache()->forget("employee:{$employee->id}:schedules");
        }
        
        // Clear Laravel cache tags if using
        if (method_exists(cache(), 'tags')) {
            cache()->tags(['employees', 'payroll'])->flush();
        }
    }

    /**
     * Send cleanup report to HR/Admin
     */
    protected function sendCleanupReport(array $results): void
    {
        $adminEmails = config('hr.cleanup_notification_emails', [
            'hr@yourcompany.com',
            'admin@yourcompany.com'
        ]);

        try {
            Mail::send('emails.employee-cleanup-report', [
                'results' => $results,
                'date' => now(),
                'days_kept' => $this->daysToKeep
            ], function ($message) use ($adminEmails) {
                $message->to($adminEmails)
                        ->subject('Employee Records Cleanup Report - ' . now()->format('Y-m-d'));
            });
        } catch (\Exception $e) {
            Log::error('Failed to send cleanup notification email', ['error' => $e->getMessage()]);
        }
    }
}