<?php

namespace App\Http\Controllers\Company\Payroll;

use App\Http\Controllers\Controller;
use App\Models\{
    Employee, PayrollBranch, PayrollDepartment, PayrollDesignation,
    PayrollProject, Setting
};
use App\Services\BankTransferLetterService;
use App\Support\{EmployeeFormOptions, PayrollVoucherOptions};
use Illuminate\Http\Request;

class BankTransferLetterController extends Controller
{
    public function __construct(private BankTransferLetterService $service) {}

    public function index(Request $request)
    {
        $this->ensurePayrollModule();
        $this->gate('view');

        $cid = auth()->user()->company_id;
        $filters = $this->service->normalizeFilters($request->all());
        $hasActiveFilters = $this->service->hasActiveFilters($filters);
        $rows = $hasActiveFilters ? $this->service->employeeRows($cid, $filters) : collect();

        return view('payroll.bank-transfer-letter.index', array_merge(
            compact('filters', 'rows', 'hasActiveFilters'),
            $this->filterOptions($cid, $filters),
        ));
    }

    public function print(Request $request)
    {
        $this->ensurePayrollModule();
        $this->gate('view');

        $cid = auth()->user()->company_id;
        $filters = $this->service->normalizeFilters($request->all());
        $employeeIds = array_values(array_unique(array_filter(array_map('intval', (array) $request->input('employees', [])))));

        if ($employeeIds === []) {
            return back()->withErrors(['employees' => 'Select at least one employee to create a transfer letter.']);
        }

        $letter = $this->service->buildLetter($cid, $filters, $employeeIds);
        $company = auth()->user()->company;

        if ($letter['employee_count'] === 0) {
            abort(404, 'No employees found for the selected transfer letter.');
        }

        return view('payroll.bank-transfer-letter.print', compact('letter', 'company'));
    }

    private function filterOptions(int $companyId, array $filters): array
    {
        $lookup = fn ($model) => $model::withoutGlobalScopes()
            ->where('company_id', $companyId)
            ->where('is_active', true)
            ->orderBy('name')
            ->pluck('name', 'name');

        $religions = Employee::withoutGlobalScopes()
            ->where('company_id', $companyId)
            ->whereNull('deleted_at')
            ->whereNotNull('religion')
            ->where('religion', '!=', '')
            ->distinct()
            ->orderBy('religion')
            ->pluck('religion', 'religion');

        if ($religions->isEmpty()) {
            $religions = collect(EmployeeFormOptions::religions());
        }

        $employees = Employee::withoutGlobalScopes()
            ->where('company_id', $companyId)
            ->whereNull('deleted_at')
            ->where('is_active', true)
            ->where('terminated_employee', false)
            ->orderBy('code')
            ->orderBy('name')
            ->get(['id', 'code', 'name', 'display_name']);

        return [
            'salaryMonths'         => $this->service->salaryMonthOptions($companyId),
            'voucherTypes'         => PayrollVoucherOptions::types(),
            'voucherNumbers'       => $this->service->voucherNumberOptions($companyId, $filters),
            'departments'          => $lookup(PayrollDepartment::class),
            'designations'         => $lookup(PayrollDesignation::class),
            'projects'             => $lookup(PayrollProject::class),
            'branches'             => $lookup(PayrollBranch::class),
            'religions'            => $religions,
            'salaryPaymentMethods' => EmployeeFormOptions::salaryPaymentMethods(),
            'employees'            => $employees->mapWithKeys(fn (Employee $emp) => [
                $emp->id => trim(($emp->code ? $emp->code . ' — ' : '') . ($emp->display_name ?: $emp->name)),
            ]),
        ];
    }

    private function ensurePayrollModule(): void
    {
        if (Setting::get(auth()->user()->company_id, 'use_payroll_module', '0') !== '1') {
            abort(404);
        }
    }

    private function gate(string $action = 'view'): void
    {
        if (!auth()->user()->hasPermission('payroll', $action)) {
            abort(403);
        }
    }
}
