<?php

namespace App\Http\Controllers;

use App\Exports\SalaryTemplateExport;
use App\Imports\SalaryTableImport;
use App\Models\SalaryGrade;
use App\Models\SalaryStep;
use App\Models\SalaryStructure;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Inertia\Inertia;
use Inertia\Response;
use Maatwebsite\Excel\Facades\Excel;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Throwable;

class SalaryTableController extends Controller
{
    public function index(): Response
    {
        return Inertia::render('config/salary/index', [
            'structures' => $this->structuresPayload(),
            'importResult' => null,
        ]);
    }

    private function structuresPayload(): \Illuminate\Support\Collection
    {
        return SalaryStructure::with(['grades' => fn ($q) => $q->orderBy('code'), 'grades.steps' => fn ($q) => $q->orderBy('step')])
            ->orderBy('code')
            ->get()
            ->map(fn (SalaryStructure $s) => [
                'id' => $s->id,
                'code' => $s->code,
                'name' => $s->name,
                'active' => $s->active,
                'grades' => $s->grades->map(fn (SalaryGrade $g) => [
                    'id' => $g->id,
                    'code' => $g->code,
                    'steps' => $g->steps->map(fn (SalaryStep $st) => [
                        'id' => $st->id,
                        'step' => $st->step,
                        'consolidated_amount' => (float) $st->consolidated_amount,
                        'effective_from' => $st->effective_from?->toDateString(),
                        'effective_to' => $st->effective_to?->toDateString(),
                    ]),
                ]),
            ]);
    }

    public function template(): BinaryFileResponse
    {
        return Excel::download(new SalaryTemplateExport, 'salary-table-template.xlsx');
    }

    public function import(Request $request): Response|RedirectResponse
    {
        $data = $request->validate([
            'file' => ['required', 'file', 'mimes:xlsx,xls,csv,txt', 'max:10240'],
            'effective_from' => ['nullable', 'date'],
        ]);

        $default = $data['effective_from'] ?? now()->toDateString();
        $import = new SalaryTableImport($default);

        try {
            Excel::import($import, $request->file('file'));
        } catch (Throwable $e) {
            return back()->with('error', 'Could not read the file: '.$e->getMessage());
        }

        return Inertia::render('config/salary/index', [
            'structures' => $this->structuresPayload(),
            'importResult' => [
                'created' => $import->created,
                'updated' => $import->updated,
                'skipped' => $import->skipped,
                'errors' => array_slice($import->errors, 0, 200),
                'error_count' => count($import->errors),
            ],
        ]);
    }

    public function storeStructure(Request $request): RedirectResponse
    {
        $data = $request->validate([
            'code' => ['required', 'string', 'max:32', Rule::unique('salary_structures', 'code')],
            'name' => ['nullable', 'string', 'max:255'],
        ]);
        SalaryStructure::create($data + ['active' => true]);

        return back()->with('success', 'Structure created.');
    }

    public function storeGrade(Request $request, SalaryStructure $structure): RedirectResponse
    {
        $data = $request->validate([
            'code' => [
                'required', 'string', 'max:16',
                Rule::unique('salary_grades', 'code')->where('salary_structure_id', $structure->id),
            ],
        ]);
        $structure->grades()->create($data);

        return back()->with('success', 'Grade added.');
    }

    public function storeStep(Request $request, SalaryGrade $grade): RedirectResponse
    {
        $data = $request->validate([
            'step' => ['required', 'integer', 'min:1', 'max:50'],
            'consolidated_amount' => ['required', 'numeric', 'min:0', 'max:999999999'],
            'effective_from' => ['required', 'date'],
        ]);

        $exists = SalaryStep::where('salary_grade_id', $grade->id)
            ->where('step', $data['step'])
            ->whereDate('effective_from', $data['effective_from'])
            ->exists();
        if ($exists) {
            return back()->with('error', 'A step with that number and effective date already exists.');
        }

        $grade->steps()->create($data);

        return back()->with('success', 'Step added.');
    }

    public function updateStep(Request $request, SalaryStep $step): RedirectResponse
    {
        $data = $request->validate([
            'consolidated_amount' => ['required', 'numeric', 'min:0', 'max:999999999'],
            'effective_to' => ['nullable', 'date'],
        ]);
        $step->update($data);

        return back()->with('success', 'Step updated.');
    }

    public function destroyStep(SalaryStep $step): RedirectResponse
    {
        $step->delete();

        return back()->with('success', 'Step removed.');
    }
}
