<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Akun;
use App\Models\Cashtransaction;
use App\Models\Language;
use App\Models\Licence;
use App\Models\Product;
use App\Models\Subcashtransaction;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use LengthException;

class AkunController extends Controller
{
    private $total;

    public static function getActiveLanguage()
    {
        return Language::where('status', true)->first();
    }

    private function loadAkunMapping($langCode = 'id')
    {
        $jsonPath = config_path("lang/{$langCode}/akun.json");

        // Fallback ke bahasa Indonesia jika file tidak ditemukan
        if (!file_exists($jsonPath)) {
            $jsonPath = config_path('lang/id/akun.json');
        }

        if (!file_exists($jsonPath)) {
            return [];
        }

        return json_decode(file_get_contents($jsonPath), true) ?? [];
    }

    private function translateAccountName($accountName, $companyType, $mappingData)
    {
        // Prioritaskan translasi berdasarkan tipe perusahaan
        if (isset($mappingData[$companyType][$accountName])) {
            return $mappingData[$companyType][$accountName];
        }

        // Fallback ke translasi umum
        if (isset($mappingData['akun_umum'][$accountName])) {
            return $mappingData['akun_umum'][$accountName];
        }

        // Jika tidak ditemukan, kembalikan nama asli
        return $accountName;
    }

    // Ubah nama akun sesuai company_type dengan multi-bahasa
    private function ubahNamaAkunSesuaiTipe(&$items, $companyType, $mappingData)
    {
        foreach ($items as $item) {
            $item->name = $this->translateAccountName($item->name, $companyType, $mappingData);

            if ($item->children && $item->children->count() > 0) {
                $this->ubahNamaAkunSesuaiTipe($item->children, $companyType, $mappingData);
            }
        }
    }

    // Tambah nama akun (rename) sesuai company_type dengan multi-bahasa
    private function tambahNamaAkunSesuaiTipe(&$items, $companyType, $mappingData)
    {
        foreach ($items as $item) {
            $item->rename = $this->translateAccountName($item->name, $companyType, $mappingData);

            if ($item->children && $item->children->count() > 0) {
                $this->tambahNamaAkunSesuaiTipe($item->children, $companyType, $mappingData);
            }
        }
    }

    private function hapusAkun(&$data, $namesToExclude)
    {
        foreach ($data as $key => &$value) {
            if (in_array($value->name, $namesToExclude)) {
                unset($data[$key]);
                continue;
            }

            if (!empty($value->children)) {
                $this->hapusAkun($value->children, $namesToExclude);
            }
        }
    }

    // Fungsi bantu untuk membuat array nested 'children.children...'
    private function generateChildrenWith($depth)
    {
        $relation = 'children';
        $relations = [];
        for ($i = 0; $i < $depth; $i++) {
            $relations[] = $relation;
            $relation .= '.children';
        }
        return $relations;
    }

    // Proses khusus untuk yayasan dengan multi-bahasa
    private function processYayasanDanaConfig(&$data, $mappingData)
    {
        foreach ($data as &$akunModal) {
            $modalTranslated = $this->translateAccountName('Modal', 'yayasan', $mappingData);

            if ($akunModal->name === 'Modal' || $akunModal->name === $modalTranslated) {
                if (!($akunModal->children instanceof Collection)) {
                    $akunModal->children = collect($akunModal->children);
                }

                $danaConfig = $mappingData['yayasan']['dana_config'] ?? null;

                if ($danaConfig) {
                    $danaTidakTerikatConfig = $danaConfig['dana_tidak_terikat'] ?? null;
                    $danaTerikatConfig = $danaConfig['dana_terikat'] ?? null;

                    // Gunakan translasi untuk nama dana
                    $danaTidakTerikatName = $danaTidakTerikatConfig['name'] ?? 'Dana Tidak Terikat';
                    $danaTidakTerikatRename = $this->translateAccountName(
                        $danaTidakTerikatConfig['rename'] ?? $danaTidakTerikatName,
                        'yayasan',
                        $mappingData
                    );

                    $danaTerikatName = $danaTerikatConfig['name'] ?? 'Dana Terikat';
                    $danaTerikatRename = $this->translateAccountName(
                        $danaTerikatConfig['rename'] ?? $danaTerikatName,
                        'yayasan',
                        $mappingData
                    );

                    $akunToTidakTerikat = $danaTidakTerikatConfig['akun_items'] ?? ['Modal Awal', 'Laba Ditahan', 'Laba Tahun Berjalan'];

                    $danaTidakTerikat = $akunModal->children->firstWhere('name', $danaTidakTerikatName);
                    if (!$danaTidakTerikat) {
                        $danaTidakTerikat = (object)[
                            'name' => $danaTidakTerikatName,
                            'rename' => $danaTidakTerikatRename,
                            'total' => 0,
                            'children' => collect()
                        ];
                        $akunModal->children->push($danaTidakTerikat);
                    }

                    $danaTerkait = $akunModal->children->firstWhere('name', $danaTerikatName);
                    if (!$danaTerkait) {
                        $danaTerkait = (object)[
                            'name' => $danaTerikatName,
                            'rename' => $danaTerikatRename,
                            'total' => 0,
                            'children' => collect()
                        ];
                        $akunModal->children->push($danaTerkait);
                    }

                    $originalChildren = $akunModal->children->whereNotIn('name', [$danaTidakTerikatName, $danaTerikatName])->values();

                    foreach ($originalChildren as $child) {
                        $index = $akunModal->children->search(function ($c) use ($child) {
                            return $c->name === $child->name;
                        });

                        if ($index !== false) {
                            $akunPindah = $akunModal->children->pull($index);

                            // Translate nama akun yang dipindahkan
                            $akunPindah->rename = $this->translateAccountName($akunPindah->name, 'yayasan', $mappingData);

                            if (in_array($akunPindah->name, $akunToTidakTerikat)) {
                                $danaTidakTerikat->children->push($akunPindah);
                            } else {
                                $danaTerkait->children->push($akunPindah);
                            }
                        }
                    }

                    // Recalculate totals if needed
                    // rekursifTotal([$danaTidakTerikat]);
                    // rekursifTotal([$danaTerkait]);
                }

                break;
            }
        }
    }

    public function getAkun()
    {
        $licence = Licence::first();
        $companyType = $licence ? $licence->company_type : null;

        $isKoperasi = $companyType === 'koperasi';
        $isYayasan = $companyType === 'yayasan';
        $isCV = $companyType === 'cv';
        $isFirma = $companyType === 'firma';
        $isPerorangan = $companyType === 'perorangan';

        // Get active language
        $lang = self::getActiveLanguage();
        $langCode = $lang->code ?? 'id';

        // Load mapping data based on language
        $mappingData = $this->loadAkunMapping($langCode);

        // Ambil semua data akun dengan relasi children rekursif
        $data = Akun::where('perent_id', null)
            ->with($this->generateChildrenWith(10))
            ->get();

        // Filter "Simpanan Wajib" jika bukan koperasi
        if (!$isKoperasi) {
            $this->hapusAkun($data, ['Simpanan Wajib']);
        }

        if (!$isCV && !$isFirma && !$isPerorangan) {
            $this->hapusAkun($data, ['Prive']);
        }

        // Proses khusus untuk yayasan
        if ($isYayasan) {
            $this->processYayasanDanaConfig($data, $mappingData);
        }

        // Ubah nama akun sesuai jenis perusahaan dengan multi-bahasa
        if ($companyType) {
            $this->tambahNamaAkunSesuaiTipe($data, $companyType, $mappingData);
        } else {
            // Fallback: apply general translation if no company type
            $this->tambahNamaAkunSesuaiTipe($data, 'general', $mappingData);
        }

        return response([
            'success' => true,
            'akun' => $data,
            'language' => $langCode,
            'company_type' => $companyType
        ], 200);
    }

    public function getAkunName(Request $request)
    {
        $data = Akun::whereRaw('LOWER(name) = ?', [strtolower($request->name)])->get();
        $response = [
            'success' => true,
            'akun' => $data,
        ];

        return response($response, 200);
    }

    public function setLabaDitahan(Request $request)
    {
        $request->validate([
            'total' => 'required',
        ]);
        $now = date('Y-m-d', time());
        $first = date('Y-1-1', time());
        $last = date('Y-12-31', time());
        $data = Cashtransaction::whereNotNull('transfer')->whereHas('from', function ($query) {
            $query->where('Laba Tahun Berjalan');
        })->whereHas('to', function ($query) {
            $query->where('Laba Ditahan');
        });
        $data = $data->whereBetween('date', [$first, $last]);
        $data = $data->get();
        if (empty($data) && date('Y-m-d', time())) {
        }
        $data = Akun::where('name', '=', 'Laba Ditahan')->first();
        $data = Akun::find($data->id);
        $data->total = $data->total + $request->total;
        $data->save();
        $response = [
            'success' => true,
            'akun' => $data,

        ];

        return response($response, 200);
    }

    public function getAkunList()
    {
        $licence = Licence::first();
        $companyType = $licence ? $licence->company_type : null;

        $lang = self::getActiveLanguage();
        $langCode = $lang->code ?? 'id';
        $mappingData = $this->loadAkunMapping($langCode);

        $data = Akun::all();

        if ($companyType) {
            $this->tambahNamaAkunSesuaiTipe($data, $companyType, $mappingData);
        } else {
            $this->tambahNamaAkunSesuaiTipe($data, 'general', $mappingData);
        }

        $response = [
            'success' => true,
            'akun'  => $data,
            'language' => $langCode,
            'company_type' => $companyType
        ];

        return response($response, 200);
    }

    public function Report(Request $request)
    {
        $data = Akun::where('name', $request->name)->with(str_repeat('children.', 10))->get();
        $response = [
            'success' => true,
            'akun'  => $data,
        ];

        return response($response, 200);
    }

    public function reportName(Request $request)
    {
        $licence = Licence::first();
        $companyType = $licence ? $licence->company_type : null;

        $isKoperasi = $companyType === 'koperasi';
        $isYayasan = $companyType === 'yayasan';

        $data = Akun::where('name', $request->name)->with(str_repeat('children.', 10))->get();

        // Filter "Simpanan Wajib" jika bukan koperasi
        if (!$isKoperasi) {
            $this->hapusAkun($data, ['Simpanan Wajib']);
        }

        if ($isYayasan) {
            foreach ($data as &$akunModal) {
                if ($akunModal->name === 'Modal') {
                    if (!($akunModal->children instanceof Collection)) {
                        $akunModal->children = collect($akunModal->children);
                    }

                    // Inisialisasi Dana Tidak Terikat
                    $danaTidakTerikat = $akunModal->children->firstWhere('name', 'Dana Tidak Terikat');
                    if (!$danaTidakTerikat) {
                        $danaTidakTerikat = (object)[
                            'name' => 'Dana Tidak Terikat',
                            'rename' => 'Dana Tidak Terikat',
                            'total' => 0,
                            'children' => collect()
                        ];
                        $akunModal->children->push($danaTidakTerikat);
                    }

                    // Inisialisasi Dana Terikat
                    $danaTerkait = $akunModal->children->firstWhere('name', 'Dana Terikat');
                    if (!$danaTerkait) {
                        $danaTerkait = (object)[
                            'name' => 'Dana Terikat',
                            'rename' => 'Dana Terikat',
                            'total' => 0,
                            'children' => collect()
                        ];
                        $akunModal->children->push($danaTerkait);
                    }

                    $akunToTidakTerikat = ['Modal Awal', 'Laba Ditahan', 'Laba Tahun Berjalan'];

                    // Duplikat daftar children agar bisa di-loop sambil di-pull
                    $originalChildren = $akunModal->children->whereNotIn('name', ['Dana Tidak Terikat', 'Dana Terikat'])->values();

                    foreach ($originalChildren as $child) {
                        $index = $akunModal->children->search(function ($c) use ($child) {
                            return $c->name === $child->name;
                        });

                        if ($index !== false) {
                            $akunPindah = $akunModal->children->pull($index);

                            if (in_array($akunPindah->name, $akunToTidakTerikat)) {
                                $danaTidakTerikat->children->push($akunPindah);
                            } else {
                                $danaTerkait->children->push($akunPindah);
                            }
                        }
                    }

                    break;
                }
            }
        }

        // Ubah nama akun sesuai jenis perusahaan
        if ($companyType) {
            $this->ubahNamaAkunSesuaiTipe($data, $companyType, []);
        }

        $response = [
            'success' => true,
            'akun'  => $data,
        ];

        return response($response, 200);
    }

    public function getAkunIsCashIn(Request $request)
    {
        $licence = Licence::first();
        $companyType = $licence ? $licence->company_type : null;

        $lang = self::getActiveLanguage();
        $langCode = $lang->code ?? 'id';
        $mappingData = $this->loadAkunMapping($langCode);

        $data = Akun::where('iscash', '<>', true)->where('iscashin', true)->get();

        if ($companyType) {
            $this->tambahNamaAkunSesuaiTipe($data, $companyType, $mappingData);
        } else {
            $this->tambahNamaAkunSesuaiTipe($data, 'general', $mappingData);
        }

        $response = [
            'success' => true,
            'akun'  => $data,
            'language' => $langCode,
            'company_type' => $companyType
        ];

        return response($response, 200);
    }

    public function getAkunIsCashOut()
    {
        $licence = Licence::first();
        $companyType = $licence ? $licence->company_type : null;

        $lang = self::getActiveLanguage();
        $langCode = $lang->code ?? 'id';
        $mappingData = $this->loadAkunMapping($langCode);

        $data = Akun::where('iscash', '<>', true)->where('iscashout', true)->get();

        if ($companyType) {
            $this->tambahNamaAkunSesuaiTipe($data, $companyType, $mappingData);
        } else {
            $this->tambahNamaAkunSesuaiTipe($data, 'general', $mappingData);
        }

        $response = [
            'success' => true,
            'akun'  => $data,
            'language' => $langCode,
            'company_type' => $companyType
        ];

        return response($response, 200);
    }

    public function getAkunIsCash()
    {
        $data = Akun::where('iscash', true)->get();

        $response = [
            'success' => true,
            'akun'  => $data,
        ];

        return response($response, 200);
    }

    public function getAkunNotCash()
    {
        $data = Akun::where('iscash', false)->orWhere('iscash', 0)->get();

        $response = [
            'success' => true,
            'akun'  => $data,
        ];

        return response($response, 200);
    }

    public function getAkunIsHeader()
    {
        $data = Akun::where('isheader', true)->orWhere('isheader', 1)->get();

        $response = [
            'success' => true,
            'akun'  => $data,
        ];

        return response($response, 200);
    }

    public function createAkun(Request $request)
    {
        $request->validate([
            'perent_id' => 'nullable',
            'name' => 'required',
            'isheader' => 'boolean',
            'iscash' => 'boolean',
            'iscashout' => 'boolean',
            'iscashin' => 'boolean',
        ]);
        $check = Akun::whereRaw('LOWER(name) = ?', [strtolower($request->name)])->first();
        if ($check) {
            $checkMenu = Akun::where('id', $check->perent_id)->first();

            $response = [
                'success' => false,
                'message'  => "Nama tersebut sudah dipakai di {$checkMenu->name}, silakan gunakan nama lainnya.",
            ];

            return response($response, 400);
        }
        $data = new Akun;
        $data->perent_id = $request->perent_id;
        $data->name = $request->name;
        $data->akun_desc = $request->akun_desc;
        $data->isheader = $request->isheader;
        $data->iscash = $request->iscash;
        $data->iscashout = $request->iscashout;
        $data->iscashin = $request->iscashin;

        $data->save();

        $response = [
            'success' => true,
            'akun'  => $data,
        ];

        return response($response, 200);
    }

    public function editAkun(Request $request)
    {
        $request->validate([
            'perent_id' => 'nullable',
            'name' => 'required',
            'isheader' => 'boolean',
            'iscash' => 'boolean',
            'iscashout' => 'boolean',
            'iscashin' => 'boolean',

        ]);

        $check = Akun::whereRaw('LOWER(name) = ?', [strtolower($request->name)])->first();
        if ($check) {
            $checkMenu = Akun::where('id', $check->perent_id)->first();

            $response = [
                'success' => false,
                'message'  => "Nama tersebut sudah dipakai di {$checkMenu->name}, silakan gunakan nama lainnya.",
            ];

            return response($response, 400);
        }

        $data = Akun::find($request->id);
        $data->perent_id = $request->perent_id;
        $data->name = $request->name;
        $data->akun_desc = $request->akun_desc;
        $data->isheader = $request->isheader;
        $data->iscash = $request->iscash;
        $data->iscashin = $request->iscashin;
        $data->iscashout = $request->iscashout;
        $data->save();

        $response = [
            'success' => true,
            'akun'  => $data,
        ];

        return response($response, 200);
    }

    public function deleteAkun(Request $request)
    {

        $data = Akun::find($request->id);

        $check = Subcashtransaction::where('akun_id', $request->id)->get();
        if (!$check->isEmpty()) {
            return response(['message' => $data->name . ' sudah pernah digunakan untuk transaksi.'], 400);
        }

        Akun::where('perent_id', '=', $data->id)->update(array('perent_id' => null));
        $data->delete();

        $response = [
            'success' => true,
            'akun'  => $data,
            'data'  => $check,
        ];

        return response($response, 200);
    }

    public function updateAkunTranslated(Request $request)
    {
        $request->validate([
            'akun_translated' => 'required',
        ]);

        $data = Akun::find($request->id);
        if (!$data) {
            return response()->json([
                'success' => false,
                'message' => 'Akun tidak ditemukan'
            ], 404);
        }

        $data->akun_translated = $request->akun_translated;
        $data->save();

        $response = [
            'success' => true,
            'akun'  => $data,
        ];

        return response($response, 200);
    }

    public function resetAkunTranslated(Request $request)
    {
        $data = Akun::find($request->id);
        if (!$data) {
            return response()->json([
                'success' => false,
                'message' => 'Akun tidak ditemukan'
            ], 404);
        }

        $data->akun_translated = null;
        $data->save();

        $response = [
            'success' => true,
            'akun'  => $data,
        ];

        return response($response, 200);
    }
}
