<?php

namespace App\Services;

use App\Models\Address;
use App\Models\City;
use App\Models\Client;
use App\Models\State;
use App\Models\User;
use App\Services\Pagarme\PagarmeCustomerService;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class ClientService
{
    public function __construct(
        private readonly AuthService $authService, private readonly PagarmeCustomerService $pagarmeCustomerService
    ) {}

    public function getAll(): Collection
    {
        return Client::with(['user'])->get();
    }

    public function findById(int $id): ?Client
    {
        return Client::with(['user'])->find($id);
    }

    public function create(array $data): Client
    {
        return Client::create($data);
    }

    public function update(array $data, int $id)
    {
        $client = Client::findOrFail($id);

        $client->update($data);

        return $client;
    }

    public function delete(int $id): bool
    {
        $client = Client::findOrFail($id);

        return $client->delete();
    }

    public function register(array $data): ?array
    {
        try {
            DB::beginTransaction();

            $user = User::when(! empty($data['email']), function ($q) use ($data) {
                $q->where('email', $data['email']);
            })
                ->when(! empty($data['phone']), function ($q) use ($data) {
                    $q->where('phone', $data['phone']);
                })
                ->where('type', 'CLIENT')
                ->where('code', $data['code'])
                ->first();

            if (! $user) {
                throw new \Exception(__('messages.user_not_found_or_code_not_validated'));
            }

            if (! empty($data['name'])) {
                $user->name = $data['name'];

                $user->save();
            }

            $client = Client::firstOrCreate(
                ['user_id' => $user->id], ['document' => $data['document'] ?? null]
            );

            if (! empty($data['document'])) {
                $client->document = $data['document'];

                $client->save();
            }

            $client->refresh();

            $addressData = [
                'zip_code'       => $data['zip_code'] ?? null,
                'address'        => $data['address'] ?? null,
                'number'         => $data['number'] ?? null,
                'district'       => $data['district'] ?? null,
                'has_complement' => $data['has_complement'] ?? false,
                'complement'     => $data['complement'] ?? null,
                'nickname'       => $data['nickname'] ?? null,
                'instructions'   => $data['instructions'] ?? null,
                'address_type'   => $data['address_type'] ?? 'home',
                'is_primary'     => true,
                'latitude'       => $data['latitude'] ?? null,
                'longitude'      => $data['longitude'] ?? null,
            ];

            if (! empty($data['state']) && ! empty($data['city'])) {
                $state = State::where('code', $data['state'])->first();

                if ($state) {
                    $city = City::where('name', $data['city'])->where('state_id', $state->id)->first();

                    $addressData['state_id'] = $state->id;
                    $addressData['city_id'] = $city?->id;
                }
            }

            Address::updateOrCreate(
                ['source' => 'client', 'source_id' => $client->id],
                $addressData
            );

            $this->pagarmeCustomerService->createCustomerForClient($client, $data);

            $registrationComplete = ! empty($user->name)
              && ! empty($client->document)
              && Address::where('source', 'client')->where('source_id', $client->id)->exists();

            if ($registrationComplete !== $user->registration_complete) {
                $user->registration_complete = $registrationComplete;

                $user->save();
            }

            $result = $this->authService->loginWithEmail(
                email: $user->email,
                code: $user->code,
            );

            DB::commit();

            return $result;
        } catch (\Exception $e) {
            DB::rollBack();

            Log::error('Error registering client: '.$e->getMessage());

            throw $e;
        }
    }
}
