<?php
namespace App\Http\Controllers\Api\V1;

use App\Http\Controllers\Controller;
use App\Models\Account;
use App\Models\ClientIpc;
use App\Models\PayrollLine;
use App\Models\PurchaseInvoice;
use App\Models\SalesInvoice;
use App\Models\Supplier;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

/** Live data for the Command Centre — Ghana Tax & Statutory module (Group scope: filed per company/TIN). */
class TaxController extends Controller
{
    use Concerns\DashboardHelpers;

    public function show(Request $r)
    {
        $this->need('finance.view');
        [$cf, $ct, $pf, $pt, $grain] = $this->windows((string) $r->get('period', 'This Month'));

        $si = fn() => SalesInvoice::where('status', '!=', 'draft');
        $pi = fn() => PurchaseInvoice::where('status', '!=', 'draft');
        $out = $this->sumBetween($si(), 'invoice_date', 'vat_amount', $cf, $ct);
        $outP = $this->sumBetween($si(), 'invoice_date', 'vat_amount', $pf, $pt);
        $in = $this->sumBetween($pi(), 'invoice_date', 'tax_amount', $cf, $ct);
        $inP = $this->sumBetween($pi(), 'invoice_date', 'tax_amount', $pf, $pt);
        $lev = (float) (clone $si())->whereBetween('invoice_date', [$cf, $ct])->selectRaw('sum(levy_nhil+levy_getfund+levy_covid) v')->value('v');
        $levP = (float) (clone $si())->whereBetween('invoice_date', [$pf, $pt])->selectRaw('sum(levy_nhil+levy_getfund+levy_covid) v')->value('v');
        $wht = $this->sumBetween($pi(), 'invoice_date', 'withholding_tax', $cf, $ct);
        $whtP = $this->sumBetween($pi(), 'invoice_date', 'withholding_tax', $pf, $pt);
        $whtSuf = $this->sumBetween(ClientIpc::where('status', '!=', 'draft'), 'ipc_date', 'tax_withheld', $cf, $ct);
        $whtSufP = $this->sumBetween(ClientIpc::where('status', '!=', 'draft'), 'ipc_date', 'tax_withheld', $pf, $pt);

        $gl = fn($c) => (float) Account::where('code', $c)->value('current_balance');
        $vatPay = $gl('2100');
        $vatRec = $gl('2140');
        $levPay = $gl('2110') + $gl('2120') + $gl('2130');
        $whtPay = $gl('2150');
        $payePay = $gl('2160');
        $ssnitPay = $gl('2170');

        $cards = [
            $this->card('Output VAT (' . $r->get('period', 'This Month') . ')', round($out), 'GHS', round($outP)),
            $this->card('Input VAT (' . $r->get('period', 'This Month') . ')', round($in), 'GHS', round($inP)),
            $this->card('Net VAT Position', round($out - $in), 'GHS', round($outP - $inP), [], ['good' => 'down', 'info' => 'output less input; negative = refundable']),
            $this->card('VAT Payable (GL)', round($vatPay), 'GHS', round($vatPay), [], ['good' => 'down']),
            $this->card('Input VAT Recoverable (GL)', round($vatRec), 'GHS', round($vatRec), [], ['st' => 'blue']),
            $this->card('Sales Levies NHIL/GETF/COVID', round($lev), 'GHS', round($levP)),
            $this->card('Levies Payable (GL)', round($levPay), 'GHS', round($levPay), [], ['good' => 'down']),
            $this->card('WHT Withheld on Suppliers', round($wht), 'GHS', round($whtP), [], ['st' => 'blue']),
            $this->card('WHT Payable (GL)', round($whtPay), 'GHS', round($whtPay), [], ['good' => 'down']),
            $this->card('WHT Suffered on IPCs', round($whtSuf), 'GHS', round($whtSufP), [], ['st' => 'blue', 'info' => 'claimable against income tax']),
            $this->card('PAYE Payable (GL)', round($payePay), 'GHS', round($payePay), [], ['st' => 'blue']),
            $this->card('SSNIT Payable (GL)', round($ssnitPay), 'GHS', round($ssnitPay), [], ['st' => 'blue']),
        ];

        return response()->json([
            'sub' => 'VAT · NHIL/GETFund/COVID · WHT · PAYE · SSNIT · Group · ' . $r->get('period', 'This Month'),
            'asAt' => Carbon::today()->format('d M Y'),
            'cards' => $cards,
            'sections' => [
                $this->secVat(),
                $this->secMix($vatPay, $levPay, $whtPay, $payePay, $ssnitPay),
                $this->secWhtSupp($cf, $ct),
                $this->secTie(),
                $this->secOutput(),
                $this->secInput(),
                $this->secIpcWht(),
            ],
        ]);
    }

    private function secVat(): array
    {
        return ['k' => 'chart', 'id' => 'tx_vat', 'ti' => 'Output vs Input VAT — GHS per day (30 days)', 'cls' => 'wide', 'spec' => [
            'type' => 'line', 'fmt' => 'money', 'zoom' => true, 'height' => 280,
            'labels' => $this->dailyLabels(30),
            'series' => [
                ['name' => 'Output', 'data' => $this->daily('sales_invoices', 'invoice_date', 'vat_amount', "status != 'draft'", 30), 'color' => '#ef4444', 'area' => true],
                ['name' => 'Input', 'data' => $this->daily('purchase_invoices', 'invoice_date', 'tax_amount', "status != 'draft'", 30), 'color' => '#22c55e'],
            ],
        ]];
    }

    private function secMix($vatPay, $levPay, $whtPay, $payePay, $ssnitPay): array
    {
        $pal = $this->palette();
        $raw = [['VAT', $vatPay], ['Levies', $levPay], ['WHT', $whtPay], ['PAYE', $payePay], ['SSNIT', $ssnitPay]];
        $items = [];
        foreach (array_values($raw) as $i => [$l, $v]) {
            if ($v > 0) $items[] = ['label' => $l, 'value' => round($v), 'color' => $pal[$i % count($pal)]];
        }
        return ['k' => 'chart', 'id' => 'tx_mix', 'ti' => 'Statutory Liabilities — GHS by tax (GL, live)', 'spec' => [
            'type' => 'doughnut', 'fmt' => 'money', 'center' => 'Due', 'items' => $items,
        ]];
    }

    private function secWhtSupp($cf, $ct): array
    {
        $rows = PurchaseInvoice::where('status', '!=', 'draft')->whereBetween('invoice_date', [$cf, $ct])
            ->where('withholding_tax', '>', 0)
            ->select('supplier_id', DB::raw('sum(withholding_tax) t'))->groupBy('supplier_id')->orderByDesc('t')->take(8)->get();
        $names = Supplier::whereIn('id', $rows->pluck('supplier_id'))->pluck('name', 'id');
        return ['k' => 'chart', 'id' => 'tx_wht', 'ti' => 'Top WHT Withheld by Supplier — GHS (period)', 'spec' => [
            'type' => 'hbar', 'fmt' => 'money',
            'labels' => $rows->map(fn($r) => mb_strimwidth($names[$r->supplier_id] ?? ('#' . $r->supplier_id), 0, 24, '…'))->all(),
            'series' => [['name' => 'GHS', 'data' => $rows->map(fn($r) => round((float) $r->t))->all(), 'color' => '#a855f7']],
        ]];
    }

    private function secTie(): array
    {
        $sub = [
            '2100' => \App\Services\CurrencyService::sumGhs(SalesInvoice::where('status', '!=', 'draft'), 'vat_amount'),
            '2110' => \App\Services\CurrencyService::sumGhs(SalesInvoice::where('status', '!=', 'draft'), 'levy_nhil'),
            '2120' => \App\Services\CurrencyService::sumGhs(SalesInvoice::where('status', '!=', 'draft'), 'levy_getfund'),
            '2130' => \App\Services\CurrencyService::sumGhs(SalesInvoice::where('status', '!=', 'draft'), 'levy_covid'),
            '2140' => \App\Services\CurrencyService::sumGhs(PurchaseInvoice::where('status', '!=', 'draft'), 'tax_amount'),
            '2150' => \App\Services\CurrencyService::sumGhs(PurchaseInvoice::where('status', '!=', 'draft'), 'withholding_tax'),
            '2160' => (float) PayrollLine::sum('paye'),
            '2170' => (float) PayrollLine::selectRaw('sum(ssnit_employee+ssnit_employer) v')->value('v'),
        ];
        $rows = Account::whereIn('code', array_keys($sub))->orderBy('code')->get()->map(function ($a) use ($sub) {
            $gl = round((float) $a->current_balance, 2);
            $sl = round($sub[$a->code] ?? 0, 2);
            $diff = round($gl - $sl, 2);
            return ['code' => $a->code, 'acc' => $a->name, 'gl' => $gl, 'sub' => $sl, 'diff' => $diff,
                'st' => abs($diff) < 0.01 ? 'green' : 'red', 'stL' => abs($diff) < 0.01 ? 'Tied' : 'Differs'];
        })->all();
        return ['k' => 'table', 'id' => 'tx_tie', 'ti' => 'Statutory Control Tie-out — GL vs source documents (live)', 'cls' => 'wide', 'cfg' => [
            'id' => 'tx_tie', 'page' => 10, 'search' => true,
            'cols' => [
                ['k' => 'code', 'l' => 'GL'], ['k' => 'acc', 'l' => 'Tax account', 'wide' => 1],
                ['k' => 'gl', 'l' => 'GL balance', 'y' => 'num'], ['k' => 'sub', 'l' => 'Source docs', 'y' => 'num'],
                ['k' => 'diff', 'l' => 'Diff', 'y' => 'num'], ['k' => 'st', 'l' => 'Tie-out', 'y' => 'badge'],
            ], 'rows' => $rows, 'totals' => [],
        ]];
    }

    private function secOutput(): array
    {
        $rows = SalesInvoice::with('customer')->where('status', '!=', 'draft')
            ->orderByDesc('invoice_date')->take(60)->get()
            ->map(fn($v) => ['no' => $v->invoice_no, 'date' => substr((string) $v->invoice_date, 0, 10),
                'cust' => $v->customer->name ?? '', 'sub' => round((float) $v->subtotal),
                'nhil' => round((float) $v->levy_nhil, 2), 'getf' => round((float) $v->levy_getfund, 2),
                'cov' => round((float) $v->levy_covid, 2), 'vat' => round((float) $v->vat_amount, 2),
                'total' => round((float) $v->grand_total)])->all();
        return ['k' => 'table', 'id' => 'tx_out', 'ti' => 'Output VAT Schedule — by sales invoice (latest 60)', 'cls' => 'wide', 'cfg' => [
            'id' => 'tx_out', 'page' => 12, 'search' => true,
            'cols' => [
                ['k' => 'no', 'l' => 'Invoice'], ['k' => 'date', 'l' => 'Date'], ['k' => 'cust', 'l' => 'Customer', 'wide' => 1],
                ['k' => 'sub', 'l' => 'Subtotal', 'y' => 'num'], ['k' => 'nhil', 'l' => 'NHIL', 'y' => 'num'],
                ['k' => 'getf', 'l' => 'GETFund', 'y' => 'num'], ['k' => 'cov', 'l' => 'COVID', 'y' => 'num'],
                ['k' => 'vat', 'l' => 'VAT', 'y' => 'num'], ['k' => 'total', 'l' => 'Total', 'y' => 'num'],
            ], 'rows' => $rows, 'totals' => ['sub', 'nhil', 'getf', 'cov', 'vat', 'total'],
        ]];
    }

    private function secInput(): array
    {
        $rows = PurchaseInvoice::with('supplier')->where('status', '!=', 'draft')
            ->orderByDesc('invoice_date')->take(60)->get()
            ->map(fn($v) => ['no' => $v->pin_no, 'date' => substr((string) $v->invoice_date, 0, 10),
                'supp' => $v->supplier->name ?? '', 'sub' => round((float) $v->subtotal),
                'vat' => round((float) $v->tax_amount, 2), 'wht' => round((float) $v->withholding_tax, 2),
                'total' => round((float) $v->grand_total)])->all();
        return ['k' => 'table', 'id' => 'tx_in', 'ti' => 'Input VAT & WHT Schedule — by supplier invoice (latest 60)', 'cls' => 'wide', 'cfg' => [
            'id' => 'tx_in', 'page' => 12, 'search' => true,
            'cols' => [
                ['k' => 'no', 'l' => 'PIN'], ['k' => 'date', 'l' => 'Date'], ['k' => 'supp', 'l' => 'Supplier', 'wide' => 1],
                ['k' => 'sub', 'l' => 'Subtotal', 'y' => 'num'], ['k' => 'vat', 'l' => 'Input VAT', 'y' => 'num'],
                ['k' => 'wht', 'l' => 'WHT', 'y' => 'num'], ['k' => 'total', 'l' => 'Total', 'y' => 'num'],
            ], 'rows' => $rows, 'totals' => ['sub', 'vat', 'wht', 'total'],
        ]];
    }

    private function secIpcWht(): array
    {
        $rows = ClientIpc::with('project')->orderByDesc('ipc_date')->take(30)->get()
            ->map(fn($i) => ['no' => $i->ipc_no, 'proj' => $i->project->code ?? '',
                'date' => substr((string) $i->ipc_date, 0, 10),
                'gross' => round((float) $i->gross_valuation), 'wht' => round((float) $i->tax_withheld, 2),
                'net' => round((float) $i->net_certified),
                'st' => $i->status === 'draft' ? 'grey' : 'blue', 'stL' => ucfirst((string) $i->status)])->all();
        return ['k' => 'table', 'id' => 'tx_ipc', 'ti' => 'WHT Suffered on Client IPCs — latest 30', 'cls' => 'wide', 'cfg' => [
            'id' => 'tx_ipc', 'page' => 10, 'search' => true,
            'cols' => [
                ['k' => 'no', 'l' => 'IPC'], ['k' => 'proj', 'l' => 'Project'], ['k' => 'date', 'l' => 'Date'],
                ['k' => 'gross', 'l' => 'Gross', 'y' => 'num'], ['k' => 'wht', 'l' => 'WHT suffered', 'y' => 'num'],
                ['k' => 'net', 'l' => 'Net certified', 'y' => 'num'], ['k' => 'st', 'l' => 'Status', 'y' => 'badge'],
            ], 'rows' => $rows, 'totals' => ['gross', 'wht', 'net'],
        ]];
    }
}
