<?php

namespace App\Http\Controllers;

use App\Models\Survey;
use App\Models\SurveyVoter;
use App\Models\Voter;
use App\Models\Booth;
use App\Models\Street;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;

class SurveyController extends Controller
{
    /**
     * Get all surveys (ordered by most recent)
     */
    public function getAllSurveys()
    {
        try {
            // Get total voters count from voters table
            $totalVotersCount = Voter::where('is_deleted', false)->count();
            
            $surveys = Survey::orderBy('survey_date', 'desc')
                ->withCount('surveyVoters')
                ->get()
                ->map(function ($survey) use ($totalVotersCount) {
                    $ratingCounts = $survey->getVoterCountsByRating();
                    
                    return [
                        'id' => $survey->id,
                        'title' => $survey->title,
                        'survey_date' => $survey->survey_date->format('Y-m-d H:i:s'),
                        'total_voters' => $totalVotersCount,
                        'surveyed_voters' => $survey->survey_voters_count,
                        'rating_breakdown' => [
                            'no_idea' => $ratingCounts[0] ?? 0,
                            'will_not_vote' => $ratingCounts[1] ?? 0,
                            'maybe_vote' => $ratingCounts[2] ?? 0,
                            'will_vote' => $ratingCounts[3] ?? 0,
                        ],
                        'created_at' => $survey->created_at,
                    ];
                });

            return response()->json([
                'status' => 200,
                'data' => $surveys,
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 500,
                'message' => 'Failed to fetch surveys',
                'error' => $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Create a new survey
     */
    public function createSurvey(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'title' => 'required|string|max:255',
            'survey_date' => 'nullable|date',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'status' => 422,
                'message' => 'Validation error',
                'errors' => $validator->errors(),
            ], 422);
        }

        try {
            $survey = Survey::create([
                'title' => $request->title,
                'survey_date' => $request->survey_date ?? now(),
            ]);

            return response()->json([
                'status' => 201,
                'message' => 'Survey created successfully',
                'data' => $survey,
            ], 201);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 500,
                'message' => 'Failed to create survey',
                'error' => $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Get survey details with all voters
     */
    public function getSurveyById($id)
    {
        try {
            // Get total voters count from voters table
            $totalVotersCount = Voter::where('is_deleted', false)->count();
            
            $survey = Survey::with(['surveyVoters.street'])
                ->findOrFail($id);

            $ratingCounts = $survey->getVoterCountsByRating();

            return response()->json([
                'status' => 200,
                'data' => [
                    'id' => $survey->id,
                    'title' => $survey->title,
                    'survey_date' => $survey->survey_date->format('Y-m-d H:i:s'),
                    'total_voters' => $totalVotersCount,
                    'surveyed_voters' => $survey->surveyVoters->count(),
                    'rating_breakdown' => [
                        'no_idea' => $ratingCounts[0] ?? 0,
                        'will_not_vote' => $ratingCounts[1] ?? 0,
                        'maybe_vote' => $ratingCounts[2] ?? 0,
                        'will_vote' => $ratingCounts[3] ?? 0,
                    ],
                    'voters' => $survey->surveyVoters->map(function ($voter) {
                        return [
                            'id' => $voter->id,
                            'voter_id' => $voter->voter_id,
                            'booth_id' => $voter->booth_id,
                            'street_id' => $voter->street_id,
                            'street_name' => $voter->street->street_name ?? null,
                            'rating' => $voter->rating,
                            'rating_label' => $this->getRatingLabel($voter->rating),
                        ];
                    }),
                ],
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 404,
                'message' => 'Survey not found',
                'error' => $e->getMessage(),
            ], 404);
        }
    }

    /**
     * Add or update voter rating in survey
     */
    public function addOrUpdateVoterRating(Request $request, $surveyId)
    {
        $validator = Validator::make($request->all(), [
            'voter_id' => 'required|string',
            'booth_id' => 'nullable|string',
            'street_id' => 'nullable|exists:streets,id',
            'rating' => 'required|integer|min:0|max:3',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'status' => 422,
                'message' => 'Validation error',
                'errors' => $validator->errors(),
            ], 422);
        }

        try {
            // Check if survey exists
            $survey = Survey::findOrFail($surveyId);

            // Create or update voter rating
            $surveyVoter = SurveyVoter::updateOrCreate(
                [
                    'survey_id' => $surveyId,
                    'voter_id' => $request->voter_id,
                ],
                [
                    'booth_id' => $request->booth_id,
                    'street_id' => $request->street_id,
                    'rating' => $request->rating,
                ]
            );

            return response()->json([
                'status' => 200,
                'message' => 'Voter rating saved successfully',
                'data' => $surveyVoter,
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 500,
                'message' => 'Failed to save voter rating',
                'error' => $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Delete a survey
     */
    public function deleteSurvey($id)
    {
        try {
            $survey = Survey::findOrFail($id);
            $survey->delete();

            return response()->json([
                'status' => 200,
                'message' => 'Survey deleted successfully',
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 500,
                'message' => 'Failed to delete survey',
                'error' => $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Get all booths with survey rating breakdowns for a specific survey
     */
    public function getAllBooths($surveyId)
    {
        try {
            // Check if survey exists
            $survey = Survey::findOrFail($surveyId);

            // Get all booths with their rating breakdowns for this survey
            $booths = Booth::where('is_deleted', false)->get()->map(function ($booth) use ($surveyId) {
                // Get rating breakdown for this booth in this survey
                // Note: SurveyVoter.booth_id (string) should match Booth.id (integer)
                $ratingCounts = SurveyVoter::where('survey_id', $surveyId)
                    ->where('booth_id', $booth->id)
                    ->selectRaw('rating, count(*) as count')
                    ->groupBy('rating')
                    ->pluck('count', 'rating')
                    ->toArray();

                // Get total voters count in this booth
                $totalVotersInBooth = Voter::where('booth_number', $booth->booth_number)
                    ->where('is_deleted', false)
                    ->count();

                // Get surveyed voters count in this booth for this survey
                $surveyedVotersInBooth = SurveyVoter::where('survey_id', $surveyId)
                    ->where('booth_id', $booth->id)
                    ->count();

                // Get only streets that have voters in this specific booth
                $streetsInBooth = Street::whereExists(function($query) use ($booth) {
                    $query->select(DB::raw(1))
                          ->from('voters')
                          ->whereRaw('voters.street_id = streets.id')
                          ->where('voters.booth_number', $booth->booth_number)
                          ->where('voters.is_deleted', false);
                })->where('is_deleted', false)->get();

                // Get streets in this booth with their rating breakdowns
                $streets = $streetsInBooth->map(function ($street) use ($surveyId, $booth) {
                    // Get rating breakdown for this street in this booth for this survey
                    $streetRatingCounts = SurveyVoter::where('survey_id', $surveyId)
                        ->where('booth_id', $booth->id)
                        ->where('street_id', $street->id)
                        ->selectRaw('rating, count(*) as count')
                        ->groupBy('rating')
                        ->pluck('count', 'rating')
                        ->toArray();

                    // Get total voters count in this street of this booth
                    $totalVotersInStreet = Voter::where('booth_number', $booth->booth_number)
                        ->where('street_id', $street->id)
                        ->where('is_deleted', false)
                        ->count();

                    // Get surveyed voters count in this street for this survey
                    $surveyedVotersInStreet = SurveyVoter::where('survey_id', $surveyId)
                        ->where('booth_id', $booth->id)
                        ->where('street_id', $street->id)
                        ->count();

                    // Only include streets that have voters or survey data
                    if ($totalVotersInStreet > 0 || $surveyedVotersInStreet > 0) {
                        return [
                            'id' => $street->id,
                            'street_name' => $street->street_name,
                            'total_voters' => $totalVotersInStreet,
                            'surveyed_voters' => $surveyedVotersInStreet,
                            'rating_breakdown' => [
                                'no_idea' => (int)($streetRatingCounts[0] ?? 0),
                                'will_not_vote' => (int)($streetRatingCounts[1] ?? 0),
                                'maybe_vote' => (int)($streetRatingCounts[2] ?? 0),
                                'will_vote' => (int)($streetRatingCounts[3] ?? 0),
                            ],
                        ];
                    }
                    return null;
                })->filter(); // Remove null entries

                return [
                    'id' => $booth->id,
                    'booth_number' => $booth->booth_number,
                    'booth_address' => $booth->booth_address,
                    'total_voters' => $totalVotersInBooth,
                    'surveyed_voters' => $surveyedVotersInBooth,
                    'rating_breakdown' => [
                        'no_idea' => (int)($ratingCounts[0] ?? 0),
                        'will_not_vote' => (int)($ratingCounts[1] ?? 0),
                        'maybe_vote' => (int)($ratingCounts[2] ?? 0),
                        'will_vote' => (int)($ratingCounts[3] ?? 0),
                    ],
                    'streets' => $streets->values(), // Reset array keys
                ];
            });

            return response()->json([
                'status' => 200,
                'message' => 'Booths with survey data fetched successfully',
                'data' => [
                    'survey_id' => $survey->id,
                    'survey_title' => $survey->title,
                    'booths' => $booths,
                    'total_booths' => $booths->count(),
                ],
            ], 200);

        } catch (\Exception $e) {
            return response()->json([
                'status' => 404,
                'message' => 'Survey not found or failed to fetch booth data',
                'error' => $e->getMessage(),
            ], 404);
        }
    }



    /**
     * Helper method to get rating label
     */
    private function getRatingLabel($rating)
    {
        $labels = [
            0 => 'No idea',
            1 => 'Will not vote',
            2 => 'Maybe (50:50)',
            3 => 'Will vote',
        ];

        return $labels[$rating] ?? 'Unknown';
    }
}
