<?php

namespace App\Http\Controllers;

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

class CompanyController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index()
    {
        if (auth()->user()->isSuperAdmin()) {
            $companies = Company::with('auditCompany')->latest()->paginate(10);
        } else {
            $this->ensureAssignedAuditCompany();

            $companies = Company::where('audit_company_id', auth()->user()->audit_company_id)
                ->with('auditCompany')
                ->latest()
                ->paginate(10);
        }
        
        return view('companies.index', compact('companies'));
    }

    /**
     * Show the form for creating a new company.
     */
    public function create()
    {
        $auditCompanies = collect();

        if (auth()->user()->isSuperAdmin()) {
            $auditCompanies = AuditCompany::active()->orderBy('name')->get();
        } else {
            $this->ensureAssignedAuditCompany();
        }

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

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

        Company::create([
            'company_name' => $validated['company_name'],
            'ci_number' => $validated['ci_number'],
            'date_of_incorporation' => $validated['date_of_incorporation'],
            'audit_company_id' => $this->resolveAuditCompanyId($validated),
        ]);

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

    /**
     * Display the specified resource.
     */
    public function show(Company $company)
    {
        $this->authorizeCompanyAccess($company);

        $company->load([
            'auditCompany',
            'directors' => function ($query) use ($company) {
                $query->where('audit_company_id', $company->audit_company_id);
            },
            'directorAppointments' => function ($query) use ($company) {
                $query->whereHas('director', function ($directorQuery) use ($company) {
                    $directorQuery->where('audit_company_id', $company->audit_company_id);
                })->with('director');
            },
        ]);

        return view('companies.show', compact('company'));
    }

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

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

        return view('companies.edit', compact('company', 'auditCompanies'));
    }

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

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

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

        $company->update([
            'company_name' => $validated['company_name'],
            'ci_number' => $validated['ci_number'],
            'date_of_incorporation' => $validated['date_of_incorporation'],
            'audit_company_id' => $newAuditCompanyId,
        ]);

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

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

        $company->delete();

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

    private function validateCompany(Request $request): array
    {
        $rules = [
            'company_name' => ['required', 'string', 'max:255'],
            'ci_number' => ['required', 'string', 'max:255'],
            'date_of_incorporation' => ['required', 'date'],
        ];

        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 companies.');
        }
    }

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

        $this->ensureAssignedAuditCompany();

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