<?php

namespace App\Services\Pagarme\Concerns;

use Carbon\Carbon;
use Illuminate\Support\Str;

trait FormatsPagarmeData
{
    protected function digits(?string $value): string
    {
        return preg_replace('/\D+/', '', (string) $value) ?? '';
    }

    protected function pagarmeIdempotencyKey(string $prefix, array $parts): string
    {
        $segments = [Str::slug($prefix)];

        foreach ($parts as $part) {
            $slug = Str::slug(trim((string) $part));

            if ($slug !== '') {
                $segments[] = $slug;
            }
        }

        return implode('-', array_filter($segments));
    }

    //

    protected function customerDocument(?string $value): string
    {
        $document = trim((string) $value);

        if (preg_match('/[A-Za-z]/', $document) === 1) {
            return $document;
        }

        return $this->digits($document);
    }

    protected function customerDocumentType(string $document): string
    {
        if (preg_match('/[A-Za-z]/', $document) === 1) {
            return 'PASSPORT';
        }

        $length = strlen($this->digits($document));

        return match ($length) {
            11      => 'CPF',
            14      => 'CNPJ',
            default => 'PASSPORT',
        };
    }

    protected function extractAddressParts(array $data): array
    {
        $addressLine   = trim((string) data_get($data, 'address', ''));
        $segments      = array_map('trim', explode(',', $addressLine));
        $streetSegment = data_get($segments, 0, '');
        $streetNumber  = data_get($data, 'number');

        if ($streetNumber === null) {
            $matches = [];

            preg_match('/^(\d+)/', $streetSegment, $matches);

            $streetNumber = data_get($matches, 1, 'S/N');
        }

        return [
            'street'          => $streetSegment,
            'street_number'   => (string) $streetNumber,
            'neighborhood'    => (string) data_get($data, 'district', data_get($segments, 1, 'N/A')),
            'reference_point' => (string) data_get($data, 'reference_point', 'N/A'),
            'complementary'   => (string) data_get($data, 'complement', 'N/A'),
        ];
    }

    protected function formatBirthdate(mixed $birthdate): ?string
    {
        if ($birthdate === null || $birthdate === '') {
            return null;
        }

        if ($birthdate instanceof \DateTimeInterface) {
            return Carbon::instance($birthdate)->format('d/m/Y');
        }

        $birthdate = trim((string) $birthdate);

        if (preg_match('/^\d{2}\/\d{2}\/\d{4}$/', $birthdate) === 1) {
            return $birthdate;
        }

        if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $birthdate) === 1) {
            return Carbon::createFromFormat('Y-m-d', $birthdate)->format('d/m/Y');
        }

        return Carbon::parse($birthdate)->format('d/m/Y');
    }

    protected function normalizeHolderName(string $holderName): string
    {
        $holderName = trim(preg_replace('/\s+/', ' ', $holderName) ?? '');

        if (Str::length($holderName) < 30) {
            return $holderName;
        }

        $parts = explode(' ', $holderName);

        if (count($parts) >= 3) {
            $firstName = array_shift($parts);
            $lastName  = array_pop($parts);

            $initials = array_map(
                static fn (string $part): string => Str::upper(Str::substr($part, 0, 1)),
                $parts
            );

            $abbreviated = trim($firstName.' '.implode(' ', $initials).' '.$lastName);

            if (Str::length($abbreviated) < 30) {
                return $abbreviated;
            }

            $firstAndLast = trim($firstName.' '.$lastName);

            if (Str::length($firstAndLast) < 30) {
                return $firstAndLast;
            }
        }

        return Str::limit($holderName, 29, '');
    }
}
