<?php

namespace App\Http\Controllers\Company\Payroll;

use App\Http\Controllers\Controller;
use App\Models\{
    AuditLog, PayrollBranch, PayrollDepartment, PayrollDesignation, PayrollProject, Setting
};
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;

class PayrollLookupController extends Controller
{
    private function configs(): array
    {
        return [
            'departments' => [
                'model'    => PayrollDepartment::class,
                'title'    => 'Departments',
                'singular' => 'Department',
                'icon'     => 'bi-diagram-3',
                'route'    => 'payroll.departments',
            ],
            'designations' => [
                'model'    => PayrollDesignation::class,
                'title'    => 'Designations',
                'singular' => 'Designation',
                'icon'     => 'bi-person-badge',
                'route'    => 'payroll.designations',
            ],
            'projects' => [
                'model'    => PayrollProject::class,
                'title'    => 'Projects',
                'singular' => 'Project',
                'icon'     => 'bi-kanban',
                'route'    => 'payroll.projects',
            ],
            'branches' => [
                'model'    => PayrollBranch::class,
                'title'    => 'Branches',
                'singular' => 'Branch',
                'icon'     => 'bi-building',
                'route'    => 'payroll.branches',
            ],
        ];
    }

    private function config(string $lookup): array
    {
        $configs = $this->configs();
        if (!isset($configs[$lookup])) {
            abort(404);
        }

        return $configs[$lookup];
    }

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

        $config = $this->config($lookup);
        $model = $config['model'];
        $cid = auth()->user()->company_id;

        $query = $model::withoutGlobalScopes()->where('company_id', $cid);
        if ($request->filled('search')) {
            $search = $request->search;
            $query->where('name', 'like', "%{$search}%");
        }
        if ($request->filled('status')) {
            $query->where('is_active', $request->status === 'active');
        }

        $records = $query->orderBy('name')->paginate(25)->withQueryString();
        $stats = [
            'total'  => $model::withoutGlobalScopes()->where('company_id', $cid)->count(),
            'active' => $model::withoutGlobalScopes()->where('company_id', $cid)->where('is_active', true)->count(),
        ];

        return view('payroll.lookups.index', array_merge(compact('records', 'stats', 'lookup'), $config));
    }

    public function store(Request $request, string $lookup)
    {
        $this->ensurePayrollModule();
        $this->gate('edit');

        $config = $this->config($lookup);
        $model = $config['model'];
        $cid = auth()->user()->company_id;
        $table = (new $model())->getTable();

        $validated = $request->validate([
            'name' => [
                'required', 'string', 'max:120',
                Rule::unique($table)->where(fn ($q) => $q->where('company_id', $cid)),
            ],
        ]);

        $record = $model::withoutGlobalScopes()->create(array_merge($validated, [
            'company_id' => $cid,
            'is_active'  => true,
        ]));

        AuditLog::record('create', $lookup, (string) $record->id, null, ['name' => $record->name], "{$config['singular']} created: {$record->name}");

        return back()->with('success', "{$config['singular']} '{$record->name}' created.");
    }

    public function update(Request $request, string $lookup, int $record)
    {
        $this->ensurePayrollModule();
        $this->gate('edit');

        $config = $this->config($lookup);
        $item = $this->findRecord($lookup, $record);
        $table = $item->getTable();
        $cid = auth()->user()->company_id;

        $validated = $request->validate([
            'name' => [
                'required', 'string', 'max:120',
                Rule::unique($table)->where(fn ($q) => $q->where('company_id', $cid))->ignore($item->id),
            ],
            'is_active' => 'boolean',
        ]);

        $validated['is_active'] = $request->boolean('is_active');
        $item->update($validated);

        AuditLog::record('update', $lookup, (string) $item->id, null, $validated, "{$config['singular']} updated: {$item->name}");

        return back()->with('success', "{$config['singular']} '{$item->name}' updated.");
    }

    public function toggle(string $lookup, int $record)
    {
        $this->ensurePayrollModule();
        $this->gate('edit');

        $config = $this->config($lookup);
        $item = $this->findRecord($lookup, $record);
        $item->update(['is_active' => !$item->is_active]);

        return back()->with('success', "{$config['singular']} marked as " . ($item->is_active ? 'active' : 'inactive') . '.');
    }

    public function destroy(string $lookup, int $record)
    {
        $this->ensurePayrollModule();
        $this->gate('edit');

        $config = $this->config($lookup);
        $item = $this->findRecord($lookup, $record);
        $name = $item->name;
        $id = $item->id;
        $item->delete();

        AuditLog::record('delete', $lookup, (string) $id, null, null, "{$config['singular']} deleted: {$name}");

        return back()->with('success', "{$config['singular']} '{$name}' deleted.");
    }

    private function findRecord(string $lookup, int $id): Model
    {
        $config = $this->config($lookup);
        $model = $config['model'];

        return $model::withoutGlobalScopes()
            ->where('company_id', auth()->user()->company_id)
            ->findOrFail($id);
    }

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

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