<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;

class GeneralLedgerController extends Controller
{
    protected $role_id;

    protected string $module = 'Reports Management';

    public function __construct()
    {
        $module = $this->module;

        $this->middleware("permission:$module General Ledger")->only(['index','print']);
    }
    public function index(Request $request)
    {
        $supplierList   = $this->getSupplierList();
        $ledgerData     = null;
        $totalDebit     = 0;
        $totalCredit    = 0;
        $selectedKhata  = $request->input('khata');
        $fromDate       = $request->input('from_date');
        $toDate         = $request->input('to_date');

        if ($request->filled('khata')) {
            $result      = $this->getLedgerRows($selectedKhata, $fromDate, $toDate);
            $ledgerData  = $result['rows'];
            $totalDebit  = $result['totalDebit'];
            $totalCredit = $result['totalCredit'];
        }

        return view('reports.general_ledger', compact(
            'supplierList',
            'ledgerData',
            'totalDebit',
            'totalCredit',
            'selectedKhata',
            'fromDate',
            'toDate'
        ));
    }

    public function print(Request $request)
    {
        $selectedKhata = $request->input('khata');
        $fromDate      = $request->input('from_date');
        $toDate        = $request->input('to_date');

        $result        = $this->getLedgerRows($selectedKhata, $fromDate, $toDate);

        $ledgerData    = $result['rows'];
        $totalDebit    = $result['totalDebit'];
        $totalCredit   = $result['totalCredit'];
        $supplierName  = $this->getSupplierName($selectedKhata);

        return view('reports.general_ledger_print_view', compact(
            'ledgerData',
            'totalDebit',
            'totalCredit',
            'selectedKhata',
            'supplierName',
            'fromDate',
            'toDate'
        ));
    }

    // ── Core ─────────────────────────────────────────────────────────────────

   private function getLedgerRows(string $supplierId, ?string $fromDate, ?string $toDate): array
    {
        $query = DB::table('vouchers')
            ->whereNotNull('adaegi_array');
            // ->where('status', '!=', '0');

        if ($fromDate) $query->whereDate('voucher_date', '>=', $fromDate);
        if ($toDate)   $query->whereDate('voucher_date', '<=', $toDate);

        $vouchers = $query->orderBy('voucher_date')->orderBy('id_vouchers')->get();

        $rows        = [];
        $balance     = 0;
        $totalDebit  = 0;
        $totalCredit = 0;

        // Opening Balance row
        $rows[] = [
            'date'       => $fromDate ? Carbon::parse($fromDate)->format('d/m/y') : '30/01/16',
            'detail'     => 'Opening Balance',
            'debit'      => null,
            'credit'     => null,
            'balance'    => 0,
            'dr_cr'      => '',
            'is_opening' => true,
        ];

        foreach ($vouchers as $voucher) {
            $entries = json_decode($voucher->adaegi_array, true) ?? [];

            foreach ($entries as $entry) {
                if ((string)($entry['adaegi_khata'] ?? '') !== (string)$supplierId) continue;

                $debit  = $this->parseAmount($entry['debit_amount']  ?? 0);
                $credit = $this->parseAmount($entry['credit_amount'] ?? 0);

                if ($debit == 0 && $credit == 0) continue;

                // Running balance: credit increases (supplier owes us / we owe supplier)
                // debit decreases — adjust sign to match your convention
                $balance    += $credit;
                $balance    -= $debit;
                $totalCredit += $credit;
                $totalDebit  += $debit;

                // description from entry, fallback to voucher details
                $detail = $entry['description'] ?? $voucher->voucher_details ?? '';

                $rows[] = [
                    'date'       => Carbon::parse($voucher->voucher_date)->format('d/m/y'),
                    'detail'     => $detail,
                    'debit'      => $debit  > 0 ? $debit  : null,
                    'credit'     => $credit > 0 ? $credit : null,
                    'balance'    => abs($balance),
                    'dr_cr'      => $balance > 0 ? 'Cr' : ($balance < 0 ? 'Dr' : ''),
                    'is_opening' => false,
                ];
            }
        }

        return compact('rows', 'totalDebit', 'totalCredit');
    }


    // ── Helpers ───────────────────────────────────────────────────────────────

    private function getSupplierList(): array
    {
        // Adjust table/column names to your actual suppliers table
        if (DB::getSchemaBuilder()->hasTable('suppliers')) {
            return DB::table('suppliers')
                ->select('id_supplier', 'supplier_name')
                ->orderBy('supplier_name')
                ->get()
                ->keyBy('id_supplier')
                ->map(fn($r) => $r->supplier_name)
                ->toArray();
        }

        // Fallback: harvest unique adaegi_khata values from vouchers
        $vouchers = DB::table('vouchers')->whereNotNull('adaegi_array')->get(['adaegi_array']);
        $map = [];
        foreach ($vouchers as $v) {
            foreach (json_decode($v->adaegi_array, true) ?? [] as $e) {
                $id = $e['adaegi_khata'] ?? null;
                if ($id && !isset($map[$id])) $map[$id] = 'سپلائر #' . $id;
            }
        }
        ksort($map);
        return $map;
    }

    private function getSupplierName(string $supplierId): string
    {
        return $this->getSupplierList()[$supplierId] ?? ('سپلائر #' . $supplierId);
    }

    private function parseAmount($val): float
    {
        return (float) str_replace(',', '', $val ?? 0);
    }
}
