<?php

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

use App\AllowanceClaimCode;
use App\AllowancePayout;
use App\Http\Controllers\Controller;
use App\Http\Controllers\Util;
use App\Result;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;

class ClaimCodeController extends Controller
{
    public function __invoke(Request $request)
    {
        $this->validate($request, [
            'method' => 'nullable|string|in:cash,bank',
        ]);

        $electionId = Util::getCurrentElection();
        $method = $request->input('method', 'cash');

        // voter auth guard; Auth::id() should be voter id under voterAPI
        $voterId = Auth::id();

        $voter = $request->user();
        if (!$voter || (int) $voter->id !== (int) $voterId) {
            return response()->json([
                'status' => 'failed',
                'message' => 'Unauthenticated.',
            ], 401);
        }

        // Enforce method by attendance
        if ($method === 'cash' && (int) $voter->kehadiran !== 1) {
            return response()->json([
                'status' => 'failed',
                'message' => 'Kod tuntutan tunai hanya untuk kehadiran Fizikal.',
            ], 422);
        }
        if ($method === 'bank' && (int) $voter->kehadiran !== 2) {
            return response()->json([
                'status' => 'failed',
                'message' => 'Kod tuntutan bank hanya untuk kehadiran Maya.',
            ], 422);
        }

        $hasVoted = Result::where('election_id', $electionId)->where('voter_id', $voterId)->exists();

        // Tunai: normally must have voted; exception — fizikal hadir & layak mesyuarat tetapi tidak dibenarkan
        // mengundi kerana saham < RM500 (same rule as voter UI).
        $kehadiran = (int) $voter->kehadiran;
        $saham = (float) $voter->saham;
        $canVoteBySaham = $saham >= 500.0;
        $canProceedToVote = $kehadiran !== 0
            && ($kehadiran !== 1 || $voter->fizikal_registration_verified_at !== null);
        $eligibleClaimCashWithoutVote = $method === 'cash'
            && $kehadiran === 1
            && $canProceedToVote
            && !$canVoteBySaham;

        if (!$hasVoted && !$eligibleClaimCashWithoutVote) {
            return response()->json([
                'status' => 'failed',
                'message' => 'Sila undi terlebih dahulu sebelum menuntut elaun.',
            ], 422);
        }

        // If already paid, don't generate codes
        $alreadyPaid = AllowancePayout::where('election_id', $electionId)
            ->where('voter_id', $voterId)
            ->where('method', $method)
            ->where('status', 'paid')
            ->exists();

        if ($alreadyPaid) {
            return response()->json([
                'status' => 'failed',
                'message' => 'Elaun anda telah direkodkan sebagai sudah dibayar.',
            ], 422);
        }

        // Generate a 6-digit numeric code
        $codeInt = random_int(0, 999999);
        $code = str_pad((string) $codeInt, 6, '0', STR_PAD_LEFT);

        $expiresAt = Carbon::now()->addHours(6);

        $row = AllowanceClaimCode::updateOrCreate(
            [
                'election_id' => $electionId,
                'voter_id' => $voterId,
                'method' => $method,
            ],
            [
                'code_hash' => Hash::make($code),
                'code_last4' => substr($code, -4),
                'expires_at' => $expiresAt,
                'used_at' => null,
                'used_by_admin_id' => null,
            ]
        );

        activity()
            ->performedOn($row)
            ->withProperties([
                'election_id' => $electionId,
                'voter_id' => (int) $voterId,
                'voter_name' => $voter->name,
                'attendance' => (int) $voter->kehadiran,
                'method' => $method,
                'expires_at' => $expiresAt->toDateTimeString(),
                'code_last4' => $row->code_last4,
                'ip' => $request->ip(),
                'user_agent' => $request->userAgent(),
            ])
            ->log("generate claim code ({$method}): {$voter->name}");

        return response()->json([
            'status' => 'success',
            'message' => 'Kod tuntutan berjaya dijana.',
            'code' => $code, // return plaintext ONCE to voter
            'expires_at' => $expiresAt,
            'method' => $method,
        ]);
    }
}

