<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\User;
use App\Models\Departamento;
use App\Models\Gerencia;
use App\Models\AreaTrabajo;
use App\Models\ReportePersonal;
use App\Models\AuditLog;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules;

class UserController extends Controller
{
    public function index(Request $request)
    {
        $query = User::with(['departamento.gerencia.direccion', 'gerenciaRel'])->orderBy('name');

        if ($request->filled('search')) {
            $search = $request->search;
            // FIX-5: Escapar caracteres wildcard de LIKE
            $escapedSearch = str_replace(['%', '_'], ['\\%', '\\_'], $search);
            $query->where(function ($q) use ($escapedSearch) {
                $q->where('name', 'like', "%{$escapedSearch}%")
                  ->orWhere('apellido', 'like', "%{$escapedSearch}%")
                  ->orWhere('cedula', 'like', "%{$escapedSearch}%");
            });
        }

        $users = $query->paginate(15);
        return view('admin.users.index', compact('users'));
    }

    public function create()
    {
        $departamentos = Departamento::with('gerencia.direccion')->where('activo', true)->orderBy('nombre')->get();
        $gerencias = Gerencia::with('direccion')->where('activo', true)->orderBy('nombre')->get();
        $areasTrabajo = AreaTrabajo::orderBy('nombre')->get();
        $cargos = ['Usuario', 'Admin', 'Jefe de Área', 'Técnico'];
        return view('admin.users.create', compact('departamentos', 'gerencias', 'cargos', 'areasTrabajo'));
    }

    public function store(Request $request)
    {
        $request->validate([
            'cedula'          => ['required', 'string', 'max:20', 'unique:pgsql.users,cedula'],
            'username'        => ['required', 'string', 'max:50', 'unique:pgsql.users,username'],
            'name'            => ['required', 'string', 'max:255'],
            'apellido'        => ['nullable', 'string', 'max:255'],
            'email'           => ['nullable', 'string', 'lowercase', 'email', 'max:255', 'unique:pgsql.users,email'],
            'cargo'           => ['required', 'string'],
            'departamento_id' => [
                Rule::requiredIf(fn() => in_array($request->cargo, ['Técnico', 'Jefe de Área'])),
                'nullable',
                'exists:pgsql.departamentos,id'
            ],
            'gerencia_id'     => ['nullable', 'required_without:departamento_id', 'exists:pgsql.cat_gerencias,id'],
            'area_trabajo_id' => ['nullable', 'exists:pgsql.area_trabajos,id'],
            // La contraseña es opcional en el formulario; si no se provee,
            // se utilizará la cédula como contraseña por defecto.
            'password'        => ['nullable', 'confirmed', 'min:8'],
        ], [
            'departamento_id.required' => 'El Departamento es obligatorio para los roles Técnico y Jefe de Área.',
            'password.min'       => 'La contraseña debe tener al menos 8 caracteres.',
            'password.confirmed' => 'Las contraseñas ingresadas no coinciden.',
        ]);

        // Si el admin no definió contraseña, se utiliza la cédula por defecto.
        if ($request->filled('password')) {
            $passwordFinal = $request->password;
        } else {
            $passwordFinal = $request->cedula;
        }

        $user = User::create([
            'cedula'          => $request->cedula,
            'username'        => $request->username,
            'name'            => $request->name,
            'apellido'        => $request->apellido,
            'email'           => $request->email,
            'cargo'           => $request->cargo,
            'departamento_id' => $request->departamento_id,
            'gerencia_id'     => $request->gerencia_id,
            'area_trabajo_id' => $request->area_trabajo_id,
            'password'        => Hash::make($passwordFinal),
        ]);

        // FIX-7: Registrar auditoría de creación de usuario
        AuditLog::registrar('usuario_creado', $user, [], [
            'cedula' => $user->cedula,
            'cargo'  => $user->cargo,
        ]);

        $mensaje = 'Usuario registrado con éxito.';

        return redirect()->route('admin.users.index')->with('success', $mensaje);
    }

    public function show(User $user)
    {
        $user->load(['departamento.gerencia.direccion', 'gerenciaRel']);
        return view('admin.users.show', compact('user'));
    }

    public function edit(User $user)
    {
        $departamentos = Departamento::with('gerencia.direccion')->where('activo', true)->orderBy('nombre')->get();
        $gerencias = Gerencia::where('activo', true)->orderBy('nombre')->get();
        $areasTrabajo = AreaTrabajo::orderBy('nombre')->get();
        $cargos = ['Usuario', 'Admin', 'Jefe de Área', 'Técnico'];

        return view('admin.users.edit', compact('user', 'departamentos', 'gerencias', 'cargos', 'areasTrabajo'));
    }

    public function update(Request $request, User $user)
    {
        $rules = [
            'cedula'          => ['required', 'string', 'max:20', 'unique:pgsql.users,cedula,' . $user->id],
            'username'        => ['required', 'string', 'max:50', 'unique:pgsql.users,username,' . $user->id],
            'name'            => ['required', 'string', 'max:255'],
            'apellido'        => ['nullable', 'string', 'max:255'],
            'email'           => ['nullable', 'string', 'lowercase', 'email', 'max:255', 'unique:pgsql.users,email,' . $user->id],
            'cargo'           => ['required', 'string'],
            'departamento_id' => [
                Rule::requiredIf(fn() => in_array($request->cargo, ['Técnico', 'Jefe de Área'])),
                'nullable',
                'exists:pgsql.departamentos,id'
            ],
            'gerencia_id'     => ['nullable', 'required_without:departamento_id', 'exists:pgsql.cat_gerencias,id'],
            'area_trabajo_id' => ['nullable', 'exists:pgsql.area_trabajos,id'],
        ];

        if ($request->filled('password')) {
            // C-05: Mínimo 8 caracteres al actualizar también.
            $rules['password'] = ['required', 'confirmed', 'min:8'];
        }

        $request->validate($rules, [
            'departamento_id.required' => 'El Departamento es obligatorio para los roles Técnico y Jefe de Área.',
            'password.min' => 'La contraseña debe tener al menos 8 caracteres.',
            'password.confirmed' => 'Las contraseñas ingresadas no coinciden.',
        ]);

        $data = [
            'cedula'          => $request->cedula,
            'username'        => $request->username,
            'name'            => $request->name,
            'apellido'        => $request->apellido,
            'email'           => $request->email,
            'cargo'           => $request->cargo,
            'departamento_id' => $request->departamento_id,
            'gerencia_id'     => $request->gerencia_id,
            'area_trabajo_id' => $request->area_trabajo_id,
        ];

        if ($request->filled('password')) {
            $data['password'] = Hash::make($request->password);
        }

        // FIX-7: Capturar datos anteriores para auditoría
        $datosAnteriores = $user->only(array_keys($data));

        $user->update($data);

        // FIX-7: Registrar auditoría de actualización
        AuditLog::registrar('usuario_actualizado', $user, $datosAnteriores, [
            'campos_modificados' => array_keys(array_diff_assoc($data, $datosAnteriores)),
        ]);

        return redirect()->route('admin.users.index')->with('success', 'Información de usuario actualizada.');
    }

    public function destroy(User $user)
    {
        if (auth()->id() === $user->id) {
            return redirect()->route('admin.users.index')->with('error', 'No puedes eliminar tu propia cuenta.');
        }

        if ($user->solicitudes()->count() > 0) {
            return redirect()->route('admin.users.index')->with('error', 'No se puede eliminar el usuario porque tiene solicitudes vinculadas.');
        }

        // FIX-7: Registrar auditoría antes de eliminar
        AuditLog::registrar('usuario_eliminado', $user, [
            'cedula' => $user->cedula,
            'nombre' => trim($user->name . ' ' . $user->apellido),
            'cargo'  => $user->cargo,
        ]);

        $user->delete();
        return redirect()->route('admin.users.index')->with('success', 'Usuario eliminado satisfactoriamente.');
    }

    /**
     * API: Busca un empleado en la vista de RRHH por cédula y
     * resuelve los IDs locales de gerencia y área de trabajo.
     */
    public function buscarPorCedula(Request $request)
    {
        $cedula = trim($request->input('cedula'));

        if (!$cedula) {
            return response()->json(['encontrado' => false, 'mensaje' => 'Cédula requerida.'], 422);
        }

        try {
            $empleado = ReportePersonal::porCedula($cedula);
        } catch (\Exception $e) {
            return response()->json([
                'encontrado' => false,
                'mensaje'    => 'Error de comunicación con el sistema de RRHH. Por favor, intente de nuevo más tarde.',
            ], 500);
        }

        if (!$empleado) {
            return response()->json(['encontrado' => false, 'mensaje' => 'No se encontró ningún empleado con esa cédula.']);
        }

        // Matching por código en tablas locales
        // codestorg de RRHH tiene 12 dígitos (ej: 000000003300),
        // cat_gerencias usa 4 dígitos (ej: 3300). Extraemos los últimos 4.
        $codigoGerencia = substr(trim($empleado->codestorg), -4);
        $gerenciaId     = Gerencia::where('codigo', $codigoGerencia)->value('id');
        $areaTrabajId   = AreaTrabajo::where('codigo', $empleado->codubifis)->value('id');

        return response()->json([
            'encontrado'       => true,
            'nomper'           => $empleado->nomper,
            'apeper'           => $empleado->apeper,
            'codestorg'        => $empleado->codestorg,
            'denestorg'        => $empleado->denestorg,
            'codubifis'        => $empleado->codubifis,
            'denubifis'        => $empleado->denubifis,
            'gerencia_id'      => $gerenciaId,
            'area_trabajo_id'  => $areaTrabajId,
        ]);
    }
}
