<?php

namespace App\Imports;

use App\Models\Employee;
use App\Models\EmployeeProfile;
use App\Models\Station;
use App\Services\EmployeeDismissalService;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithValidation;
use Maatwebsite\Excel\Concerns\SkipsOnFailure;
use Maatwebsite\Excel\Concerns\Importable;
use Maatwebsite\Excel\Validators\Failure;

class EmployeesImport implements ToCollection, WithHeadingRow, WithValidation, SkipsOnFailure
{
    use Importable;

    protected EmployeeDismissalService $dismissalService;
    protected array $importResults;
    protected array $errors = [];
    protected int $processedCount = 0;
    protected int $successCount = 0;
    protected int $dismissedCount = 0;
    protected int $updatedCount = 0;

    public function __construct()
    {
        $this->dismissalService = app(EmployeeDismissalService::class);
        $this->importResults = [
            'total_rows' => 0,
            'successful' => 0,
            'failed' => 0,
            'dismissed' => 0,
            'updated' => 0,
            'details' => []
        ];
    }

    /**
     * Process each row of the import
     */
    public function collection(Collection $rows)
    {
        $this->importResults['total_rows'] = $rows->count();

        foreach ($rows as $index => $row) {
            try {
                $this->processRow($row, $index + 2); // +2 for heading row
            } catch (\Exception $e) {
                $this->errors[] = [
                    'row' => $index + 2,
                    'error' => $e->getMessage(),
                    'data' => $row->toArray()
                ];
                $this->importResults['failed']++;
                Log::error('Import row failed', [
                    'row' => $index + 2,
                    'error' => $e->getMessage()
                ]);
            }
        }

        $this->importResults['successful'] = $this->successCount;
        $this->importResults['dismissed'] = $this->dismissedCount;
        $this->importResults['updated'] = $this->updatedCount;
        
        // Log final import summary
        Log::info('Employee import completed', $this->importResults);
    }

    /**
     * Process a single row
     */
    protected function processRow(Collection $row, int $rowNumber): void
    {
        // Validate the row data
        $validator = Validator::make($row->toArray(), $this->rules(), $this->customValidationMessages());
        
        if ($validator->fails()) {
            throw new \Exception('Validation failed: ' . implode(', ', $validator->errors()->all()));
        }

        DB::transaction(function () use ($row, $rowNumber) {
            // Check if employee exists
            $employee = Employee::withTrashed()->updateOrCreate(
                ['employee_code' => $row['employee_code']],
                [
                    'name' => $row['name'],
                    'email' => $row['email'] ?? null,
                    'phone' => $row['phone'] ?? null,
                    'hire_date' => $row['hire_date'],
                    'department' => $row['department'] ?? null,
                    'position' => $row['position'] ?? null,
                    'status' => $this->determineStatus($row),
                ]
            );

            $isNewEmployee = $employee->wasRecentlyCreated;
            $previousStatus = $employee->getOriginal('status');

            // Handle employee profile
            $this->updateOrCreateProfile($employee, $row);

            // Handle station assignment
            if (!empty($row['station_code'])) {
                $this->assignToStation($employee, $row['station_code']);
            }

            // Handle dismissal scenario
            if ($this->shouldBeDismissed($row, $employee, $previousStatus)) {
                $this->handleDismissal($employee, $row, $rowNumber);
                $this->dismissedCount++;
            } elseif ($isNewEmployee) {
                $this->successCount++;
            } else {
                $this->updatedCount++;
            }

            // Record import metadata
            $this->recordImportMetadata($employee, $rowNumber, $isNewEmployee);
        });

        $this->processedCount++;
    }

    /**
     * Determine employee status from import row
     */
    protected function determineStatus(Collection $row): string
    {
        if (isset($row['status'])) {
            $status = strtolower($row['status']);
            if (in_array($status, ['active', 'on_leave', 'terminated', 'suspended', 'pending_termination'])) {
                return $status;
            }
        }
        return 'active';
    }

    /**
     * Check if employee should be dismissed based on import data
     */
    protected function shouldBeDismissed(Collection $row, Employee $employee, string $previousStatus): bool
    {
        $newStatus = $this->determineStatus($row);
        
        // Case 1: Import explicitly says terminated
        if ($newStatus === 'terminated') {
            return !$employee->is_dismissed;
        }
        
        // Case 2: Employee was active but has dismissal_reason in import
        if (!empty($row['dismissal_reason']) && $employee->status === 'active') {
            return true;
        }
        
        // Case 3: Employee has termination date in the past
        if (!empty($row['termination_date']) && strtotime($row['termination_date']) < time()) {
            return !$employee->is_dismissed;
        }
        
        return false;
    }

    /**
     * Handle employee dismissal during import
     */
    protected function handleDismissal(Employee $employee, Collection $row, int $rowNumber): void
    {
        try {
            $reason = $row['dismissal_reason'] ?? 
                      $row['termination_reason'] ?? 
                      'Imported as terminated via Excel import';
            
            $metadata = [
                'import_row' => $rowNumber,
                'import_file' => request()->file('import_file')->getClientOriginalName(),
                'previous_status' => $employee->getOriginal('status'),
                'termination_date' => $row['termination_date'] ?? now()
            ];
            
            // Use the dismissal service
            $terminationLog = $this->dismissalService->dismiss(
                $employee,
                $reason,
                auth()->user() ?? $this->getSystemUser(),
                $metadata
            );
            
            // Queue final payroll calculation
            FinalPayrollCalculation::dispatch($employee)->delay(now()->addMinutes(5));
            
            $this->importResults['details'][] = [
                'employee_id' => $employee->id,
                'employee_code' => $employee->employee_code,
                'action' => 'dismissed',
                'reason' => $reason,
                'termination_log_id' => $terminationLog->id
            ];
            
            Log::info('Employee dismissed during import', [
                'employee_id' => $employee->id,
                'row' => $rowNumber,
                'reason' => $reason
            ]);
            
        } catch (\Exception $e) {
            throw new \Exception("Failed to dismiss employee: {$e->getMessage()}");
        }
    }

    /**
     * Update or create employee profile
     */
    protected function updateOrCreateProfile(Employee $employee, Collection $row): void
    {
        $profileData = [
            'employee_id' => $employee->id,
            'date_of_birth' => $row['date_of_birth'] ?? null,
            'address' => $row['address'] ?? null,
            'id_number' => $row['id_number'] ?? null,
            'bank_name' => $row['bank_name'] ?? null,
            'bank_account' => $row['bank_account'] ?? null,
            'emergency_contact' => $row['emergency_contact'] ?? null,
            'emergency_phone' => $row['emergency_phone'] ?? null,
            'status' => $employee->status,
        ];

        EmployeeProfile::updateOrCreate(
            ['employee_id' => $employee->id],
            $profileData
        );
    }

    /**
     * Assign employee to station
     */
    protected function assignToStation(Employee $employee, string $stationCode): void
    {
        $station = Station::where('code', $stationCode)->first();
        
        if (!$station) {
            Log::warning('Station not found for import assignment', [
                'station_code' => $stationCode,
                'employee_id' => $employee->id
            ]);
            return;
        }
        
        // Don't reassign if already assigned and not dismissed
        if (!$employee->is_dismissed && !$employee->stations()->where('station_id', $station->id)->exists()) {
            $employee->stations()->attach($station->id, [
                'assigned_at' => now(),
                'assigned_by' => 'import'
            ]);
        }
    }

    /**
     * Record import metadata for audit trail
     */
    protected function recordImportMetadata(Employee $employee, int $rowNumber, bool $isNew): void
    {
        DB::table('import_logs')->insert([
            'employee_id' => $employee->id,
            'import_file' => request()->file('import_file')->getClientOriginalName(),
            'row_number' => $rowNumber,
            'action' => $isNew ? 'created' : 'updated',
            'imported_by' => auth()->id() ?? 0,
            'imported_at' => now(),
            'data_snapshot' => json_encode($employee->toArray()),
            'created_at' => now(),
            'updated_at' => now()
        ]);
    }

    /**
     * Get system user for automated actions
     */
    protected function getSystemUser()
    {
        // Create or get system user for automated operations
        return \App\Models\User::firstOrCreate(
            ['email' => 'system@yourcompany.com'],
            [
                'name' => 'System',
                'password' => bcrypt(uniqid()),
                'is_system' => true
            ]
        );
    }

    /**
     * Validation rules
     */
    public function rules(): array
    {
        return [
            'employee_code' => 'required|string|max:50',
            'name' => 'required|string|max:255',
            'email' => 'nullable|email|max:255',
            'hire_date' => 'required|date',
            'status' => 'nullable|in:active,on_leave,terminated,suspended,pending_termination',
            'station_code' => 'nullable|string|exists:stations,code',
            'dismissal_reason' => 'nullable|string|required_if:status,terminated',
            'termination_date' => 'nullable|date',
        ];
    }

    /**
     * Custom validation messages
     */
    public function customValidationMessages(): array
    {
        return [
            'employee_code.required' => 'Employee code is required',
            'name.required' => 'Employee name is required',
            'hire_date.required' => 'Hire date is required',
            'station_code.exists' => 'Station code does not exist in system',
            'dismissal_reason.required_if' => 'Dismissal reason required when status is terminated',
        ];
    }

    /**
     * Handle validation failures
     */
    public function onFailure(Failure ...$failures)
    {
        foreach ($failures as $failure) {
            $this->errors[] = [
                'row' => $failure->row(),
                'attribute' => $failure->attribute(),
                'errors' => $failure->errors(),
                'values' => $failure->values()
            ];
            
            Log::warning('Import validation failure', [
                'row' => $failure->row(),
                'errors' => $failure->errors()
            ]);
        }
    }

    /**
     * Get import results
     */
    public function getResults(): array
    {
        return [
            'summary' => $this->importResults,
            'errors' => $this->errors,
            'has_errors' => count($this->errors) > 0
        ];
    }

    /**
     * Get error report
     */
    public function getErrorReport(): string
    {
        if (empty($this->errors)) {
            return "Import completed successfully!\n" .
                   "Processed: {$this->importResults['total_rows']}\n" .
                   "Successful: {$this->importResults['successful']}\n" .
                   "Dismissed: {$this->importResults['dismissed']}\n" .
                   "Updated: {$this->importResults['updated']}";
        }
        
        $report = "Import completed with errors:\n\n";
        foreach ($this->errors as $error) {
            $report .= "Row {$error['row']}: " . implode(', ', $error['errors']) . "\n";
        }
        
        return $report;
    }
}