<?php

namespace App\Http\Controllers\Admin\SuperAdmin;

use App\Http\Controllers\Controller;
use App\Models\JabatanFungsional;
use App\Models\JenjangJabatan;
use App\Models\UnitKerja;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;

class JabatanFungsionalController extends Controller
{
    /**
     * Display a listing of jabatan fungsional
     */
    public function index(Request $request)
    {
        $query = JabatanFungsional::query()
            ->leftJoin('unit_kerja', 'jabatan_fungsional.unit_kerja_id', '=', 'unit_kerja.id')
            ->leftJoin('pegawai', function ($join) {
                $join->on('jabatan_fungsional.id', '=', 'pegawai.jabatan_fungsional_id')
                    ->where('pegawai.status_validasi', 'disetujui');
            })
            ->select(
                'jabatan_fungsional.nama_jabatan',
                DB::raw('MIN(unit_kerja.nama_unit) as nama_unit'),
                DB::raw('MIN(jabatan_fungsional.created_at) as created_at'),
                DB::raw('COUNT(DISTINCT jabatan_fungsional.id) as jenjang_count'),
                DB::raw('COUNT(pegawai.id) as pegawai_count')
            )
            ->groupBy('jabatan_fungsional.nama_jabatan');

        if ($request->filled('search')) {
            $search = $request->search;
            $query->where(function ($q) use ($search) {
                $q->where('jabatan_fungsional.nama_jabatan', 'like', "%{$search}%")
                  ->orWhere('unit_kerja.nama_unit', 'like', "%{$search}%");
            });
        }

        $jabatan = $query->orderBy('jabatan_fungsional.nama_jabatan')
            ->paginate(15)->withQueryString();

        return view('admin.jabatan.index', compact('jabatan'));
    }

    /**
     * Display jenjang list for selected nama jabatan
     */
    public function detail(string $namaJabatan)
    {
        $jabatan = JabatanFungsional::with('unitKerja')
            ->select('jabatan_fungsional.*')
            ->withCount(['pegawai' => function ($query) {
                $query->where('status_validasi', 'disetujui');
            }])
            ->where('nama_jabatan', $namaJabatan)
            ->join('jenjang_jabatan', 'jabatan_fungsional.jenjang_jabatan_id', '=', 'jenjang_jabatan.id')
            ->orderBy('jenjang_jabatan.sort_order')
            ->paginate(15);

        abort_if($jabatan->count() === 0, 404);

        $totalPegawai = JabatanFungsional::withCount(['pegawai' => function ($query) {
                $query->where('status_validasi', 'disetujui');
            }])
            ->where('nama_jabatan', $namaJabatan)
            ->get()
            ->sum('pegawai_count');

        return view('admin.jabatan.detail', compact('jabatan', 'namaJabatan', 'totalPegawai'));
    }

    /**
     * Show the form for creating a new jabatan
     */
    public function create()
    {
        $namaJabatanList = JabatanFungsional::query()
            ->select('nama_jabatan')
            ->distinct()
            ->orderBy('nama_jabatan')
            ->pluck('nama_jabatan');
        $unitKerjaList = UnitKerja::orderBy('nama_unit')->get();
        $jenjangList = JenjangJabatan::orderBy('sort_order')->get();

        return view('admin.jabatan.create', compact('namaJabatanList', 'unitKerjaList', 'jenjangList'));
    }

    /**
     * Store a newly created jabatan
     */
    public function store(Request $request)
    {
        $request->merge([
            'nama_jabatan' => $this->normalizeNamaJabatan($request->nama_jabatan),
        ]);

        $validated = $request->validate([
            'nama_jabatan' => [
                'required',
                'string',
                'max:255',
            ],
            'kategori' => [
                'nullable',
                'string',
                'max:255',
            ],
            'jenjang_jabatan_id' => [
                'required',
                'exists:jenjang_jabatan,id',
            ],
            'unit_kerja_id' => [
                'required',
                'exists:unit_kerja,id',
            ],
        ]);

        $exists = JabatanFungsional::where('nama_jabatan', $validated['nama_jabatan'])
            ->where('jenjang_jabatan_id', $validated['jenjang_jabatan_id'])
            ->exists();

        if ($exists) {
            return back()
                ->withInput()
                ->withErrors([
                    'jenjang_jabatan_id' => 'Jenjang ini sudah tersedia untuk nama jabatan tersebut.',
                ]);
        }

        JabatanFungsional::create([
            'nama_jabatan' => $validated['nama_jabatan'],
            'jenjang_jabatan_id' => $validated['jenjang_jabatan_id'],
            'kategori' => $validated['kategori'] ?? null,
            'unit_kerja_id' => $validated['unit_kerja_id'],
        ]);

        return redirect()->route('admin.jabatan.detail', $validated['nama_jabatan'])
            ->with('success', 'Jabatan fungsional berhasil ditambahkan.');
    }

    /**
     * Show the form for editing the jabatan
     */
    public function edit(JabatanFungsional $jabatan)
    {
        $jenjangList = JenjangJabatan::orderBy('sort_order')->get();
        $unitKerjaList = UnitKerja::orderBy('nama_unit')->get();

        return view('admin.jabatan.edit', compact('jabatan', 'jenjangList', 'unitKerjaList'));
    }

    /**
     * Update the jabatan
     */
    public function update(Request $request, JabatanFungsional $jabatan)
    {
        $request->merge([
            'nama_jabatan' => $this->normalizeNamaJabatan($request->nama_jabatan),
        ]);

        $validated = $request->validate([
            'nama_jabatan' => [
                'required',
                'string',
                'max:255',
                Rule::unique('jabatan_fungsional')
                    ->where('jenjang_jabatan_id', $request->jenjang_jabatan_id)
                    ->ignore($jabatan->id),
            ],
            'jenjang_jabatan_id' => [
                'required',
                'exists:jenjang_jabatan,id',
            ],
            'kategori' => [
                'nullable',
                'string',
                'max:255',
            ],
            'unit_kerja_id' => [
                'required',
                'exists:unit_kerja,id',
            ],
        ]);

        $namaJabatanLama = $jabatan->nama_jabatan;
        $namaJabatanBaru = $validated['nama_jabatan'];

        if ($namaJabatanBaru !== $namaJabatanLama) {
            $jenjangLain = JabatanFungsional::where('nama_jabatan', $namaJabatanLama)
                ->where('id', '!=', $jabatan->id)
                ->pluck('jenjang_jabatan_id');

            $jenjangDuplikat = JabatanFungsional::where('nama_jabatan', $namaJabatanBaru)
                ->whereIn('jenjang_jabatan_id', $jenjangLain)
                ->with('jenjangJabatan')
                ->get();

            if ($jenjangDuplikat->isNotEmpty()) {
                return back()
                    ->withInput()
                    ->withErrors([
                        'nama_jabatan' => 'Nama jabatan tujuan sudah memiliki jenjang: ' .
                            $jenjangDuplikat
                                ->map(fn ($item) => $item->jenjang_label)
                                ->implode(', ') . '.',
                    ]);
            }
        }

        DB::transaction(function () use ($jabatan, $validated, $namaJabatanLama) {
            $jabatan->update($validated);

            JabatanFungsional::where('nama_jabatan', $namaJabatanLama)
                ->where('id', '!=', $jabatan->id)
                ->update([
                    'nama_jabatan' => $validated['nama_jabatan'],
                    'kategori' => $validated['kategori'] ?? null,
                    'unit_kerja_id' => $validated['unit_kerja_id'],
                ]);
        });

        return redirect()->route('admin.jabatan.detail', $namaJabatanBaru)
            ->with('success', 'Jabatan fungsional berhasil diperbarui.');
    }

    /**
     * Delete the jabatan
     */
    public function destroy(JabatanFungsional $jabatan)
    {
        if ($jabatan->pegawai()->exists()) {
            return redirect()->back()
                ->with('error', 'Tidak dapat menghapus jabatan yang masih memiliki pegawai.');
        }

        $jabatan->delete();

        return redirect()->route('admin.jabatan.index')
            ->with('success', 'Jabatan fungsional berhasil dihapus.');
    }

    private function normalizeNamaJabatan(?string $namaJabatan): string
    {
        return trim(preg_replace('/\s+/', ' ', $namaJabatan ?? ''));
    }
}
