<?php

namespace App\Services\Sale;

use App\Enums\PaymentPlanType;
use App\Enums\SalesType;
use App\Http\Messages\ErrorMessages;
use App\Repositories\Sale\PaymentPlansRepositoryInterface;
use Illuminate\Support\Facades\DB;
use App\Repositories\Sale\SaleRepositoryInterface;

class SaleService
{
    protected $saleRepository;
    protected $paymentPlansRepository;
    public function __construct(SaleRepositoryInterface $saleRepository, PaymentPlansRepositoryInterface $paymentPlansRepositoryInterface)
    {
        $this->saleRepository = $saleRepository;
        $this->paymentPlansRepository = $paymentPlansRepositoryInterface;
    }

    public function getAllSales()
    {
        return $this->saleRepository->all();
    }

    public function createSales($data)
    {
        // $this->verifDiffer($data);
        $data['status'] = SalesType::PRESALE->value;
        $sale = $this->saleRepository->create($data)->refresh();
        foreach ($data['properties'] as $property) {
            $property['sale_id'] = $sale->id;
            $this->saleRepository->generateDetailSale($property);
        }
        foreach ($data['differs_initial_fee'] as $differInitialFee) {
            $differInitialFee['sales_id'] = $sale->id;
            $differInitialFee['type'] = PaymentPlanType::INITIAL_PAYMENT->value;
            $this->paymentPlansRepository->create($differInitialFee);
        }
        foreach ($data['differs_balance'] as $differBalance) {
            $differBalance['sales_id'] = $sale->id;
            $differBalance['type'] = PaymentPlanType::BALANCE->value;
            $this->paymentPlansRepository->create($differBalance);
        }
        return $sale;
    }

    public function verifDiffer($data)
    {
        $differsInitialFee = collect($data['differs_initial_fee']);
        $differsBalance = collect($data['differs_balance']);

        // Verifica si "differs_initial_fee" tiene elementos antes de hacer la suma
        if ($differsInitialFee->isNotEmpty()) {
            $differsInitialFeeSum = $differsInitialFee->sum('amount');
            if ($differsInitialFeeSum != $data['initial_fee']) {
                throw new \Exception(ErrorMessages::INITIAL_FEE_MISMATCH, 404);
            }
        }

        // Verifica si "differs_balance" tiene elementos antes de hacer la suma
        if ($differsBalance->isNotEmpty()) {
            $differsBalanceSum = $differsBalance->sum('amount');
            if ($differsBalanceSum != ($data['amount'] - $data['initial_fee'])) {
                throw new \Exception(ErrorMessages::BALANCE_MISMATCH, 404);
            }
        }
    }

    public function changeStatus($id, $status)
    {
        $this->isSaleExists($id);
        return $this->saleRepository->update($id, ['status' => $status]);
    }


    public function changeConfirmationSignature($id)
    {
        $sale = $this->isSaleExists($id);
        return $this->saleRepository->update($id, ['confirmation_signature' => !$sale->confirmation_signature]);
    }

    public function updateSale($id, $data)
    {
        return DB::transaction(function () use ($id, $data) {
            $this->isSaleExists($id);
            $this->saleRepository->update($id, $data);
            return $this->saleRepository->find($id);
        });
    }

    private function isSaleExists($saleId)
    {
        return $this->saleRepository->find($saleId)
            ?? throw new \Exception(ErrorMessages::SALE_NOT_FOUND, 404);
    }

    public function getSalebyId($id)
    {
        return $this->isSaleExists($id);
    }

    public function getSalebyOpportunityId($id)
    {
        return $this->saleRepository->getByOpportunity($id)
            ?? throw new \Exception(ErrorMessages::SALE_NOT_FOUND, 404);
    }

    public function getAllsalepagination($datos)
    {
        $query = $this->saleRepository->allquery();

        if ($datos->filled('search')) {
            $searchTerm = $datos->query('search');
            $query->where(function ($query) use ($searchTerm) {
                $query->where('social_reason', 'like', '%' . $searchTerm . '%');
                $query->orWhere('nit', 'like', '%' . $searchTerm . '%');
            });
        }

        if ($datos->query('sortBy') && $datos->query('orderBy')) {
            $sortBy = $datos->query('sortBy');
            $orderBy = $datos->query('orderBy');
            $query->orderBy($sortBy, $orderBy);
        }

        $itemsPerPage = $datos->query('itemsPerPage', 10);
        $page = $datos->query('page', 1);
        return  $query->paginate($itemsPerPage, ['*'], 'page', $page);
    }


}
