<?php

namespace App\Http\Controllers;

use App\Models\Company;
use App\Models\Director;
use App\Models\DirectorAppointment;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;

class DirectorAppointmentController extends Controller
{
    /**
     * Display a listing of appointments for a company.
     */
    public function index(Company $company)
    {
        $this->authorizeCompanyAccess($company);

        $appointments = $company->directorAppointments()
            ->whereHas('director', function ($query) use ($company) {
                $query->where('audit_company_id', $company->audit_company_id);
            })
            ->with('director')
            ->orderBy('date_of_appointment', 'desc')
            ->get();
        
        return view('appointments.index', compact('company', 'appointments'));
    }

    /**
     * Show the form for creating a new appointment.
     */
    public function create(Company $company)
    {
        $this->authorizeCompanyAccess($company);

        $directors = $this->availableDirectors($company);
        
        return view('appointments.create', compact('company', 'directors'));
    }

    /**
     * Store a newly created appointment in storage.
     */
    public function store(Request $request, Company $company)
    {
        $this->authorizeCompanyAccess($company);

        $validated = $request->validate([
            'director_id' => [
                'required',
                Rule::exists('directors', 'id')->where(function ($query) use ($company) {
                    $query->where('audit_company_id', $company->audit_company_id);
                }),
            ],
            'date_of_appointment' => 'required|date',
            'date_of_ceasing' => 'nullable|date|after_or_equal:date_of_appointment',
            'remarks' => 'nullable|string',
        ]);

        $company->directorAppointments()->create($validated);

        return redirect()
            ->route('companies.appointments.index', $company)
            ->with('success', 'Director appointment created successfully.');
    }

    /**
     * Show the form for editing the specified appointment.
     */
    public function edit(Company $company, DirectorAppointment $appointment)
    {
        $this->authorizeCompanyAccess($company);
        $this->ensureAppointmentBelongsToCompany($company, $appointment);

        $directors = $this->availableDirectors($company);
        
        return view('appointments.edit', compact('company', 'appointment', 'directors'));
    }

    /**
     * Update the specified appointment in storage.
     */
    public function update(Request $request, Company $company, DirectorAppointment $appointment)
    {
        $this->authorizeCompanyAccess($company);
        $this->ensureAppointmentBelongsToCompany($company, $appointment);

        $validated = $request->validate([
            'director_id' => [
                'required',
                Rule::exists('directors', 'id')->where(function ($query) use ($company) {
                    $query->where('audit_company_id', $company->audit_company_id);
                }),
            ],
            'date_of_appointment' => 'required|date',
            'date_of_ceasing' => 'nullable|date|after_or_equal:date_of_appointment',
            'remarks' => 'nullable|string',
        ]);

        $appointment->update($validated);

        return redirect()
            ->route('companies.appointments.index', $company)
            ->with('success', 'Director appointment updated successfully.');
    }

    /**
     * Remove the specified appointment from storage.
     */
    public function destroy(Company $company, DirectorAppointment $appointment)
    {
        $this->authorizeCompanyAccess($company);
        $this->ensureAppointmentBelongsToCompany($company, $appointment);

        $appointment->delete();

        return redirect()
            ->route('companies.appointments.index', $company)
            ->with('success', 'Director appointment deleted successfully.');
    }

    private function authorizeCompanyAccess(Company $company): void
    {
        if (auth()->user()->isSuperAdmin()) {
            return;
        }

        if (!auth()->user()->audit_company_id) {
            abort(403, 'Your account must be assigned to an audit company before managing appointments.');
        }

        if ($company->audit_company_id !== auth()->user()->audit_company_id) {
            abort(403, 'You do not have permission to access this company.');
        }
    }

    private function ensureAppointmentBelongsToCompany(Company $company, DirectorAppointment $appointment): void
    {
        if ($appointment->company_id !== $company->id) {
            abort(404);
        }
    }

    private function availableDirectors(Company $company)
    {
        return Director::where('audit_company_id', $company->audit_company_id)
            ->orderBy('english_name')
            ->get();
    }
}
