<?php

namespace App\Http\Controllers;

use App\Models\AuditCompany;
use App\Models\Director;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;

class DirectorController extends Controller
{
    /**
     * Display a listing of the directors.
     */
    public function index()
    {
        if (auth()->user()->isSuperAdmin()) {
            $directors = Director::with('auditCompany')->orderBy('english_name')->get();
        } else {
            $this->ensureAssignedAuditCompany();
            $directors = Director::orderBy('english_name')
                ->where('audit_company_id', auth()->user()->audit_company_id)
                ->get();
        }
        
        return view('directors.index', compact('directors'));
    }

    /**
     * Show the form for creating a new director.
     */
    public function create()
    {
        $auditCompanies = auth()->user()->isSuperAdmin()
            ? AuditCompany::active()->orderBy('name')->get()
            : collect();

        if (!auth()->user()->isSuperAdmin()) {
            $this->ensureAssignedAuditCompany();
        }

        return view('directors.create', compact('auditCompanies'));
    }

    /**
     * Store a newly created director in storage.
     */
    public function store(Request $request)
    {
        $validated = $this->validateDirector($request);

        Director::create([
            'english_name' => $validated['english_name'],
            'chinese_name' => $validated['chinese_name'] ?? null,
            'alias' => $validated['alias'] ?? null,
            'previous_name' => $validated['previous_name'] ?? null,
            'hkid_or_ci_number' => $validated['hkid_or_ci_number'] ?? null,
            'passport_number' => $validated['passport_number'] ?? null,
            'passport_issuing_country' => $validated['passport_issuing_country'] ?? null,
            'residential_address' => $validated['residential_address'] ?? null,
            'other_directorships' => $validated['other_directorships'] ?? null,
            'remarks' => $validated['remarks'] ?? null,
            'audit_company_id' => $this->resolveAuditCompanyId($validated),
        ]);

        return redirect()->route('directors.index')
            ->with('success', 'Director created successfully.');
    }

    /**
     * Display the specified director.
     */
    public function show(Director $director)
    {
        $this->authorizeDirectorAccess($director);

        $director->load([
            'auditCompany',
            'directorAppointments' => function ($query) use ($director) {
                $query->whereHas('company', function ($companyQuery) use ($director) {
                    $companyQuery->where('audit_company_id', $director->audit_company_id);
                })->with('company');
            },
        ]);
        
        return view('directors.show', compact('director'));
    }

    /**
     * Show the form for editing the specified director.
     */
    public function edit(Director $director)
    {
        $this->authorizeDirectorAccess($director);

        $auditCompanies = auth()->user()->isSuperAdmin()
            ? AuditCompany::active()->orderBy('name')->get()
            : collect();

        return view('directors.edit', compact('director', 'auditCompanies'));
    }

    /**
     * Update the specified director in storage.
     */
    public function update(Request $request, Director $director)
    {
        $this->authorizeDirectorAccess($director);

        $validated = $this->validateDirector($request);
        $newAuditCompanyId = $this->resolveAuditCompanyId($validated);

        if (
            auth()->user()->isSuperAdmin() &&
            $director->audit_company_id !== $newAuditCompanyId &&
            $director->directorAppointments()->exists()
        ) {
            return back()
                ->withErrors([
                    'audit_company_id' => 'A director with existing appointments cannot be moved to a different audit company.',
                ])
                ->withInput();
        }

        $director->update([
            'english_name' => $validated['english_name'],
            'chinese_name' => $validated['chinese_name'] ?? null,
            'alias' => $validated['alias'] ?? null,
            'previous_name' => $validated['previous_name'] ?? null,
            'hkid_or_ci_number' => $validated['hkid_or_ci_number'] ?? null,
            'passport_number' => $validated['passport_number'] ?? null,
            'passport_issuing_country' => $validated['passport_issuing_country'] ?? null,
            'residential_address' => $validated['residential_address'] ?? null,
            'other_directorships' => $validated['other_directorships'] ?? null,
            'remarks' => $validated['remarks'] ?? null,
            'audit_company_id' => $newAuditCompanyId,
        ]);

        return redirect()->route('directors.index')
            ->with('success', 'Director updated successfully.');
    }

    /**
     * Remove the specified director from storage.
     */
    public function destroy(Director $director)
    {
        $this->authorizeDirectorAccess($director);

        $director->delete();

        return redirect()->route('directors.index')
            ->with('success', 'Director deleted successfully.');
    }

    private function validateDirector(Request $request): array
    {
        $rules = [
            'english_name' => ['required', 'string', 'max:255'],
            'chinese_name' => ['nullable', 'string', 'max:255'],
            'alias' => ['nullable', 'string', 'max:255'],
            'previous_name' => ['nullable', 'string', 'max:255'],
            'hkid_or_ci_number' => ['nullable', 'string', 'max:255'],
            'passport_number' => ['nullable', 'string', 'max:255'],
            'passport_issuing_country' => ['nullable', 'string', 'max:255'],
            'residential_address' => ['nullable', 'string'],
            'other_directorships' => ['nullable', 'string'],
            'remarks' => ['nullable', 'string'],
        ];

        if (auth()->user()->isSuperAdmin()) {
            $rules['audit_company_id'] = [
                'required',
                Rule::exists('audit_companies', 'id')->where(function ($query) {
                    $query->whereNull('deleted_at');
                }),
            ];
        } else {
            $this->ensureAssignedAuditCompany();
        }

        return $request->validate($rules);
    }

    private function resolveAuditCompanyId(array $validated): ?int
    {
        if (auth()->user()->isSuperAdmin()) {
            return (int) $validated['audit_company_id'];
        }

        return auth()->user()->audit_company_id;
    }

    private function ensureAssignedAuditCompany(): void
    {
        if (!auth()->user()->isSuperAdmin() && !auth()->user()->audit_company_id) {
            abort(403, 'Your account must be assigned to an audit company before managing directors.');
        }
    }

    private function authorizeDirectorAccess(Director $director): void
    {
        if (auth()->user()->isSuperAdmin()) {
            return;
        }

        $this->ensureAssignedAuditCompany();

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