<?php

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

use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Util;
use App\Position;
use App\Nominee;
use App\Result;

class VoteController extends Controller
{

    public function __invoke(Request $request)
    {
        $validation = $this->validateRequest($request);
        if (($validation['status'] ?? 'failed') === 'failed') {
            return response()->json($validation);
        }

        $this->insertVote($request);

        $user = Auth::guard('voter')->user() ?: $request->user();
        $vote = is_array($request->vote) ? $request->vote : [];
        $positionsVoted = 0;
        $totalSelections = 0;
        foreach ($vote as $value) {
            $nomineeIds = $value['nominee_id'] ?? null;
            if (is_array($nomineeIds) && count($nomineeIds)) {
                $positionsVoted++;
                $totalSelections += count($nomineeIds);
            }
        }

        activity()
            ->performedOn($user)
            ->withProperties([
                'election_id' => Util::getCurrentElection(),
                'voter_id' => Auth::id(),
                'voter_name' => $user ? $user->name : null,
                'positions_voted' => $positionsVoted,
                'total_selections' => $totalSelections,
                'ip' => $request->ip(),
                'user_agent' => $request->userAgent(),
            ])
            ->log('submit vote');

        return response()->json([
            'status' => 'success',
            'message' => 'Undian anda telah berjaya dihantar.',
            'result' => Result::where('voter_id', Auth::id())->get()
        ]);
    }

    private function insertVote($request)
    {
        $vote = $request->vote;
        if (!is_array($vote)) return;

        foreach ($vote as $value) {
            $positionId = $value['position_id'] ?? null;
            $nomineeIds = $value['nominee_id'] ?? [];
            if (!$positionId || !is_array($nomineeIds) || !count($nomineeIds)) continue;

            foreach ($nomineeIds as $nomineeId) {
                Result::updateOrCreate([
                    'voter_id' => Auth::id(),
                    'election_id' => Util::getCurrentElection(),
                    'position_id' => $positionId,
                    'nominee_id' => $nomineeId,
                ]);
            }
        }
    }

    private function validNominee($id, $position_id)
    {
        try{
            $nominee = Nominee::where('position_id', '=', $position_id)->whereIn('id',$id)->count();
        }catch(\Exception $e){
            return 0;
        }
        return $nominee;
    }

    private function isPositionExist($id)
    {
        try{
            return Position::where('id', $id)->count();        
        }catch(\Exception $e){
            return 0;
        }
    }

    private function voteAllPosition($request)
    {
        $total_position = Position::where('election_id', Util::getCurrentElection())->count();
        $total_vote = !empty($request->vote) ? count($request->vote) : 0;
        
        return $total_vote >= $total_position;
    }
    

    private function validateRequest($request)
    {
        $result['status'] = 'failed';
        $vote = $request->vote;

        if (!is_array($vote) || !count($vote)) {
            $result['message'] = 'You must vote on at least one position.';
            return $result;
        }

        foreach ($vote as $value) {
            /**
             * Check if position_id and nominee_id has a value
             */
            // dd($vote,$value);
            $positionId = $value['position_id'] ?? null;
            $nomineeIds = $value['nominee_id'] ?? null;
            if (empty($positionId)) {
                $result['message'] = 'Invalid Position.';
                return $result;
            }
            if (!is_array($nomineeIds) || !count($nomineeIds)) {
                // Skip empty positions; allow partial voting setups (UI may send all positions with empty arrays)
                continue;
            }
            if (count($nomineeIds) > 1) {
                $result['message'] = 'You can only vote for one nominee.';
                return $result;
            }

            /**
             * Check if the Position you vote exists
             */
            if (!$this->isPositionExist($positionId)) {
                $result['message'] = 'Invalid Position.';
                return $result;
            } 

            /**
             * Check if the Nominee you vote on certain position exists
             */
            // elseif (!$this->validNominee($value['nominee_id'], $value['position_id'])) {
                elseif($this->validNominee($nomineeIds, $positionId) <= 0){

                $result['message'] = 'Invalid Nominee for '.Position::find($positionId)->name.' position.';

                return $result;
            } 
        }

        // Ensure at least one actual vote exists
        $hasAny = false;
        foreach ($vote as $value) {
            $nomineeIds = $value['nominee_id'] ?? null;
            if (is_array($nomineeIds) && count($nomineeIds)) {
                $hasAny = true;
                break;
            }
        }
        if (!$hasAny) {
            $result['message'] = 'You must vote on at least one position.';
            return $result;
        }

        return ['status' => 'success'];
    }
}
