<?php

namespace App\Http\Controllers\API\v1\Voter;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Controllers\Util;
use Illuminate\Support\Facades\DB;
use App\Voter;

class GetController extends Controller
{
    public function __invoke()
    {
        $electionId = Util::getCurrentElection();

        $q = Voter::query()
            ->where('election_id', $electionId)
            // Ensure we keep all voter columns when adding computed selects
            ->select('voter.*')
            // Computed: whether voter has any vote record for this election
            ->selectSub(function ($sq) use ($electionId) {
                $sq->from('result')
                    ->selectRaw('COUNT(*)')
                    ->whereColumn('result.voter_id', 'voter.id')
                    ->where('result.election_id', $electionId);
            }, 'votes_count');

        // Computed: payout timestamps (paperless coupon replacement state)
        $q->selectSub(function ($sq) use ($electionId) {
            $sq->from('allowance_payouts')
                ->selectRaw('MAX(paid_at)')
                ->whereColumn('allowance_payouts.voter_id', 'voter.id')
                ->where('allowance_payouts.election_id', $electionId)
                ->where('allowance_payouts.method', 'cash')
                ->where('allowance_payouts.status', 'paid');
        }, 'cash_paid_at');

        $q->selectSub(function ($sq) use ($electionId) {
            $sq->from('allowance_payouts')
                ->selectRaw('MAX(id)')
                ->whereColumn('allowance_payouts.voter_id', 'voter.id')
                ->where('allowance_payouts.election_id', $electionId)
                ->where('allowance_payouts.method', 'cash')
                ->where('allowance_payouts.status', 'paid');
        }, 'cash_payout_id');

        // Latest paid cash payout — Rujukan / Nota for admin allowance modal ($electionId bound as int)
        $eid = (int) $electionId;
        $q->addSelect([
            DB::raw("(SELECT ap.reference FROM allowance_payouts ap WHERE ap.voter_id = voter.id AND ap.election_id = {$eid} AND ap.method = 'cash' AND ap.status = 'paid' ORDER BY ap.id DESC LIMIT 1) as cash_payout_reference"),
            DB::raw("(SELECT ap.note FROM allowance_payouts ap WHERE ap.voter_id = voter.id AND ap.election_id = {$eid} AND ap.method = 'cash' AND ap.status = 'paid' ORDER BY ap.id DESC LIMIT 1) as cash_payout_note"),
            DB::raw("(SELECT u.name FROM allowance_payouts ap LEFT JOIN users u ON u.id = ap.paid_by_admin_id WHERE ap.voter_id = voter.id AND ap.election_id = {$eid} AND ap.method = 'cash' AND ap.status = 'paid' ORDER BY ap.id DESC LIMIT 1) as cash_paid_by_admin_name"),
            DB::raw("(SELECT u.email FROM allowance_payouts ap LEFT JOIN users u ON u.id = ap.paid_by_admin_id WHERE ap.voter_id = voter.id AND ap.election_id = {$eid} AND ap.method = 'cash' AND ap.status = 'paid' ORDER BY ap.id DESC LIMIT 1) as cash_paid_by_admin_email"),
        ]);

        $q->selectSub(function ($sq) use ($electionId) {
            $sq->from('allowance_payouts')
                ->selectRaw('MAX(paid_at)')
                ->whereColumn('allowance_payouts.voter_id', 'voter.id')
                ->where('allowance_payouts.election_id', $electionId)
                ->where('allowance_payouts.method', 'bank')
                ->where('allowance_payouts.status', 'paid');
        }, 'bank_paid_at');

        $q->selectSub(function ($sq) use ($electionId) {
            $sq->from('allowance_payouts')
                ->selectRaw('MAX(id)')
                ->whereColumn('allowance_payouts.voter_id', 'voter.id')
                ->where('allowance_payouts.election_id', $electionId)
                ->where('allowance_payouts.method', 'bank')
                ->where('allowance_payouts.status', 'paid');
        }, 'bank_payout_id');

        // Optional search filters
        $noAnggota = request('no_anggota');
        if ($noAnggota !== null && $noAnggota !== '') {
            $q->where('no_anggota', 'like', '%' . $noAnggota . '%');
        }

        $noKp = request('no_kp');
        if ($noKp !== null && $noKp !== '') {
            $q->where('no_kp', 'like', '%' . $noKp . '%');
        }

        $name = request('name');
        if ($name !== null && $name !== '') {
            $q->where('name', 'like', '%' . $name . '%');
        }

        // Optional attendance filter: 1 = Fizikal, 2 = Maya
        $kehadiran = request('kehadiran');
        if ($kehadiran !== null && $kehadiran !== '') {
            if ($kehadiran === 'unset') {
                $q->where(function ($qq) {
                    $qq->whereNull('kehadiran')->orWhere('kehadiran', 0);
                });
            } else {
                $k = (int) $kehadiran;
                if (in_array($k, [1, 2], true)) {
                    $q->where('kehadiran', $k);
                }
            }
        }

        // Fizikal registration queue: pending = fizikal but not admin-verified yet
        $fizikalReg = request('fizikal_reg');
        if ($fizikalReg !== null && $fizikalReg !== '') {
            if ($fizikalReg === 'pending') {
                $q->where('kehadiran', 1)->whereNull('fizikal_registration_verified_at');
            } elseif ($fizikalReg === 'verified') {
                $q->where('kehadiran', 1)->whereNotNull('fizikal_registration_verified_at');
            }
        }

        // Vote status: 1 = has voted, 0 = has not voted (for this election)
        $hasVoted = request('has_voted');
        if ($hasVoted !== null && $hasVoted !== '') {
            $hv = (string) $hasVoted;
            if ($hv === '1' || $hv === 'true' || $hv === 'yes') {
                $q->whereExists(function ($sub) use ($electionId) {
                    $sub->from('result')
                        ->whereColumn('result.voter_id', 'voter.id')
                        ->where('result.election_id', $electionId);
                });
            } elseif ($hv === '0' || $hv === 'false' || $hv === 'no') {
                $q->whereNotExists(function ($sub) use ($electionId) {
                    $sub->from('result')
                        ->whereColumn('result.voter_id', 'voter.id')
                        ->where('result.election_id', $electionId);
                });
            }
        }

        // Cash allowance payment status (matches admin "Status" column: cash_paid_at)
        $cashStatus = request('cash_status');
        if ($cashStatus !== null && $cashStatus !== '') {
            if ($cashStatus === 'paid') {
                $q->whereExists(function ($sub) use ($electionId) {
                    $sub->from('allowance_payouts')
                        ->whereColumn('allowance_payouts.voter_id', 'voter.id')
                        ->where('allowance_payouts.election_id', $electionId)
                        ->where('allowance_payouts.method', 'cash')
                        ->where('allowance_payouts.status', 'paid');
                });
            } elseif ($cashStatus === 'unpaid') {
                $q->whereNotExists(function ($sub) use ($electionId) {
                    $sub->from('allowance_payouts')
                        ->whereColumn('allowance_payouts.voter_id', 'voter.id')
                        ->where('allowance_payouts.election_id', $electionId)
                        ->where('allowance_payouts.method', 'cash')
                        ->where('allowance_payouts.status', 'paid');
                });
            }
        }

        // Return all voters with pagination
        return $q->paginate(1000);
    }
}
