<?php

namespace App\Services;

use App\Models\JurnalTrans;
use App\Models\Kas;
use App\Models\ProdukDeposito;
use App\Models\Tabungan;
use App\Models\TransaksiDeposito;
use App\Repositories\TransaksiDepositoRepository;
use Carbon\Carbon;
use Exception;
use Illuminate\Support\Facades\DB;
use Nette\NotImplementedException;

class TransaksiDepositoService
{
    protected $transaksiDepositoRepository;
    protected $depositoService;
    protected $tabunganService;
    protected $jurnalService;

    public function __construct(TransaksiDepositoRepository $transaksiDepositoRepository, JurnalService $jurnalService, DepositoService $depositoService, TabunganService $tabunganService)
    {
        $this->transaksiDepositoRepository = $transaksiDepositoRepository;
        $this->jurnalService = $jurnalService;
        $this->depositoService = $depositoService;
        $this->tabunganService = $tabunganService;
    }

    public function getAllTransaksi($tgl_awal, $tgl_akhir)
    {
        return $this->transaksiDepositoRepository->getAllTransaksi($tgl_awal, $tgl_akhir);
    }

    public function findTransaksiByTransId($id)
    {
        return $this->transaksiDepositoRepository->findTransaksiByTransId($id);
    }

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

                // Dapatkan saldo saat ini dari tabungan
                $deposito = $this->depositoService->findByRekening($rekening);
                if (!$deposito) {
                    throw new Exception('Rekening tidak ditemukan.');
                }
                $deposito->status = 1;
                $deposito->save();

                $dataTrans = [];
                $dataTrans['trans_kode'] = $data['trans_kode'];
                $dataTrans['trans_date'] = Carbon::now();
                $dataTrans['trans_tglbuku'] = $data['trans_tglbuku'];
                $dataTrans['rekening'] = $data['rekening'];
                $dataTrans['keterangan'] = "Setoran deposito " . $deposito->anggota->nama_lengkap . " (" . $deposito->rekening . ") Tunai";

                $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;
                $dataTrans['trans_id'] = $trans_id;

                $produk = ProdukDeposito::where('id', $deposito->produk_id)->first();
                $kas = Kas::where('is_default', 1)->first();

                $akun_kas = $kas->akun_kas;
                $akun_deposito = $produk->akun_jurnal_id;

                // setoran deposito tunai
                if ($data['trans_kode'] === '41') {
                    $dataTrans['setor'] = $deposito->nilai_valuta;
                    $dataTrans['tarik'] = 0;

                    $this->jurnalService->createJurnal([
                        'trans_id' => $dataTrans['trans_id'],
                        'trans_kode' => $dataTrans['trans_kode'],
                        'akun_jurnal' => $akun_kas,
                        'debet' => $deposito->nilai_valuta,
                        'kredit' => 0,
                        'keterangan' => $dataTrans['keterangan'],
                        'trans_tglbuku' => $dataTrans['trans_tglbuku'],
                        'trans_date' => $dataTrans['trans_date']
                    ]);
                    $this->jurnalService->createJurnal([
                        'trans_id' => $dataTrans['trans_id'],
                        'trans_kode' => $dataTrans['trans_kode'],
                        'akun_jurnal' => $akun_deposito,
                        'debet' => 0,
                        'kredit' => $deposito->nilai_valuta,
                        'rekening' => $dataTrans['rekening'],
                        'keterangan' => $dataTrans['keterangan'],
                        'trans_tglbuku' => $dataTrans['trans_tglbuku'],
                        'trans_date' => $dataTrans['trans_date']
                    ]);
                }
                // penarikan deposito tunai
                else if ($data['trans_kode'] === '42') { // 'tarik'
                    $dataTrans['setor'] = 0;
                    $dataTrans['tarik'] = $data['nominal'];
                    $dataTrans['keterangan'] = "Penarikan deposito " . $deposito->anggota->nama_lengkap . " (" . $deposito->rekening . ") Tunai";

                    $this->jurnalService->createJurnal([
                        'trans_id' => $dataTrans['trans_id'],
                        'trans_kode' => $dataTrans['trans_kode'],
                        'akun_jurnal' => $akun_kas,
                        'debet' => 0,
                        'kredit' => $deposito->nilai_valuta,
                        'keterangan' => $dataTrans['keterangan'],
                        'trans_tglbuku' => $dataTrans['trans_tglbuku'],
                        'trans_date' => $dataTrans['trans_date']
                    ]);

                    $this->jurnalService->createJurnal([
                        'trans_id' => $dataTrans['trans_id'],
                        'trans_kode' => $dataTrans['trans_kode'],
                        'akun_jurnal' => $akun_deposito,
                        'debet' => $deposito->nilai_valuta,
                        'kredit' => 0,
                        'rekening' => $dataTrans['rekening'],
                        'keterangan' => $dataTrans['keterangan'],
                        'trans_tglbuku' => $dataTrans['trans_tglbuku'],
                        'trans_date' => $dataTrans['trans_date']
                    ]);
                }
                // setoran deposito overbooking
                else if ($data['trans_kode'] === '43') {
                    $tabungan = $this->tabunganService->findById($deposito->rekening_tabungan);
                    if (!$tabungan) {
                        throw new Exception('Rekening Tabungan tidak ditemukan.');
                    }

                    if ($tabungan->saldo < $deposito->nilai_valuta) {
                        throw new Exception('Saldo tidak mencukupi.');
                    }

                    $tabungan->saldo = $tabungan->saldo - $deposito->nilai_valuta;
                    $tabungan->save();

                    $ob_rekening = $this->tabunganService->findById($data['ob_rekening']);

                    $dataTrans['ob_rekening'] = $data['ob_rekening'];
                    $dataTrans['setor'] = $deposito->nilai_valuta;
                    $dataTrans['tarik'] = 0;
                    $dataTrans['keterangan'] = "Setoran deposito " . $deposito->anggota->nama_lengkap . " (" . $deposito->rekening . ") OB dari Tabungan";

                    $this->jurnalService->createJurnal([
                        'trans_id' => $dataTrans['trans_id'],
                        'trans_kode' => $dataTrans['trans_kode'],
                        'akun_jurnal' => $ob_rekening->produk->akun_simpanan_id,
                        'debet' => $deposito->nilai_valuta,
                        'kredit' => 0,
                        'rekening' => $dataTrans['ob_rekening'],
                        'keterangan' => $dataTrans['keterangan'],
                        'trans_tglbuku' => $dataTrans['trans_tglbuku'],
                        'trans_date' => $dataTrans['trans_date']
                    ]);
                    $this->jurnalService->createJurnal([
                        'trans_id' => $dataTrans['trans_id'],
                        'trans_kode' => $dataTrans['trans_kode'],
                        'akun_jurnal' => $akun_deposito,
                        'debet' => 0,
                        'kredit' => $deposito->nilai_valuta,
                        'rekening' => $dataTrans['rekening'],
                        'keterangan' => $dataTrans['keterangan'],
                        'trans_tglbuku' => $dataTrans['trans_tglbuku'],
                        'trans_date' => $dataTrans['trans_date']
                    ]);
                } else {
                    throw new Exception('Kode transaksi tidak valid.');
                }


                $transaksi = $this->transaksiDepositoRepository->createTransaksi($dataTrans);

                return $transaksi;
            });
        } catch (Exception $error) {
            throw new Exception($error->getMessage());
        }
    }

    public function validasiTransaksi($id)
    {
        try {
            DB::transaction(function () use ($id) {
                $transaksi = TransaksiDeposito::find($id);
                if (!$transaksi) {
                    throw new Exception('Transaksi tidak ditemukan.');
                }
                $transaksi->status = 1;
                $transaksi->save();

                $jurnals = JurnalTrans::where('trans_id', $transaksi->trans_id)->get();
                foreach ($jurnals as $jurnal) {
                    $jurnal->status = 1;
                    $jurnal->save();
                }

                $kas = Kas::where('is_default', 1)->first();

                $trans_kode = $transaksi->trans_kode;
                if ($trans_kode === '41') {
                    $kas->saldo = $kas->saldo + $transaksi->setor;
                    $kas->save();
                } else if ($trans_kode === '42') {
                    $kas->saldo = $kas->saldo - $transaksi->tarik;
                    $kas->save();
                } elseif ($trans_kode === '43') {
                    $tabungan = Tabungan::where('rekening', $transaksi->ob_rekening)->first();
                    $tabungan->saldo = $tabungan->saldo - $transaksi->setor;
                    $tabungan->save();
                }
                return $transaksi;
            });
            return response()->json(['message' => 'Transaksi berhasil divalidasi'], 200);
        } catch (Exception $error) {
            throw new \Exception('Error validating transaction: ' . $error->getMessage(), 500);
        }
    }

    public function deleteTransaksi($id)
    {
        try {
            DB::transaction(function () use ($id) {
                $transaksi = TransaksiDeposito::find($id);
                if (!$transaksi) {
                    throw new Exception('Transaksi tidak ditemukan.');
                }
                $transaksi->status = 9;
                $transaksi->save();

                $jurnals = JurnalTrans::where('trans_id', $transaksi->trans_id)->get();
                foreach ($jurnals as $jurnal) {
                    $jurnal->status = 9;
                    $jurnal->save();
                }

                $kas = Kas::where('is_default', 1)->first();


                $trans_kode = $transaksi->trans_kode;
                if ($trans_kode === '41') {
                    $kas->saldo = $kas->saldo - $transaksi->setor;
                    $kas->save();
                } else if ($trans_kode === '42') {
                    $kas->saldo = $kas->saldo + $transaksi->tarik;
                    $kas->save();
                } elseif ($trans_kode === '43') {
                    $tabungan = Tabungan::where('rekening', $transaksi->ob_rekening)->first();
                    $tabungan->saldo = $tabungan->saldo + $transaksi->setor;
                    $tabungan->save();
                }

                return $transaksi;
            });
            return response()->json(['message' => 'Transaksi berhasil dihapus'], 200);
        } catch (Exception $error) {
            throw new \Exception('Error Deleting transaction: ' . $error->getMessage(), 500);
        }
    }
}
