<?php

namespace App\Services\Import\Handlers;

use App\Models\Import;
use App\Models\Person\Person;
use App\Models\Person\PersonGroup;
use App\Models\Person\PersonType;
use App\Services\Import\DateNormalizer;
use App\Services\Import\BaseEntityHandler;
use App\Services\Import\EntityResolutionService;
use Illuminate\Support\Facades\Log;

class PersonHandler extends BaseEntityHandler
{
    protected EntityResolutionService $resolutionService;

    public function __construct($entityConfig = null)
    {
        parent::__construct($entityConfig);
        $this->resolutionService = new EntityResolutionService();
    }

    public function getEntityClass(): string
    {
        return Person::class;
    }

    public function resolve(array $mapped, array $context = []): mixed
    {
        // PHASE 3: Use EntityResolutionService to check chain-based deduplication
        // This prevents creating duplicate Persons when Contract/ClientCase already exists
        $import = $context['import'] ?? null;
        
        if ($import) {
            $personId = $this->resolutionService->resolvePersonFromContext($import, $mapped, $context);
            
            if ($personId) {
                $person = Person::find($personId);
                
                if ($person) {
                    Log::info('PersonHandler: Resolved existing Person via chain', [
                        'person_id' => $personId,
                        'resolution_method' => 'EntityResolutionService',
                    ]);
                    
                    return $person;
                }
            }
        }
        
        // Fall back to configured deduplication fields (tax_number, SSN)
        $dedupeBy = $this->getOption('deduplicate_by', ['tax_number', 'social_security_number']);

        foreach ($dedupeBy as $field) {
            if (! empty($mapped[$field])) {
                $person = Person::where($field, $mapped[$field])->first();
                if ($person) {
                    Log::info('PersonHandler: Resolved existing Person by identifier', [
                        'person_id' => $person->id,
                        'field' => $field,
                    ]);
                    
                    return $person;
                }
            }
        }

        return null;
    }

    public function process(Import $import, array $mapped, array $raw, array $context = []): array
    {
        // Add import to context for EntityResolutionService
        $context['import'] = $import;
        
        $existing = $this->resolve($mapped, $context);

        if ($existing) {
            // Update if configured
            $mode = $this->getOption('update_mode', 'update');

            if ($mode === 'skip') {
                return [
                    'action' => 'skipped',
                    'entity' => $existing,
                    'message' => 'Person already exists (skip mode)',
                ];
            }

            $payload = $this->buildPayload($mapped, $existing);
            $appliedFields = $this->trackAppliedFields($existing, $payload);

            if (empty($appliedFields)) {
                return [
                    'action' => 'skipped',
                    'entity' => $existing,
                    'message' => 'No changes detected',
                ];
            }

            $existing->fill($payload);
            $existing->save();

            return [
                'action' => 'updated',
                'entity' => $existing,
                'applied_fields' => $appliedFields,
            ];
        }

        // Create new person
        Log::info('PersonHandler: Creating new Person (no existing entity found)', [
            'has_tax_number' => !empty($mapped['tax_number']),
            'has_ssn' => !empty($mapped['social_security_number']),
            'has_contract' => isset($context['contract']),
            'has_client_case' => isset($context['client_case']),
        ]);
        
        $person = new Person;
        $payload = $this->buildPayload($mapped, $person);
        
        // Ensure required foreign keys have defaults
        if (!isset($payload['group_id'])) {
            $payload['group_id'] = $this->getDefaultPersonGroupId();
        }
        if (!isset($payload['type_id'])) {
            $payload['type_id'] = $this->getDefaultPersonTypeId();
        }
        
        Log::debug('PersonHandler: Payload before fill', [
            'payload' => $payload,
            'has_group_id' => isset($payload['group_id']),
            'group_id_value' => $payload['group_id'] ?? null,
        ]);
        
        $person->fill($payload);
        
        Log::debug('PersonHandler: Person attributes after fill', [
            'attributes' => $person->getAttributes(),
            'has_group_id' => isset($person->group_id),
            'group_id_value' => $person->group_id ?? null,
        ]);
        
        $person->save();
        
        Log::info('PersonHandler: Created new Person', [
            'person_id' => $person->id,
        ]);

        return [
            'action' => 'inserted',
            'entity' => $person,
            'applied_fields' => array_keys($payload),
        ];
    }

    protected function buildPayload(array $mapped, $model): array
    {
        $payload = [];

        $fieldMap = [
            'first_name' => 'first_name',
            'last_name' => 'last_name',
            'full_name' => 'full_name',
            'gender' => 'gender',
            'birthday' => 'birthday',
            'tax_number' => 'tax_number',
            'social_security_number' => 'social_security_number',
            'description' => 'description',
            'group_id' => 'group_id',
            'type_id' => 'type_id',
        ];

        foreach ($fieldMap as $source => $target) {
            if (array_key_exists($source, $mapped)) {
                $value = $mapped[$source];

                // Normalize date fields
                if ($source === 'birthday' && $value) {
                    $value = DateNormalizer::toDate((string) $value);
                }

                $payload[$target] = $value;
            }
        }

        return $payload;
    }
    
    private function getDefaultPersonGroupId(): int
    {
        return (int) (PersonGroup::min('id') ?? 1);
    }

    private function getDefaultPersonTypeId(): int
    {
        return (int) (PersonType::min('id') ?? 1);
    }
}
