<?php

namespace App\Services\Pagarme;

use App\Data\Pagarme\Request\CustomerRequestData\CustomerAddressRequestData;
use App\Data\Pagarme\Request\CustomerRequestData\CustomerPhonesRequestData\CustomerPhoneData;
use App\Data\Pagarme\Request\CustomerRequestData\CustomerPhonesRequestData\CustomerPhonesRequestData;
use App\Data\Pagarme\Request\CustomerRequestData\CustomerRequestData;
use App\Data\Pagarme\Response\CustomerResponseData\CustomerResponseData;
use App\Models\Client;
use App\Services\Pagarme\Concerns\FormatsPagarmeData;
use App\Services\Pagarme\Concerns\SendsPagarmeRequests;

class PagarmeCustomerService
{
    use FormatsPagarmeData;
    use SendsPagarmeRequests;

    public function createCustomerForClient(Client $client, array $data): ?string
    {
        if (! empty($client->external_customer_id)) {
            return $client->external_customer_id;
        }

        $client->loadMissing('user');

        $name = $client->user?->name ?? $data['name'] ?? 'Cliente';
        $email = $client->user?->email ?? $data['email'] ?? null;
        $code = $client->ensureGatewayCode();

        $document = $this->digits($client->document ?? $data['document'] ?? null);
        $documentLen = strlen($document);

        $address = $this->buildAddressData($data);
        $phones = $this->buildPhones($client->user?->phone ?? $data['phone'] ?? null);

        $customerRequest = new CustomerRequestData(
            name: $name,
            email: (string) $email,
            document: $document,
            type: $documentLen === 14 ? 'company' : 'individual',
            documentType: $documentLen === 14 ? 'CNPJ' : 'CPF',
            code: $code,
            address: $address,
            phones: $phones,
        );

        $customerData = CustomerResponseData::fromArray($this->pagarmeRequest(
            method: 'POST',
            path: '/customers',
            payload: $customerRequest,
            idempotencyKey: $this->idempotencyKey($client->id),
            errorMessage: 'Erro ao criar cliente no Pagar.me.',
        ));

        $customerId = $customerData->requireId();

        $client->forceFill([
            'external_customer_id'   => $customerId,
            'external_customer_code' => $code,
        ])->save();

        return $customerId;
    }

    //

    private function buildAddressData(array $data): CustomerAddressRequestData
    {
        $line1Parts = array_filter([
            (string) ($data['number'] ?? '0'),
            (string) ($data['address'] ?? ''),
            (string) ($data['district'] ?? ''),
        ], static fn ($value) => $value !== '');

        return new CustomerAddressRequestData(
            line1: implode(', ', $line1Parts),
            line2: (string) ($data['complement'] ?? $data['instructions'] ?? ''),
            zipCode: $this->digits($data['zip_code'] ?? null),
            city: (string) ($data['city'] ?? ''),
            state: (string) ($data['state'] ?? ''),
            country: (string) ($data['country'] ?? 'BR'),
        );
    }

    private function buildPhones(?string $phone): CustomerPhonesRequestData
    {
        $digits = $this->digits($phone);

        if ($digits === '') {
            return new CustomerPhonesRequestData;
        }

        $areaCode = substr($digits, 0, 2);
        $number = substr($digits, 2);

        if (strlen($digits) <= 2) {
            $areaCode = '';
            $number = $digits;
        }

        return new CustomerPhonesRequestData(
            mobilePhone: new CustomerPhoneData(
                countryCode: '55',
                areaCode: $areaCode,
                number: $number,
            ),
        );
    }

    // evita criacao duplicada de customer

    private function idempotencyKey(int $clientId, string $suffix = 'customer'): string
    {
        return "client-{$clientId}-{$suffix}";
    }
}
