<?php

namespace App\Services;

use App\Models\Deposito;
use App\Models\TransaksiDeposito;
use App\Repositories\DepositoRepository;
use Carbon\Carbon;
use Exception;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\DB;

class DepositoService
{
    protected $depositoRepository;

    public function __construct(DepositoRepository $depositoRepository)
    {
        $this->depositoRepository = $depositoRepository;
    }

    public function getAll(): Collection
    {
        return $this->depositoRepository->getAll();
    }

    public function createDeposito(array $data): Deposito
    {
        $count = $this->depositoRepository->count();
        $id = "D" . str_pad($count + 1, 5, "0", STR_PAD_LEFT);

        $produk_deposito = $this->depositoRepository->findProdukById($data['produk_id']);
        if (!$produk_deposito) {
            throw new \Exception('Produk deposito tidak ditemukan');
        }

        $data['rekening'] = $id;
        $data['tgl_buka'] = Carbon::now();
        $data['suku_bunga'] = $produk_deposito->suku_bunga;
        $data['jkw'] = $produk_deposito->jkw;
        $data['status'] = 0;

        return $this->depositoRepository->createDeposito($data);
    }

    public function updateTabungan($id, array $data): Deposito
    {
        $tabungan = $this->depositoRepository->findById($id);
        if (!$tabungan) {
            throw new \Exception('Tabungan tidak ditemukan');
        }

        unset($data['saldo']);

        return $this->depositoRepository->updateDeposito($id, $data);
    }

    public function findById($id): ?Deposito
    {
        return $this->depositoRepository->findById($id);
    }

    public function findByRekening($rekening): ?Deposito
    {
        return $this->depositoRepository->findByRekening($rekening);
    }

    public function updateDeposito($id, array $data): Deposito
    {
        $deposito = $this->depositoRepository->findById($id);
        if (!$deposito) {
            throw new \Exception('Deposito tidak ditemukan');
        }
        return $this->depositoRepository->updateDeposito($id, $data);
    }

    public function deleteDeposito($id)
    {
        $deposito = $this->depositoRepository->findById($id);
        if (!$deposito) {
            throw new \Exception('Deposito tidak ditemukan');
        }
        return $this->depositoRepository->deleteDeposito($id);
    }

    public function findByAnggotaId($anggotaId): Collection
    {
        return $this->depositoRepository->findByAnggotaId($anggotaId);
    }

    public function transaksiDeposito(array $data)
    {
        return DB::transaction(function () use ($data) {
            $rekening = $data['rekening'];

            // Dapatkan saldo saat ini dari tabungan
            $tabungan = $this->depositoRepository->findByRekening($rekening);
            if (!$tabungan) {
                throw new Exception('Tabungan tidak ditemukan.');
            }
            $saldoSaatIni = $tabungan->saldo;

            // Hitung saldo baru
            if ($data['trans_kode'] === '12') {
                $saldoBaru = $saldoSaatIni + $data['setor'];
            } else
            if ($data['trans_kode'] === '13') { // 'tarik'
                if ($saldoSaatIni < $data['tarik']) {
                    throw new Exception('Saldo tidak mencukupi untuk melakukan penarikan.');
                }
                $saldoBaru = $saldoSaatIni - $data['tarik'];
            } else {
                throw new Exception('Kode transaksi tidak valid.');
            }

            $tabungan->saldo = $saldoBaru;
            $tabungan->save();

            $trans_tglbuku = Carbon::parse($data['trans_tglbuku']);

            $jumlah_transaksi = TransaksiDeposito::whereYear('trans_tglbuku', $trans_tglbuku->format('Y'))->whereMonth('trans_tglbuku', $trans_tglbuku->format('m'))->count();
            $trans_id = $data['trans_kode'] . "." . $trans_tglbuku->format('Ymd') . "." . str_pad($jumlah_transaksi + 1, 5, "0", STR_PAD_LEFT);

            $data['trans_id'] = $trans_id;

            return $this->depositoRepository->transaksiDeposito($data);
        });
    }

    public function deleteTransaksiDeposito($id)
    {
        return $this->depositoRepository->deleteTransaksiDeposito($id);
    }

    public function getAllProduk()
    {
        return $this->depositoRepository->getAllProduk();
    }

    public function createProduk(array $data)
    {
        return $this->depositoRepository->createProduk($data);
    }

    public function updateProduk($id, array $data)
    {
        $produk = $this->depositoRepository->findProdukById($id);
        if (!$produk) {
            throw new \Exception('Produk deposito tidak ditemukan');
        }

        if ($data['nama'] && $data['nama'] != $produk->nama) {
            $produk = $this->depositoRepository->findProdukByNama($data['nama']);
            if ($produk) {
                throw new \Exception('duplikat nama produk');
            };
        }

        return $this->depositoRepository->updateProduk($id, $data);
    }

    public function deleteProdukDeposito($id)
    {
        $produk = $this->depositoRepository->findProdukById($id);
        if (!$produk) {
            throw new \Exception('Produk deposito tidak ditemukan');
        }
        return $this->depositoRepository->deleteProdukDeposito($id);
    }
}
