<?php

namespace App\Http\Controllers;

use App\Models\Organization;
use App\Models\ElectionCycle;
use App\Models\LeadershipPosition;
use App\Models\VotingProcedure;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Illuminate\View\View;

/**
 * ElectionCycleController
 *
 * Handles CRUD operations for election cycles.
 * Only accessible by users with Super Manager or Manager roles.
 */
class ElectionCycleController extends Controller
{
    /**
     * Display a listing of election cycles.
     */
    public function index(): View
    {
        abort_unless(auth()->user()->can('view election cycles'), 403,
            'You do not have permission to view election cycles.');

        $electionCycles = ElectionCycle::with(['organization', 'votingProcedures'])
            ->withCount('votingProcedures')
            ->orderBy('start_date', 'desc')
            ->paginate(15);

        return view('organization.election-cycles.index', compact('electionCycles'));
    }

    /**
     * Show the form for creating a new election cycle.
     */
    public function create(): View
    {
        abort_unless(auth()->user()->can('create election cycles'), 403,
            'You do not have permission to create election cycles.');

        $organizations = Organization::orderBy('name')->get();
        $votingProcedures = null;

        if (request()->has('organization_id')) {
            $votingProcedures = \App\Models\VotingProcedure::where('organization_id', request('organization_id'))
                ->orderBy('name')
                ->get();
        }

        return view('organization.election-cycles.create', compact('organizations', 'votingProcedures'));
    }

    /**
     * Store a newly created election cycle in storage.
     */
    public function store(Request $request): RedirectResponse
    {
        abort_unless(auth()->user()->can('create election cycles'), 403,
            'You do not have permission to create election cycles.');

        $validated = $request->validate([
            'organization_id' => 'required|exists:organizations,id',
            'name' => 'required|string|max:191',
            'duration_years' => 'required|numeric|min:0.5|max:10',
            'start_date' => 'required|date',
            'applicable_positions' => 'required|array',
            'applicable_positions.*' => 'exists:leadership_positions,id',
            'voting_procedures' => 'nullable|array',
            'voting_procedures.*' => 'exists:voting_procedures,id',
        ], [
            'organization_id.required' => 'Please select an organization.',
            'name.required' => 'Election cycle name is required.',
            'duration_years.required' => 'Duration is required.',
            'duration_years.min' => 'Duration must be at least 0.5 years.',
            'duration_years.max' => 'Duration cannot exceed 10 years.',
            'start_date.required' => 'Start date is required.',
            'applicable_positions.required' => 'Please select at least one applicable position.',
        ]);

        // XSS Prevention
        $validated['name'] = strip_tags($validated['name']);

        // Calculate end date
        $startDate = \Carbon\Carbon::parse($validated['start_date']);
        $years = floor($validated['duration_years']);
        $months = ($validated['duration_years'] - $years) * 12;
        $endDate = $startDate->copy()->addYears((int) $years)->addMonths((int) $months);

        // Create election cycle
        $electionCycle = ElectionCycle::create([
            'organization_id' => $validated['organization_id'],
            'name' => $validated['name'],
            'duration_years' => $validated['duration_years'],
            'start_date' => $validated['start_date'],
            'end_date' => $endDate,
            'status' => ElectionCycle::STATUS_ACTIVE,
            'applicable_positions' => $validated['applicable_positions'],
        ]);

        // Sync voting procedures
        if (!empty($validated['voting_procedures'])) {
            $electionCycle->votingProcedures()->sync($validated['voting_procedures']);
        }

        return redirect()
            ->route('organization.election-cycles.index')
            ->with('success', 'Election cycle created successfully!');
    }

    /**
     * Display the specified election cycle.
     */
    public function show(ElectionCycle $electionCycle): View
    {
        abort_unless(auth()->user()->can('view election cycles'), 403,
            'You do not have permission to view election cycles.');

        $electionCycle->load(['organization', 'votingProcedures']);
        $applicablePositions = $electionCycle->getApplicablePositions();
        $daysUntilElection = $electionCycle->getDaysUntilNextElection();

        return view('organization.election-cycles.show', compact('electionCycle', 'applicablePositions', 'daysUntilElection'));
    }

    /**
     * Show the form for editing the specified election cycle.
     */
    public function edit(ElectionCycle $electionCycle): View
    {
        abort_unless(auth()->user()->can('edit election cycles'), 403,
            'You do not have permission to edit election cycles.');

        $organizations = Organization::orderBy('name')->get();
        $positions = LeadershipPosition::where('organization_id', $electionCycle->organization_id)
            ->orderBy('title')
            ->get();
        $votingProcedures = \App\Models\VotingProcedure::where('organization_id', $electionCycle->organization_id)
            ->orderBy('name')
            ->get();
        $selectedProcedures = $electionCycle->votingProcedures->pluck('id')->toArray();

        return view('organization.election-cycles.edit', compact('electionCycle', 'organizations', 'positions', 'votingProcedures', 'selectedProcedures'));
    }

    /**
     * Update the specified election cycle in storage.
     */
    public function update(Request $request, ElectionCycle $electionCycle): RedirectResponse
    {
        abort_unless(auth()->user()->can('edit election cycles'), 403,
            'You do not have permission to edit election cycles.');

        $validated = $request->validate([
            'organization_id' => 'required|exists:organizations,id',
            'name' => 'required|string|max:191',
            'duration_years' => 'required|numeric|min:0.5|max:10',
            'start_date' => 'required|date',
            'applicable_positions' => 'required|array',
            'applicable_positions.*' => 'exists:leadership_positions,id',
            'voting_procedures' => 'nullable|array',
            'voting_procedures.*' => 'exists:voting_procedures,id',
        ], [
            'organization_id.required' => 'Please select an organization.',
            'name.required' => 'Election cycle name is required.',
            'applicable_positions.required' => 'Please select at least one applicable position.',
        ]);

        // XSS Prevention
        $validated['name'] = strip_tags($validated['name']);

        // Calculate end date
        $startDate = \Carbon\Carbon::parse($validated['start_date']);
        $years = floor($validated['duration_years']);
        $months = ($validated['duration_years'] - $years) * 12;
        $endDate = $startDate->copy()->addYears((int) $years)->addMonths((int) $months);

        // Update election cycle
        $electionCycle->update([
            'organization_id' => $validated['organization_id'],
            'name' => $validated['name'],
            'duration_years' => $validated['duration_years'],
            'start_date' => $validated['start_date'],
            'end_date' => $endDate,
            'applicable_positions' => $validated['applicable_positions'],
        ]);

        // Sync voting procedures
        $electionCycle->votingProcedures()->sync($validated['voting_procedures'] ?? []);

        return redirect()
            ->route('organization.election-cycles.index')
            ->with('success', 'Election cycle updated successfully!');
    }

    /**
     * Remove the specified election cycle from storage.
     */
    public function destroy(ElectionCycle $electionCycle): RedirectResponse
    {
        abort_unless(auth()->user()->can('delete election cycles'), 403,
            'You do not have permission to delete election cycles.');

        // Detach voting procedures
        $electionCycle->votingProcedures()->detach();

        $electionCycle->delete();

        return redirect()
            ->route('organization.election-cycles.index')
            ->with('success', 'Election cycle deleted successfully!');
    }

    /**
     * Mark the specified election cycle as completed.
     */
    public function complete(ElectionCycle $electionCycle): RedirectResponse
    {
        abort_unless(auth()->user()->can('complete election cycles'), 403,
            'You do not have permission to complete election cycles.');

        if (!$electionCycle->isActive()) {
            return redirect()
                ->route('organization.election-cycles.index')
                ->with('error', 'Only active election cycles can be completed.');
        }

        $electionCycle->complete();

        return redirect()
            ->route('organization.election-cycles.index')
            ->with('success', 'Election cycle marked as completed!');
    }

    /**
     * Get positions for a specific organization (AJAX).
     */
    public function getPositions(Organization $organization)
    {
        $positions = LeadershipPosition::where('organization_id', $organization->id)
            ->orderBy('hierarchy_level')
            ->orderBy('title')
            ->get(['id', 'title', 'hierarchy_level']);

        return response()->json($positions);
    }
}
