<?php

namespace App\Services;

/**
 * FaraidhCalculator — Kalkulator Waris Islam
 * 100% sinkron dengan Daftar Pembagian Waris KH. Turaichan Adjhuri Kudus
 */
class FaraidhCalculator
{
    // ============================================================
    // DAFTAR 29 AHLI WARIS (sesuai urutan tabel Turaichan baris 1-29)
    // ============================================================

    const AHLI_WARIS_LIST = [
        'anak_laki'                       => 'Anak Laki-laki',
        'cucu_laki'                       => 'Cucu Laki-laki (dari anak laki)',
        'ayah'                            => 'Ayah',
        'kakek'                           => 'Kakek (dari ayah)',
        'anak_perempuan'                  => 'Anak Perempuan (1 orang)',
        'anak_perempuan_lebih'            => '2+ Anak Perempuan',
        'cucu_perempuan'                  => 'Cucu Perempuan (1 orang)',
        'cucu_perempuan_lebih'            => '2+ Cucu Perempuan',
        'suami'                           => 'Suami',
        'ibu'                             => 'Ibu',
        'istri'                           => 'Istri',
        'nenek_dari_ibu'                  => 'Nenek (dari ibu)',
        'nenek_dari_ayah'                 => 'Nenek (dari ayah)',
        'saudara_laki_kandung'            => 'Saudara Laki-laki Kandung (1)',
        'saudara_laki_kandung_lebih'      => '2+ Saudara Laki-laki Kandung',
        'saudara_laki_seayah'             => 'Saudara Laki-laki Seayah (1)',
        'saudara_laki_seayah_lebih'       => '2+ Saudara Laki-laki Seayah',
        'saudara_perempuan_kandung'       => 'Saudara Perempuan Kandung (1)',
        'saudara_perempuan_kandung_lebih' => '2+ Saudara Perempuan Kandung',
        'saudara_perempuan_seayah'        => 'Saudara Perempuan Seayah (1)',
        'saudara_perempuan_seayah_lebih'  => '2+ Saudara Perempuan Seayah',
        'saudara_seibu'                   => 'Saudara Seibu (1 orang)',
        'saudara_seibu_lebih'             => '2+ Saudara Seibu',
        'keponakan_laki_kandung'          => 'Keponakan Laki (dari Sdr Kandung)',
        'keponakan_laki_seayah'           => 'Keponakan Laki (dari Sdr Seayah)',
        'paman_kandung'                   => 'Paman Kandung',
        'paman_seayah'                    => 'Paman Seayah',
        'anak_laki_paman_kandung'         => 'Anak Laki Paman Kandung',
        'anak_laki_paman_seayah'          => 'Anak Laki Paman Seayah',
    ];

    // ============================================================
    // METODE UTAMA
    // ============================================================

    public function hitung(array $ahliWaris, int $hartaTotal): array
    {
        // 1. Filter aktif (jumlah > 0)
        $aktif = array_filter($ahliWaris, fn($j) => (int)$j > 0);

        // 2. Tentukan mahjub
        $mahjub = $this->tentukanMahjub($aktif);

        // 3. Buang yang mahjub
        $aktif = array_filter($aktif, fn($k) => !in_array($k, $mahjub), ARRAY_FILTER_USE_KEY);

        // 4. Buat konteks kehadiran
        $ctx = $this->buatKonteks($aktif);

        // 5. Tentukan bagian masing-masing
        $bagianList = $this->tentukanBagian($aktif, $ctx);

        // 6. Hitung total unit ashabah
        $totalUnitAshabah = $this->hitungTotalUnitAshabah($bagianList, $aktif);

        // 7. Asal Masalah
        $am = $this->hitungAsalMasalah($bagianList, $totalUnitAshabah);

        // 8. Saham
        $sahamList = $this->hitungSaham($bagianList, $aktif, $am, $totalUnitAshabah);

        // 9. Cek kondisi
        $totalSaham = array_sum(array_column($sahamList, 'saham'));
        $kondisi    = $this->cekKondisi($totalSaham, $am, $bagianList);

        // 10. Aul — AM = total saham
        if ($kondisi === 'aul') {
            $am = $totalSaham;
        }

        // 11. Radd
        if ($kondisi === 'radd') {
            $sahamList  = $this->prosesRadd($sahamList, $am);
            $totalSaham = array_sum(array_column($sahamList, 'saham'));
            $am         = $totalSaham;
        }

        // 12. Nominal
        $hasil = $this->hitungNominal($sahamList, $aktif, $am, $hartaTotal);

        // 13. Langkah penjelasan
        $langkah = $this->susunLangkah($aktif, $bagianList, $am, $sahamList, $kondisi, $mahjub, $ctx);

        return [
            'success'      => true,
            'harta_total'  => $hartaTotal,
            'asal_masalah' => $am,
            'kondisi'      => $kondisi,
            'mahjub'       => $mahjub,
            'pembagian'    => $hasil,
            'langkah'      => $langkah,
        ];
    }

    // ============================================================
    // TENTUKAN MAHJUB
    // ============================================================

    private function tentukanMahjub(array $aktif): array
    {
        $mahjub = [];
        $keys   = array_keys($aktif);
        $ada    = fn($k) => in_array($k, $keys);

        $adaAnakLaki = $ada('anak_laki');
        $adaAnakPr   = $ada('anak_perempuan') || $ada('anak_perempuan_lebih');
        $adaAnak     = $adaAnakLaki || $adaAnakPr;
        $adaCucuLaki = $ada('cucu_laki');
        $adaAnakCucu = $adaAnak || $adaCucuLaki
                    || $ada('cucu_perempuan') || $ada('cucu_perempuan_lebih');
        $adaAyah     = $ada('ayah');

        // ── Cucu Laki: dimahjub anak laki ──
        if ($adaAnakLaki && $ada('cucu_laki')) {
            $mahjub[] = 'cucu_laki';
        }

        // ── Cucu Perempuan ──
        if ($adaAnakLaki) {
            if (!$adaCucuLaki) {
                if ($ada('cucu_perempuan'))       $mahjub[] = 'cucu_perempuan';
                if ($ada('cucu_perempuan_lebih')) $mahjub[] = 'cucu_perempuan_lebih';
            }
        } elseif ($ada('anak_perempuan_lebih') && !$adaCucuLaki) {
            if ($ada('cucu_perempuan'))       $mahjub[] = 'cucu_perempuan';
            if ($ada('cucu_perempuan_lebih')) $mahjub[] = 'cucu_perempuan_lebih';
        }

        // ── Kakek: dimahjub ayah ──
        if ($adaAyah && $ada('kakek')) {
            $mahjub[] = 'kakek';
        }

        // ── Nenek dari ayah: dimahjub ayah ──
        if ($adaAyah && $ada('nenek_dari_ayah')) {
            $mahjub[] = 'nenek_dari_ayah';
        }

        // ── Nenek dari ibu: dimahjub ibu ──
        if ($ada('ibu') && $ada('nenek_dari_ibu')) {
            $mahjub[] = 'nenek_dari_ibu';
        }

        // ── Semua saudara (kandung/seayah): dimahjub furuu' atau ayah ──
        $adaFuruu = $adaAnak || $adaCucuLaki
                 || $ada('cucu_perempuan') || $ada('cucu_perempuan_lebih');

        if ($adaFuruu || $adaAyah) {
            foreach ([
                'saudara_laki_kandung', 'saudara_laki_kandung_lebih',
                'saudara_laki_seayah',  'saudara_laki_seayah_lebih',
                'saudara_perempuan_kandung', 'saudara_perempuan_kandung_lebih',
                'saudara_perempuan_seayah',  'saudara_perempuan_seayah_lebih',
            ] as $s) {
                if ($ada($s)) $mahjub[] = $s;
            }
        }

        // ── FIX #5: Saudara seibu dimahjub furuu' DAN ayah ──
        // Sesuai tabel Turaichan baris 22-23:
        // kolom 3 (Ayah) → 0 (mahjub), kolom 1,2,5,6,7,8 → 0 (mahjub)
        if ($adaFuruu || $adaAyah) {
            if ($ada('saudara_seibu'))       $mahjub[] = 'saudara_seibu';
            if ($ada('saudara_seibu_lebih')) $mahjub[] = 'saudara_seibu_lebih';
        }

        // ── Saudara seayah: dimahjub saudara laki kandung ──
        if ($ada('saudara_laki_kandung') || $ada('saudara_laki_kandung_lebih')) {
            foreach ([
                'saudara_laki_seayah',      'saudara_laki_seayah_lebih',
                'saudara_perempuan_seayah', 'saudara_perempuan_seayah_lebih',
            ] as $s) {
                if ($ada($s)) $mahjub[] = $s;
            }
        }

        // ── FIX #4: Saudara perempuan seayah dimahjub 2+ saudara perempuan kandung ──
        if (
            $ada('saudara_perempuan_kandung_lebih') &&
            !$ada('saudara_laki_kandung') &&
            !$ada('saudara_laki_kandung_lebih')
        ) {
            foreach ([
                'saudara_perempuan_seayah',
                'saudara_perempuan_seayah_lebih',
                'saudara_laki_seayah',
                'saudara_laki_seayah_lebih',
            ] as $s) {
                if ($ada($s)) $mahjub[] = $s;
            }
        }

        // ── Keponakan: dimahjub furuu', ayah, kakek, sdr laki ──
        $penghalangKeponakan = $adaFuruu || $adaAyah || $ada('kakek')
            || $ada('saudara_laki_kandung') || $ada('saudara_laki_kandung_lebih')
            || $ada('saudara_laki_seayah')  || $ada('saudara_laki_seayah_lebih');
        if ($penghalangKeponakan) {
            if ($ada('keponakan_laki_kandung')) $mahjub[] = 'keponakan_laki_kandung';
            if ($ada('keponakan_laki_seayah'))  $mahjub[] = 'keponakan_laki_seayah';
        }

        // ── Paman & Anak Paman ──
        $penghalangPaman = $adaFuruu || $adaAyah || $ada('kakek')
            || $ada('saudara_laki_kandung') || $ada('saudara_laki_kandung_lebih')
            || $ada('keponakan_laki_kandung') || $ada('keponakan_laki_seayah');
        if ($penghalangPaman) {
            foreach ([
                'paman_kandung', 'paman_seayah',
                'anak_laki_paman_kandung', 'anak_laki_paman_seayah',
            ] as $s) {
                if ($ada($s)) $mahjub[] = $s;
            }
        }

        // Paman seayah dimahjub paman kandung
        if ($ada('paman_kandung')) {
            if ($ada('paman_seayah'))           $mahjub[] = 'paman_seayah';
            if ($ada('anak_laki_paman_seayah')) $mahjub[] = 'anak_laki_paman_seayah';
        }

        return array_values(array_unique($mahjub));
    }

    // ============================================================
    // KONTEKS KEHADIRAN AHLI WARIS
    // ============================================================

    private function buatKonteks(array $aktif): array
    {
        $keys = array_keys($aktif);
        $ada  = fn($k) => in_array($k, $keys);

        $adaAnakLaki       = $ada('anak_laki');
        $adaAnakPr         = $ada('anak_perempuan') || $ada('anak_perempuan_lebih');
        $adaAnak           = $adaAnakLaki || $adaAnakPr;
        $adaCucuLaki       = $ada('cucu_laki');
        $adaCucuPr         = $ada('cucu_perempuan') || $ada('cucu_perempuan_lebih');
        $adaCucu           = $adaCucuLaki || $adaCucuPr;
        $adaAnakCucu       = $adaAnak || $adaCucu;
        $adaSdrLakiKandung = $ada('saudara_laki_kandung') || $ada('saudara_laki_kandung_lebih');
        $adaSdrLakiSeayah  = $ada('saudara_laki_seayah')  || $ada('saudara_laki_seayah_lebih');
        $adaSdrPrKandung   = $ada('saudara_perempuan_kandung') || $ada('saudara_perempuan_kandung_lebih');
        $adaSdrPrSeayah    = $ada('saudara_perempuan_seayah')  || $ada('saudara_perempuan_seayah_lebih');
        $adaSdr2Plus       = $ada('saudara_laki_kandung_lebih')
                           || $ada('saudara_laki_seayah_lebih')
                           || $ada('saudara_perempuan_kandung_lebih')
                           || $ada('saudara_seibu_lebih');

        $adaSuamiIstri = $ada('suami') || $ada('istri');
        $adaAyah       = $ada('ayah');
        $adaIbu        = $ada('ibu');
        $adaSaudara    = $adaSdrLakiKandung || $adaSdrLakiSeayah
                       || $adaSdrPrKandung  || $adaSdrPrSeayah
                       || $ada('saudara_seibu') || $ada('saudara_seibu_lebih');

        // Umariyatain: tepat 3 ahli waris = suami/istri + ayah + ibu
        $isUmariyatain = $adaIbu && $adaAyah && $adaSuamiIstri
                      && !$adaAnakCucu && !$adaSaudara
                      && count($keys) === 3;

        return compact(
            'adaAnakLaki', 'adaAnakPr', 'adaAnak',
            'adaCucuLaki', 'adaCucuPr', 'adaCucu',
            'adaAnakCucu',
            'adaSdrLakiKandung', 'adaSdrLakiSeayah',
            'adaSdrPrKandung',   'adaSdrPrSeayah',
            'adaSdr2Plus',
            'isUmariyatain',
            'adaAyah', 'adaIbu', 'adaSuamiIstri'
        );
    }

    // ============================================================
    // TENTUKAN BAGIAN MASING-MASING AHLI WARIS
    // ============================================================

    private function tentukanBagian(array $aktif, array $ctx): array
    {
        $bagian = [];
        foreach (array_keys($aktif) as $key) {
            $bagian[$key] = $this->bagianSatu($key, $ctx);
        }
        return $bagian;
    }

    private function bagianSatu(string $key, array $ctx): array
    {
        $adaAnakLaki       = $ctx['adaAnakLaki'];
        $adaAnakPr         = $ctx['adaAnakPr'];
        $adaAnakCucu       = $ctx['adaAnakCucu'];
        $adaCucuLaki       = $ctx['adaCucuLaki'];
        $adaCucuPr         = $ctx['adaCucuPr'];
        $adaSdrLakiKandung = $ctx['adaSdrLakiKandung'];
        $adaSdrLakiSeayah  = $ctx['adaSdrLakiSeayah'];
        $adaSdrPrKandung   = $ctx['adaSdrPrKandung'];
        $adaSdrPrSeayah    = $ctx['adaSdrPrSeayah'];
        $adaSdr2Plus       = $ctx['adaSdr2Plus'];
        $isUmariyatain     = $ctx['isUmariyatain'];

        $ayahFurudhAshabah  = $adaAnakCucu && !$adaAnakLaki && !$adaCucuLaki;
        $kakekFurudhAshabah = $adaAnakCucu && !$adaAnakLaki && !$adaCucuLaki;

        return match(true) {

            $key === 'suami' => [
                'pembilang' => 1,
                'penyebut'  => $adaAnakCucu ? 4 : 2,
                'label'     => $adaAnakCucu ? '1/4' : '1/2',
                'tipe'      => 'furudh',
            ],

            $key === 'istri' => [
                'pembilang' => 1,
                'penyebut'  => $adaAnakCucu ? 8 : 4,
                'label'     => $adaAnakCucu ? '1/8' : '1/4',
                'tipe'      => 'furudh',
            ],

            $key === 'anak_laki' => [
                'pembilang' => 0, 'penyebut' => 0,
                'label'     => $adaAnakPr ? 'Ashabah (2:1 dengan anak perempuan)' : 'Ashabah binafsihi',
                'tipe'      => 'ashabah',
            ],

            $key === 'anak_perempuan' => $adaAnakLaki
                ? ['pembilang' => 0, 'penyebut' => 0, 'label' => 'Ashabah bilghairi (2:1 dengan anak laki)', 'tipe' => 'ashabah']
                : ['pembilang' => 1, 'penyebut' => 2, 'label' => '1/2', 'tipe' => 'furudh'],

            $key === 'anak_perempuan_lebih' => $adaAnakLaki
                ? ['pembilang' => 0, 'penyebut' => 0, 'label' => 'Ashabah bilghairi (2:1 dengan anak laki)', 'tipe' => 'ashabah']
                : ['pembilang' => 2, 'penyebut' => 3, 'label' => '2/3', 'tipe' => 'furudh'],

            $key === 'cucu_laki' => [
                'pembilang' => 0, 'penyebut' => 0,
                'label'     => $adaCucuPr ? 'Ashabah (2:1 dengan cucu perempuan)' : 'Ashabah binafsihi',
                'tipe'      => 'ashabah',
            ],

            $key === 'cucu_perempuan' => $adaCucuLaki
                ? ['pembilang' => 0, 'penyebut' => 0, 'label' => 'Ashabah bilghairi (2:1 dengan cucu laki)', 'tipe' => 'ashabah']
                : ($adaAnakPr
                    ? ['pembilang' => 1, 'penyebut' => 6, 'label' => '1/6 (takmilah 2/3)', 'tipe' => 'furudh']
                    : ['pembilang' => 1, 'penyebut' => 2, 'label' => '1/2', 'tipe' => 'furudh']),

            $key === 'cucu_perempuan_lebih' => $adaCucuLaki
                ? ['pembilang' => 0, 'penyebut' => 0, 'label' => 'Ashabah bilghairi (2:1 dengan cucu laki)', 'tipe' => 'ashabah']
                : ['pembilang' => 2, 'penyebut' => 3, 'label' => '2/3', 'tipe' => 'furudh'],

            $key === 'ayah' => !$adaAnakCucu
                ? ['pembilang' => 0, 'penyebut' => 0, 'label' => 'Ashabah binafsihi', 'tipe' => 'ashabah']
                : ($ayahFurudhAshabah
                    ? ['pembilang' => 1, 'penyebut' => 6, 'label' => '1/6 + sisa (ashabah)', 'tipe' => 'furudh_ashabah']
                    : ['pembilang' => 1, 'penyebut' => 6, 'label' => '1/6', 'tipe' => 'furudh']),

            $key === 'kakek' => !$adaAnakCucu
                ? ['pembilang' => 0, 'penyebut' => 0, 'label' => 'Ashabah binafsihi', 'tipe' => 'ashabah']
                : ($kakekFurudhAshabah
                    ? ['pembilang' => 1, 'penyebut' => 6, 'label' => '1/6 + sisa (ashabah)', 'tipe' => 'furudh_ashabah']
                    : ['pembilang' => 1, 'penyebut' => 6, 'label' => '1/6', 'tipe' => 'furudh']),

            $key === 'ibu' => ($adaAnakCucu || $adaSdr2Plus)
                ? ['pembilang' => 1, 'penyebut' => 6, 'label' => '1/6', 'tipe' => 'furudh']
                : ($isUmariyatain
                    ? ['pembilang' => 0, 'penyebut' => 0, 'label' => '1/3 dari sisa (Umariyatain)', 'tipe' => 'umariyatain']
                    : ['pembilang' => 1, 'penyebut' => 3, 'label' => '1/3', 'tipe' => 'furudh']),

            $key === 'nenek_dari_ibu',
            $key === 'nenek_dari_ayah' => [
                'pembilang' => 1, 'penyebut' => 6, 'label' => '1/6', 'tipe' => 'furudh',
            ],

            $key === 'saudara_laki_kandung',
            $key === 'saudara_laki_kandung_lebih' => [
                'pembilang' => 0, 'penyebut' => 0,
                'label'     => $adaSdrPrKandung ? 'Ashabah (2:1 dengan sdr pr kandung)' : 'Ashabah binafsihi',
                'tipe'      => 'ashabah',
            ],

            $key === 'saudara_perempuan_kandung' => $adaSdrLakiKandung
                ? ['pembilang' => 0, 'penyebut' => 0, 'label' => 'Ashabah bilghairi (2:1 dengan sdr laki kandung)', 'tipe' => 'ashabah']
                : ($adaAnakPr
                    ? ['pembilang' => 0, 'penyebut' => 0, 'label' => 'Ashabah maa al-ghair (bersama anak perempuan)', 'tipe' => 'ashabah']
                    : ['pembilang' => 1, 'penyebut' => 2, 'label' => '1/2', 'tipe' => 'furudh']),

            $key === 'saudara_perempuan_kandung_lebih' => $adaSdrLakiKandung
                ? ['pembilang' => 0, 'penyebut' => 0, 'label' => 'Ashabah bilghairi (2:1 dengan sdr laki kandung)', 'tipe' => 'ashabah']
                : ($adaAnakPr
                    ? ['pembilang' => 0, 'penyebut' => 0, 'label' => 'Ashabah maa al-ghair (bersama anak perempuan)', 'tipe' => 'ashabah']
                    : ['pembilang' => 2, 'penyebut' => 3, 'label' => '2/3', 'tipe' => 'furudh']),

            $key === 'saudara_laki_seayah',
            $key === 'saudara_laki_seayah_lebih' => [
                'pembilang' => 0, 'penyebut' => 0,
                'label'     => $adaSdrPrSeayah ? 'Ashabah (2:1 dengan sdr pr seayah)' : 'Ashabah binafsihi',
                'tipe'      => 'ashabah',
            ],

            $key === 'saudara_perempuan_seayah' => $adaSdrLakiSeayah
                ? ['pembilang' => 0, 'penyebut' => 0, 'label' => 'Ashabah bilghairi (2:1 dengan sdr laki seayah)', 'tipe' => 'ashabah']
                : ($adaAnakPr
                    ? ['pembilang' => 0, 'penyebut' => 0, 'label' => 'Ashabah maa al-ghair (bersama anak perempuan)', 'tipe' => 'ashabah']
                    : ['pembilang' => 1, 'penyebut' => 2, 'label' => '1/2', 'tipe' => 'furudh']),

            $key === 'saudara_perempuan_seayah_lebih' => $adaSdrLakiSeayah
                ? ['pembilang' => 0, 'penyebut' => 0, 'label' => 'Ashabah bilghairi (2:1 dengan sdr laki seayah)', 'tipe' => 'ashabah']
                : ($adaAnakPr
                    ? ['pembilang' => 0, 'penyebut' => 0, 'label' => 'Ashabah maa al-ghair (bersama anak perempuan)', 'tipe' => 'ashabah']
                    : ['pembilang' => 2, 'penyebut' => 3, 'label' => '2/3', 'tipe' => 'furudh']),

            $key === 'saudara_seibu' => [
                'pembilang' => 1, 'penyebut' => 6, 'label' => '1/6', 'tipe' => 'furudh',
            ],

            $key === 'saudara_seibu_lebih' => [
                'pembilang' => 1, 'penyebut' => 3, 'label' => '1/3 (dibagi rata)', 'tipe' => 'furudh',
            ],

            default => [
                'pembilang' => 0, 'penyebut' => 0, 'label' => 'Ashabah binafsihi', 'tipe' => 'ashabah',
            ],
        };
    }

    // ============================================================
    // HITUNG TOTAL UNIT ASHABAH
    // ============================================================

    private function hitungTotalUnitAshabah(array $bagianList, array $aktif): int
    {
        $total = 0;
        foreach ($bagianList as $key => $b) {
            if (!in_array($b['tipe'], ['ashabah', 'furudh_ashabah'])) continue;
            $jumlah = (int)($aktif[$key] ?? 1);
            $total += $jumlah * $this->bobotAshabah($key);
        }
        return $total;
    }

    // ============================================================
    // ASAL MASALAH
    // ============================================================

    private function hitungAsalMasalah(array $bagianList, int $totalUnitAshabah): int
    {
        $penyebutList = [];
        foreach ($bagianList as $b) {
            if (in_array($b['tipe'], ['furudh', 'furudh_ashabah']) && $b['penyebut'] > 1) {
                $penyebutList[] = $b['penyebut'];
            }
        }

        if (empty($penyebutList)) {
            return max(1, $totalUnitAshabah);
        }

        $kpk = $penyebutList[0];
        for ($i = 1; $i < count($penyebutList); $i++) {
            $kpk = $this->kpk($kpk, $penyebutList[$i]);
        }
        return $kpk;
    }

    // ============================================================
    // HITUNG SAHAM
    // ============================================================

    private function hitungSaham(
        array $bagianList,
        array $aktif,
        int   $am,
        int   $totalUnitAshabah
    ): array {
        $sahamList   = [];
        $totalFurudh = 0;

        // A: Furudh murni
        foreach ($bagianList as $key => $b) {
            if ($b['tipe'] !== 'furudh') continue;
            $saham = intval(($b['pembilang'] / $b['penyebut']) * $am);
            $sahamList[$key] = [
                'key'    => $key,
                'nama'   => self::AHLI_WARIS_LIST[$key] ?? $key,
                'bagian' => $b['label'],
                'tipe'   => 'furudh',
                'saham'  => $saham,
            ];
            $totalFurudh += $saham;
        }

        // B: Furudh + Ashabah (Ayah/Kakek dengan hanya anak/cucu perempuan)
        foreach ($bagianList as $key => $b) {
            if ($b['tipe'] !== 'furudh_ashabah') continue;
            $sahamFurudh = intval(($b['pembilang'] / $b['penyebut']) * $am);
            $sahamList[$key] = [
                'key'          => $key,
                'nama'         => self::AHLI_WARIS_LIST[$key] ?? $key,
                'bagian'       => $b['label'],
                'tipe'         => 'furudh_ashabah',
                'saham'        => $sahamFurudh,
                'saham_furudh' => $sahamFurudh,
            ];
            $totalFurudh += $sahamFurudh;
        }

        // C: Sisa untuk ashabah
        $sisa = max(0, $am - $totalFurudh);

        // D: Distribusi sisa ke ashabah
        foreach ($bagianList as $key => $b) {
            if (!in_array($b['tipe'], ['ashabah', 'furudh_ashabah'])) continue;
            $jumlah       = (int)($aktif[$key] ?? 1);
            $unitKelompok = $jumlah * $this->bobotAshabah($key);
            $sahamAshabah = $totalUnitAshabah > 0
                ? intval(round(($unitKelompok / $totalUnitAshabah) * $sisa))
                : 0;

            if ($b['tipe'] === 'furudh_ashabah') {
                $sahamList[$key]['saham'] = $sahamList[$key]['saham_furudh'] + $sahamAshabah;
            } else {
                $sahamList[$key] = [
                    'key'    => $key,
                    'nama'   => self::AHLI_WARIS_LIST[$key] ?? $key,
                    'bagian' => $b['label'],
                    'tipe'   => 'ashabah',
                    'saham'  => $sahamAshabah,
                ];
            }
        }

        // E: Umariyatain — Ibu mendapat 1/3 dari sisa setelah suami/istri
        foreach ($bagianList as $key => $b) {
            if ($b['tipe'] !== 'umariyatain') continue;

            $sahamSuamiIstri = 0;
            foreach ($sahamList as $k => $s) {
                if (in_array($k, ['suami', 'istri'])) {
                    $sahamSuamiIstri += $s['saham'];
                }
            }
            $sisaSetelahSuamiIstri = $am - $sahamSuamiIstri;
            $sahamIbu = intval(round($sisaSetelahSuamiIstri / 3));

            $sahamList[$key] = [
                'key'    => $key,
                'nama'   => self::AHLI_WARIS_LIST[$key] ?? $key,
                'bagian' => $b['label'],
                'tipe'   => 'umariyatain',
                'saham'  => $sahamIbu,
            ];

            if (isset($sahamList['ayah'])) {
                $totalFurudhDanIbu = $sahamSuamiIstri + $sahamIbu;
                $sahamList['ayah']['saham'] = max(0, $am - $totalFurudhDanIbu);
            }
        }

        return $sahamList;
    }

    // ============================================================
    // BOBOT ASHABAH
    // ============================================================

    private function bobotAshabah(string $key): int
    {
        $laki = [
            'anak_laki', 'cucu_laki', 'ayah', 'kakek',
            'saudara_laki_kandung', 'saudara_laki_kandung_lebih',
            'saudara_laki_seayah',  'saudara_laki_seayah_lebih',
            'keponakan_laki_kandung', 'keponakan_laki_seayah',
            'paman_kandung', 'paman_seayah',
            'anak_laki_paman_kandung', 'anak_laki_paman_seayah',
        ];
        return in_array($key, $laki) ? 2 : 1;
    }

    // ============================================================
    // CEK KONDISI
    // ============================================================

    private function cekKondisi(int $totalSaham, int $am, array $bagianList): string
    {
        $adaAshabah = false;
        foreach ($bagianList as $b) {
            if (in_array($b['tipe'], ['ashabah', 'furudh_ashabah', 'umariyatain'])) {
                $adaAshabah = true;
                break;
            }
        }
        if ($totalSaham > $am) return 'aul';
        if ($totalSaham < $am && !$adaAshabah) return 'radd';
        return 'normal';
    }

    // ============================================================
    // RADD
    // ============================================================

    private function prosesRadd(array $sahamList, int $am): array
    {
        $totalSkrg = array_sum(array_column($sahamList, 'saham'));
        $sisa      = $am - $totalSkrg;
        if ($sisa <= 0) return $sahamList;

        $tidakRadd      = ['suami', 'istri'];
        $totalSahamRadd = 0;
        foreach ($sahamList as $key => $item) {
            if (!in_array($key, $tidakRadd)) {
                $totalSahamRadd += $item['saham'];
            }
        }
        if ($totalSahamRadd <= 0) return $sahamList;

        foreach ($sahamList as $key => $item) {
            if (in_array($key, $tidakRadd)) continue;
            $tambahan = intval(round(($item['saham'] / $totalSahamRadd) * $sisa));
            $sahamList[$key]['saham']  += $tambahan;
            $sahamList[$key]['bagian'] .= ' + Radd';
        }

        return $sahamList;
    }

    // ============================================================
    // HITUNG NOMINAL
    // ============================================================

    private function hitungNominal(
        array $sahamList,
        array $aktif,
        int   $am,
        int   $hartaTotal
    ): array {
        $hasil = [];
        foreach ($sahamList as $key => $item) {
            $jumlahOrang     = (int)($aktif[$key] ?? 1);
            $nominalTotal    = $am > 0 ? intval(($item['saham'] / $am) * $hartaTotal) : 0;
            $nominalPerOrang = $jumlahOrang > 1 ? intval($nominalTotal / $jumlahOrang) : $nominalTotal;
            $persentase      = $am > 0 ? round(($item['saham'] / $am) * 100, 2) : 0;

            $entry = [
                'key'            => $key,
                'nama'           => $item['nama'],
                'bagian'         => $item['bagian'],
                'tipe'           => $item['tipe'],
                'saham'          => $item['saham'],
                'jumlah_orang'   => $jumlahOrang,
                'nominal'        => $nominalTotal,
                'nominal_format' => 'Rp ' . number_format($nominalTotal, 0, ',', '.'),
                'persentase'     => $persentase,
            ];

            if ($jumlahOrang > 1) {
                $entry['nominal_per_orang']        = $nominalPerOrang;
                $entry['nominal_per_orang_format'] = 'Rp ' . number_format($nominalPerOrang, 0, ',', '.');
            }

            $hasil[] = $entry;
        }
        return $hasil;
    }

    // ============================================================
    // SUSUN LANGKAH PENJELASAN
    // ============================================================

    private function susunLangkah(
        array  $aktif,
        array  $bagianList,
        int    $am,
        array  $sahamList,
        string $kondisi,
        array  $mahjub,
        array  $ctx
    ): array {
        $langkah = [];
        $nomor   = 1;

        $namaAktif = array_map(fn($k) => self::AHLI_WARIS_LIST[$k] ?? $k, array_keys($aktif));
        $langkah[] = [
            'nomor' => $nomor++,
            'judul' => 'Identifikasi Ahli Waris',
            'isi'   => 'Ahli waris yang ada: ' . implode(', ', $namaAktif) . '.',
        ];

        if (empty($mahjub)) {
            $langkah[] = ['nomor' => $nomor++, 'judul' => 'Penentuan Mahjub', 'isi' => 'Tidak ada ahli waris yang terhalang (mahjub).'];
        } else {
            $namaMahjub = array_map(fn($k) => self::AHLI_WARIS_LIST[$k] ?? $k, $mahjub);
            $langkah[]  = ['nomor' => $nomor++, 'judul' => 'Penentuan Mahjub (Terhalang)', 'isi' => implode(', ', $namaMahjub) . ' terhalang dan tidak mendapat warisan.'];
        }

        if ($ctx['isUmariyatain']) {
            $langkah[] = [
                'nomor' => $nomor++,
                'judul' => 'Kasus Umariyatain (Gharawain)',
                'isi'   => 'Berlaku kasus Umariyatain: ahli waris hanya Suami/Istri + Ayah + Ibu. Ibu mendapat 1/3 dari sisa setelah bagian Suami/Istri dikeluarkan — bukan 1/3 dari total harta. (Berdasarkan ijtihad Khalifah Umar bin Khattab RA yang disepakati Usman RA).',
            ];
        }

        $rincian = [];
        foreach ($bagianList as $k => $b) {
            $rincian[] = (self::AHLI_WARIS_LIST[$k] ?? $k) . ': ' . $b['label'];
        }
        $langkah[] = ['nomor' => $nomor++, 'judul' => 'Penentuan Bagian (Furudul Muqaddarah)', 'isi' => implode('. ', $rincian) . '.'];

        $langkah[] = ['nomor' => $nomor++, 'judul' => 'Penentuan Asal Masalah', 'isi' => 'Asal Masalah = ' . $am . ' (KPK dari semua penyebut furudh).'];

        $kondisiText = match($kondisi) {
            'aul'   => 'Terjadi AUL: jumlah saham melebihi Asal Masalah. AM dinaikkan menjadi ' . $am . '.',
            'radd'  => 'Terjadi RADD: jumlah saham kurang dari AM dan tidak ada ashabah. Sisa dikembalikan ke ahli waris furudh (kecuali suami/istri).',
            default => 'Kondisi NORMAL: jumlah saham sama dengan Asal Masalah.',
        };
        $langkah[] = ['nomor' => $nomor++, 'judul' => 'Cek Kondisi (Normal / Aul / Radd)', 'isi' => $kondisiText];

        $tabel = [];
        foreach ($sahamList as $item) {
            $tabel[] = ['nama' => $item['nama'], 'bagian' => $item['bagian'], 'saham' => $item['saham']];
        }
        $langkah[] = ['nomor' => $nomor++, 'judul' => 'Tabel Saham', 'isi' => 'Rincian saham masing-masing dari AM = ' . $am . '.', 'tabel' => $tabel];

        $adaCampur = ($ctx['adaAnakLaki']      && $ctx['adaAnakPr'])
                  || ($ctx['adaCucuLaki']       && $ctx['adaCucuPr'])
                  || ($ctx['adaSdrLakiKandung'] && $ctx['adaSdrPrKandung'])
                  || ($ctx['adaSdrLakiSeayah']  && $ctx['adaSdrPrSeayah']);
        if ($adaCampur) {
            $langkah[] = ['nomor' => $nomor++, 'judul' => 'Kaidah Ashabah 2:1', 'isi' => 'Berlaku kaidah لِلذَّكَرِ مِثْلُ حَظِّ الْأُنثَيَيْنِ — bagian laki-laki = 2× bagian perempuan (QS. An-Nisa: 11).'];
        }

        $langkah[] = ['nomor' => $nomor, 'judul' => 'Perhitungan Nominal', 'isi' => 'Nominal = (Saham ÷ ' . $am . ') × Total Harta Warisan.'];

        return $langkah;
    }

    // ============================================================
    // HELPERS
    // ============================================================

    private function kpk(int $a, int $b): int
    {
        return intval(abs($a * $b) / $this->fpb($a, $b));
    }

    private function fpb(int $a, int $b): int
    {
        while ($b !== 0) [$a, $b] = [$b, $a % $b];
        return $a;
    }

    public function getDaftarAhliWaris(): array
    {
        return array_map(
            fn($key, $nama) => ['key' => $key, 'nama' => $nama],
            array_keys(self::AHLI_WARIS_LIST),
            self::AHLI_WARIS_LIST
        );
    }
}
