<?php

namespace App\Services;

use App\Models\Merchant;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class MerchantService
{
    /**
     * Criar um novo comerciante
     *
     * @throws \Exception
     */
    public function createMerchant(array $data): Merchant
    {
        // Validação extra: NIF e BI únicos
        if (Merchant::where('identity_number', $data['identity_number'])->exists()) {
            throw new \Exception('Já existe comerciante com este número de identidade.');
        }

        if (Merchant::where('tax_number', $data['tax_number'])->exists()) {
            throw new \Exception('Já existe comerciante com este NIF.');
        }

        if (empty($data['phone'])) {
            throw new \Exception('Telefone é obrigatório.');
        }

        DB::beginTransaction();
        try {
            $merchant = Merchant::create([
                'business_type_id' => $data['business_type_id'],
                'full_name' => $data['full_name'],
                'birth_date' => $data['birth_date'],
                'identity_number' => $data['identity_number'],
                'identity_type' => $data['identity_type'],
                'tax_number' => $data['tax_number'],
                'phone' => $data['phone'],
                'alternate_phone' => $data['alternate_phone'] ?? null,
                'email' => $data['email'] ?? null,
                'address' => $data['address'],
                'photo_url' => $data['photo_url'] ?? null,
                'status' => 'pending',
                'metadata' => $data['metadata'] ?? [],
            ]);

            DB::commit();
            Log::info('Comerciante criado', ['merchant_id' => $merchant->id]);

            return $merchant;
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Erro ao criar comerciante', ['error' => $e->getMessage(), 'data' => $data]);
            throw $e;
        }
    }

    /**
     * Atualizar um comerciante existente
     *
     * @throws \Exception
     */
    public function updateMerchant(int $id, array $data): Merchant
    {
        $merchant = Merchant::findOrFail($id);

        // Não permitir editar comerciante aprovado
        if ($merchant->approved_at) {
            throw new \Exception('Não é permitido editar comerciante já aprovado.');
        }

        // Validação extra: NIF e BI únicos (exceto o próprio)
        if (isset($data['identity_number']) &&
            Merchant::where('identity_number', $data['identity_number'])
                ->where('id', '!=', $id)
                ->exists()) {
            throw new \Exception('Já existe comerciante com este número de identidade.');
        }

        if (isset($data['tax_number']) &&
            Merchant::where('tax_number', $data['tax_number'])
                ->where('id', '!=', $id)
                ->exists()) {
            throw new \Exception('Já existe comerciante com este NIF.');
        }

        if (isset($data['phone']) && empty($data['phone'])) {
            throw new \Exception('Telefone é obrigatório.');
        }

        DB::beginTransaction();
        try {
            $merchant->update([
                'business_type_id' => $data['business_type_id'] ?? $merchant->business_type_id,
                'full_name' => $data['full_name'] ?? $merchant->full_name,
                'birth_date' => $data['birth_date'] ?? $merchant->birth_date,
                'identity_number' => $data['identity_number'] ?? $merchant->identity_number,
                'identity_type' => $data['identity_type'] ?? $merchant->identity_type,
                'tax_number' => $data['tax_number'] ?? $merchant->tax_number,
                'phone' => $data['phone'] ?? $merchant->phone,
                'alternate_phone' => $data['alternate_phone'] ?? $merchant->alternate_phone,
                'email' => $data['email'] ?? $merchant->email,
                'address' => $data['address'] ?? $merchant->address,
                'photo_url' => $data['photo_url'] ?? $merchant->photo_url,
                'metadata' => $data['metadata'] ?? $merchant->metadata,
            ]);

            DB::commit();
            Log::info('Comerciante atualizado', ['merchant_id' => $merchant->id]);

            return $merchant;
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Erro ao atualizar comerciante', ['merchant_id' => $id, 'error' => $e->getMessage()]);
            throw $e;
        }
    }

    /**
     * Aprovar um comerciante
     *
     * @throws \Exception
     */
    public function approveMerchant(int $id, int $approvedBy): Merchant
    {
        $merchant = Merchant::findOrFail($id);

        if ($merchant->approved_at) {
            throw new \Exception('Comerciante já foi aprovado anteriormente.');
        }

        DB::beginTransaction();
        try {
            $merchant->update([
                'status' => 'approved',
                'approved_by' => $approvedBy,
                'approved_at' => now(),
            ]);

            DB::commit();
            Log::info('Comerciante aprovado', ['merchant_id' => $merchant->id, 'approved_by' => $approvedBy]);

            return $merchant;
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Erro ao aprovar comerciante', ['merchant_id' => $id, 'error' => $e->getMessage()]);
            throw $e;
        }
    }

    /**
     * Bloquear um comerciante
     *
     * @throws \Exception
     */
    public function blockMerchant(int $id): Merchant
    {
        $merchant = Merchant::findOrFail($id);

        if ($merchant->status === 'suspended') {
            throw new \Exception('Comerciante já está bloqueado.');
        }

        DB::beginTransaction();
        try {
            $merchant->update(['status' => 'suspended']);

            DB::commit();
            Log::info('Comerciante bloqueado', ['merchant_id' => $merchant->id]);

            return $merchant;
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Erro ao bloquear comerciante', ['merchant_id' => $id, 'error' => $e->getMessage()]);
            throw $e;
        }
    }

    /**
     * Desbloquear um comerciante
     *
     * @throws \Exception
     */
    public function unblockMerchant(int $id): Merchant
    {
        $merchant = Merchant::findOrFail($id);

        DB::beginTransaction();
        try {
            $merchant->update(['status' => 'active']);

            DB::commit();
            Log::info('Comerciante desbloqueado', ['merchant_id' => $merchant->id]);

            return $merchant;
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Erro ao desbloquear comerciante', ['merchant_id' => $id, 'error' => $e->getMessage()]);
            throw $e;
        }
    }

    /**
     * Obter comerciante por ID
     */
    public function getMerchant(int $id): ?Merchant
    {
        return Merchant::find($id);
    }

    /**
     * Obter todos os comerciantes ativos
     */
    public function getActiveMerchants()
    {
        return Merchant::where('status', 'active')
            ->orderBy('full_name')
            ->get();
    }

    /**
     * Obter comerciantes por tipo de negócio
     */
    public function getMerchantsByBusinessType(int $businessTypeId)
    {
        return Merchant::where('business_type_id', $businessTypeId)
            ->orderBy('full_name')
            ->get();
    }
}
