<?php

namespace App\Controllers;

use App\Models\Area;
use App\Models\PersonType;
use App\Models\Role;
use App\Models\RoleUser;
use App\Models\User;
use App\Models\UserComunity;
use App\Models\UserDirectorData;
use App\Models\UserPersonType;
use App\Models\UserUgel;
use App\Services\AreaService;
use App\Services\PasswordValidator;
use App\Services\PersonTypeService;
use App\Services\UserService;
use Config\Database;
use Exception;

class UserController extends BaseController
{
    protected AreaService $areaService;
    protected PersonTypeService $personTypeService;
    protected UserService $userService;

    public function __construct()
    {
        if (session_status() === PHP_SESSION_NONE) {
            session_start();
        }

        $this->areaService = new AreaService();
        $this->personTypeService = new PersonTypeService();
        $this->userService = new UserService();
    }

    public function usersUgel()
    {
        $users = $this->userService->getAllUsersUgel();
        $this->render('users/users-ugel-index', ['users' => $users]);
    }

    public function usersComunity()
    {
        $users = UserComunity::getActives();
        $this->render('users/users-comunity-index', ['users' => $users]);
    }

    public function createUserUgel()
    {
        $areas = $this->areaService->getAreasWithRelations();
        $this->render('users/create-ugel-user', ['areas' => $areas]);
    }

    public function createUserComunity()
    {
        $personTypes = PersonType::getActives();
        $this->render('users/create-comunity-user', ['personTypes' => $personTypes]);
    }

    public function editUserUgel($id)
    {
        $userUgel = UserUgel::find($id);

        if (!$userUgel) {
            $_SESSION['message'] = "Usuario no encontrado.";
            $_SESSION['message_type'] = "danger";
            header("Location: " . BASE_HEADER . "ugel-users");
            exit;
        }

        $user = $userUgel->user();
        $areas = $this->areaService->getAreasWithRelations();

        $this->render('users/edit-ugel-user', ['areas' => $areas, 'user' => $user, 'userUgel' => $userUgel]);
    }

    public function editUserComunity($id)
    {
        $userComunity = UserComunity::find($id);

        if (!$userComunity) {
            $_SESSION['message'] = "Usuario no encontrado.";
            $_SESSION['message_type'] = "danger";
            header("Location: " . BASE_HEADER . "comunity-users");
            exit;
        }

        $user = $userComunity->user();
        $personTypes = PersonType::getActives();
        $userPersonTypeIds = $userComunity->personTypeIds();

        $directorData = null;
        $director_person_type = PersonType::findBy('description', 'DIRECTOR');
        if (in_array($director_person_type->id, $userPersonTypeIds)) {
            $directorData = UserDirectorData::findBy('comunity_user_id', $userComunity->id);
        }


        $this->render('users/edit-comunity-user', [
            'user' => $user,
            'userComunity' => $userComunity,
            'personTypes' => $personTypes,
            'userPersonTypeIds' => $userPersonTypeIds,
            'directorData' => $directorData
        ]);
    }

    public function storeUserUgel()
    {
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {

            $name = $_POST['name'] ?? '';
            $paternal_surname = $_POST['paternal_surname'] ?? '';
            $maternal_surname = $_POST['maternal_surname'] ?? '';
            $dni = $_POST['dni'] ?? '';
            $birthdate = $_POST['birthdate'] ?? '';
            $age = $_POST['age'] ?? '';
            $phone = isset($_POST['phone']) && $_POST['phone'] !== '' ? $_POST['phone'] : null;
            $email = isset($_POST['email']) && $_POST['email'] !== '' ? $_POST['email'] : null;
            $address = isset($_POST['address']) && $_POST['address'] !== '' ? $_POST['address'] : null;
            $groupId = $_POST['group_id'] ?? '';
            $subgroupId = !empty($_POST['subgroup_id']) ? $_POST['subgroup_id'] : null;
            $position = $_POST['position'] ?? '';
            $files_charge = $_POST['files_charge'] ?? 0;
            $username = $_POST['username'] ?? '';
            $password = $_POST['password'] ?? '';
            $role = $_POST['role'] ?? 'UGEL';
            $active = 1;

            $errors = PasswordValidator::validate($password);

            if (!empty($errors)) {
                $_SESSION['message'] = implode("<br>", $errors);
                $_SESSION['message_type'] = "danger";
                header("Location: " . BASE_HEADER . "users/create-ugel-user");
                exit;
            }

            try {
                $db = Database::getConnection();
                $db->beginTransaction();

                $user = new User();
                $user->username = $username;
                $user->password = password_hash($password, PASSWORD_BCRYPT);
                $user->role = $role;
                $userId = $user->save();

                if (!$userId) {
                    $_SESSION['message'] = "Error al guardar el usuario.";
                    $_SESSION['message_type'] = "danger";
                    header("Location: " . BASE_HEADER . "users/create-ugel-user");
                    exit;
                }

                $ugelUser = new UserUgel();
                $ugelUser->name = $name;
                $ugelUser->paternal_surname = $paternal_surname;
                $ugelUser->maternal_surname = $maternal_surname;
                $ugelUser->dni = $dni;
                $ugelUser->group_id = $groupId;
                $ugelUser->subgroup_id = $subgroupId;
                $ugelUser->position = $position;
                $ugelUser->files_charge = $files_charge;
                $ugelUser->birthdate = $birthdate;
                $ugelUser->age = $age;
                $ugelUser->phone = $phone;
                $ugelUser->email = $email;
                $ugelUser->address = $address;
                $ugelUser->user_id = $userId;
                $ugelUser->active = $active;
                $ugelUser->save();

                $roleUgel = Role::findBy('name', 'UGEL');
                $roleComunity = Role::findBy('name', 'COMUNITY');

                $roleUserUgel = new RoleUser();
                $roleUserUgel->user_id = $userId;
                $roleUserUgel->role_id = $roleUgel->id;
                $roleUserUgel->save();

                if ($roleComunity) {
                    $roleUserComunity = new RoleUser();
                    $roleUserComunity->user_id = $userId;
                    $roleUserComunity->role_id = $roleComunity->id;
                    $roleUserComunity->save();
                }

                $db->commit();

                $_SESSION['message'] = "¡Usuario UGEL creado exitosamente!";
                $_SESSION['message_type'] = "success";
                header("Location: " . BASE_HEADER . "ugel-users");
                exit;
            } catch (Exception $e) {
                $db->rollBack();
                $_SESSION['message'] = "Error: " . $e->getMessage();
                $_SESSION['message_type'] = "danger";
                header("Location: " . BASE_HEADER . "users/create-ugel-user");
                exit;
            }
        }
    }

    public function storeUserComunity()
    {

        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $userService = new UserService();

            $password = $_POST['password'] ?? '';
            $errors = PasswordValidator::validate($password);

            if (!empty($errors)) {
                $_SESSION['message'] = implode("<br>", $errors);
                $_SESSION['message_type'] = "danger";
                header("Location: " . BASE_HEADER . "users/create-comunity-user");
                exit;
            }

            try {
                $userService->createComunityUser($_POST);

                $_SESSION['message'] = "¡Usuario Comunidad creado exitosamente!";
                $_SESSION['message_type'] = "success";
                header("Location: " . BASE_HEADER . "comunity-users");
                exit;
            } catch (Exception $e) {
                $_SESSION['message'] = "Error: " . $e->getMessage();
                $_SESSION['message_type'] = "danger";
                header("Location: " . BASE_HEADER . "users/create-comunity-user");
                exit;
            }
        }
    }


    public function updateUserUgel($id)
    {
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $userUgel = UserUgel::find($id);

            if (!$userUgel) {
                $_SESSION['message'] = "Usuario no encontrado.";
                $_SESSION['message_type'] = "danger";
                header("Location: " . BASE_HEADER . "ugel-users");
                exit;
            }

            $user = User::find($userUgel->user_id);
            if (!$user) {
                $_SESSION['message'] = "Error al encontrar el usuario.";
                $_SESSION['message_type'] = "danger";
                header("Location: " . BASE_HEADER . "ugel-users");
                exit;
            }

            $user->username = trim($_POST['username']);

            if (!empty($_POST['password'])) {

                $errors = PasswordValidator::validate($_POST['password']);

                if (!empty($errors)) {
                    $_SESSION['message'] = implode("<br>", $errors);
                    $_SESSION['message_type'] = "danger";
                    header("Location: " . BASE_HEADER . "ugel-users/{$id}/edit");
                    exit;
                }

                $user->password = password_hash($_POST['password'], PASSWORD_BCRYPT);
            }

            $user->save();

            $userUgel->group_id = $_POST['group_id'];
            $userUgel->subgroup_id = !empty($_POST['subgroup_id']) ? $_POST['subgroup_id'] : null;
            $userUgel->name = $_POST['name'];
            $userUgel->paternal_surname = $_POST['paternal_surname'];
            $userUgel->maternal_surname = $_POST['maternal_surname'];
            $userUgel->dni = $_POST['dni'];
            $userUgel->birthdate = $_POST['birthdate'];
            $userUgel->age = $_POST['age'];
            $userUgel->phone = isset($_POST['phone']) && $_POST['phone'] !== '' ? $_POST['phone'] : null;
            $userUgel->email = isset($_POST['email']) && $_POST['email'] !== '' ? $_POST['email'] : null;
            $userUgel->address = isset($_POST['address']) && $_POST['address'] !== '' ? $_POST['address'] : null;
            $userUgel->position = $_POST['position'];
            $userUgel->files_charge = $_POST['files_charge'];
            $userUgel->active = $_POST['active'] ?? 0;

            $userUgel->save();

            UserService::syncMirrorData($userUgel, 'UGEL', [
                'name' => $userUgel->name,
                'paternal_surname' => $userUgel->paternal_surname,
                'maternal_surname' => $userUgel->maternal_surname,
                'dni' => $userUgel->dni,
                'phone' => $userUgel->phone,
                'email' => $userUgel->email,
                'address' => $userUgel->address,
            ]);

            $_SESSION['message'] = "Usuario actualizado correctamente.";
            $_SESSION['message_type'] = "success";
            header("Location: " . BASE_HEADER . "ugel-users");
            exit;
        }

        $_SESSION['message'] = "Método no permitido.";
        $_SESSION['message_type'] = "danger";
        header("Location: " . BASE_HEADER . "ugel-users");
        exit;
    }

    public function updateUserComunity($id)
    {
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            try {
                $userComunity = UserComunity::find($id);

                if (!$userComunity) {
                    $_SESSION['message'] = "Usuario no encontrado.";
                    $_SESSION['message_type'] = "danger";
                    header("Location: " . BASE_HEADER . "comunity-users");
                    exit;
                }

                $user = User::find($userComunity->user_id);
                if (!$user) {
                    $_SESSION['message'] = "Error al encontrar el usuario.";
                    $_SESSION['message_type'] = "danger";
                    header("Location: " . BASE_HEADER . "comunity-users");
                    exit;
                }

                $user->username = trim($_POST['username'] ?? '');

                if (!empty($_POST['password'])) {

                    $errors = PasswordValidator::validate($_POST['password']);

                    if (!empty($errors)) {
                        $_SESSION['message'] = implode("<br>", $errors);
                        $_SESSION['message_type'] = "danger";
                        header("Location: " . BASE_HEADER . "comunity-users/{$id}/edit");
                        exit;
                    }

                    $user->password = password_hash($_POST['password'], PASSWORD_BCRYPT);
                }

                $user->save();

                $userComunity->name = $_POST['name'] ?? null;
                $userComunity->paternal_surname = $_POST['paternal_surname'] ?? null;
                $userComunity->maternal_surname = $_POST['maternal_surname'] ?? null;
                $userComunity->dni = $_POST['dni'] ?? null;
                $userComunity->company_name = isset($_POST['company_name']) && trim($_POST['company_name']) !== '' ? $_POST['company_name'] : null;
                $userComunity->ruc = isset($_POST['ruc']) && trim($_POST['ruc']) !== '' ? $_POST['ruc'] : null;
                $userComunity->phone = isset($_POST['phone']) && trim($_POST['phone']) !== '' ? $_POST['phone'] : null;
                $userComunity->email = isset($_POST['email']) && trim($_POST['email']) !== '' ? $_POST['email'] : null;
                $userComunity->address = isset($_POST['address']) && trim($_POST['address']) !== '' ? $_POST['address'] : null;
                $userComunity->active = isset($_POST['active']) ? 1 : 0;

                $userComunity->save();

                UserService::syncMirrorData($userComunity, 'COMUNITY', [
                    'name' => $userComunity->name,
                    'paternal_surname' => $userComunity->paternal_surname,
                    'maternal_surname' => $userComunity->maternal_surname,
                    'dni' => $userComunity->dni,
                    'phone' => $userComunity->phone,
                    'email' => $userComunity->email,
                    'address' => $userComunity->address,
                ]);

                $personTypes = $_POST['person_types'] ?? [];

                Database::getConnection()->prepare("DELETE FROM users_person_types WHERE comunity_user_id = ?")
                    ->execute([$userComunity->id]);

                foreach ($personTypes as $personTypeId) {
                    $userPersonType = new UserPersonType([
                        'comunity_user_id' => $userComunity->id,
                        'person_type_id' => $personTypeId
                    ]);
                    $userPersonType->save();
                }

                // Lógica para DIRECTOR
                $directorType = $this->personTypeService->findByDescription('DIRECTOR');
                if ($directorType && in_array($directorType->id, $personTypes)) {
                    $schoolName = trim($_POST['school_name'] ?? '');
                    if (empty($schoolName)) {
                        throw new Exception("Debe ingresar el nombre del colegio para el tipo de persona DIRECTOR.");
                    }

                    $existingDirectorData = UserDirectorData::findBy('comunity_user_id', $userComunity->id);
                    if ($existingDirectorData) {
                        $existingDirectorData->school_name = $schoolName;
                        $existingDirectorData->save();
                    } else {
                        $newDirectorData = new UserDirectorData([
                            'comunity_user_id' => $userComunity->id,
                            'school_name' => $schoolName
                        ]);
                        $newDirectorData->save();
                    }
                } else {
                    // Si ya no es director, eliminar el registro si existe
                    $existingDirectorData = UserDirectorData::findBy('comunity_user_id', $userComunity->id);
                    if ($existingDirectorData) {
                        $existingDirectorData->delete($existingDirectorData->id);
                    }
                }

                $_SESSION['message'] = "Usuario actualizado correctamente.";
                $_SESSION['message_type'] = "success";
                header("Location: " . BASE_HEADER . "comunity-users");
                exit;
            } catch (Exception $e) {
                error_log("Error en la actualización: " . $e->getMessage());
                $_SESSION['message'] = "Ocurrió un error al actualizar.";
                $_SESSION['message_type'] = "danger";
                header("Location: " . BASE_HEADER . "comunity-users");
                exit;
            }
        }

        $_SESSION['message'] = "Método no permitido.";
        $_SESSION['message_type'] = "danger";
        header("Location: " . BASE_HEADER . "comunity-users");
        exit;
    }

    public function deleteUserUgel($id)
    {
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['_method']) && $_POST['_method'] === 'DELETE') {
            try {
                $userUgel = UserUgel::find($id);

                if (!$userUgel) {
                    $_SESSION['message'] = "Error: No se pudo encontrar el usuario.";
                    $_SESSION['message_type'] = "danger";
                    header("Location: " . BASE_HEADER . "ugel-users");
                    exit;
                }

                $user = User::find($userUgel->user_id);

                if (!$user) {
                    $_SESSION['message'] = "Error: No se pudo encontrar el usuario principal.";
                    $_SESSION['message_type'] = "danger";
                    header("Location: " . BASE_HEADER . "ugel-users");
                    exit;
                }

                $userUgel->delete($id);
                $user->delete($user->id);

                $_SESSION['message'] = "¡Usuario eliminado correctamente!";
                $_SESSION['message_type'] = "success";
                header("Location: " . BASE_HEADER . "ugel-users");
                exit;
            } catch (Exception $e) {
                error_log("Error al eliminar usuario: " . $e->getMessage());
                $_SESSION['message'] = "Ocurrió un error al eliminar el usuario.";
                $_SESSION['message_type'] = "danger";
                header("Location: " . BASE_HEADER . "ugel-users");
                exit;
            }
        }

        $_SESSION['message'] = "Error: Método no permitido.";
        $_SESSION['message_type'] = "danger";
        header("Location: " . BASE_HEADER . "ugel-users");
        exit;
    }

    public function deleteUserComunity($id)
    {
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['_method']) && $_POST['_method'] === 'DELETE') {
            try {
                $userComunity = UserComunity::find($id);

                if (!$userComunity) {
                    $_SESSION['message'] = "Error: No se pudo encontrar el usuario.";
                    $_SESSION['message_type'] = "danger";
                    header("Location: " . BASE_HEADER . "comunity-users");
                    exit;
                }

                $user = User::find($userComunity->user_id);

                if (!$user) {
                    $_SESSION['message'] = "Error: No se pudo encontrar el usuario principal.";
                    $_SESSION['message_type'] = "danger";
                    header("Location: " . BASE_HEADER . "comunity-users");
                    exit;
                }

                $userComunity->delete($id);
                $user->delete($user->id);

                $_SESSION['message'] = "¡Usuario eliminado correctamente!";
                $_SESSION['message_type'] = "success";
                header("Location: " . BASE_HEADER . "comunity-users");
                exit;
            } catch (Exception $e) {
                error_log("Error al eliminar usuario: " . $e->getMessage());
                $_SESSION['message'] = "Ocurrió un error al eliminar el usuario.";
                $_SESSION['message_type'] = "danger";
                header("Location: " . BASE_HEADER . "comunity-users");
                exit;
            }
        }

        $_SESSION['message'] = "Error: Método no permitido.";
        $_SESSION['message_type'] = "danger";
        header("Location: " . BASE_HEADER . "comunity-users");
        exit;
    }


    public function searchComunityUser()
    {
        $tipo = $_GET['tipo'] ?? '';
        $numero = $_GET['numero'] ?? '';

        if (empty($numero) || empty($tipo)) {
            echo json_encode(['exists' => false]);
            return;
        }

        // Buscar según tipo
        if ($tipo === 'dni') {
            $user = UserComunity::findBy('dni', $numero);
        } elseif ($tipo === 'ruc') {
            $user = UserComunity::findBy('ruc', $numero);
        } else {
            echo json_encode(['exists' => false]);
            return;
        }

        header('Content-Type: application/json');

        if ($user) {
            echo json_encode([
                'exists' => true,
                'name' => $user->name,
                'paternal_surname' => $user->paternal_surname,
                'maternal_surname' => $user->maternal_surname,
                'dni' => $user->dni,
                'company_name' => $user->company_name,
                'ruc' => $user->ruc,
                'phone' => $user->phone,
                'email' => $user->email,
                'address' => $user->address,
                'person_types' => $user->personTypeIds(),
                'has_user_id' => !empty($user->user_id),
            ]);
        } else {
            echo json_encode(['exists' => false]);
        }
    }

    public function searchUser()
    {
        header('Content-Type: application/json');

        $document = $_GET['dni'] ?? '';
        $document = trim($document);

        if ($document === '') {
            echo json_encode(['type' => 'none']);
            return;
        }

        $result = $this->userService->searchComunityByDocument($document, 5);
        
        echo json_encode($result);
        return;
    }

    public function searchUserByName()
    {
        header('Content-Type: application/json');
        $q = $_GET['q'] ?? '';
        $q = trim($q);

        if ($q === '') {
            echo json_encode([]);
            return;
        }

        $limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 20;
        $limit = max(1, min(50, $limit));

        $results = $this->userService->searchComunityUsersByName($q, $limit);

        echo json_encode($results);
    }

    public function registerUser()
    {
        header('Content-Type: application/json');
        $data = json_decode(file_get_contents("php://input"), true);

        if (!$data) {
            echo json_encode(["success" => false, "message" => "Datos no recibidos"]);
            return;
        }

        $dni = $data['dni'] ?? null;
        $ruc = $data['ruc'] ?? null;

        // 🔹 Validar tipo de registro
        if ($dni) {
            // Persona natural
            if (empty($data['name']) || empty($data['paternal_surname']) || empty($data['maternal_surname'])) {
                echo json_encode(["success" => false, "message" => "Complete los datos personales"]);
                return;
            }

            $exists = $this->userService->findComunityUserByDni($dni);
            if ($exists) {
                echo json_encode(["success" => false, "message" => "El usuario ya está registrado"]);
                return;
            }

            $user = new UserComunity();
            $user->dni = $dni;
            $user->name = $data['name'];
            $user->paternal_surname = $data['paternal_surname'];
            $user->maternal_surname = $data['maternal_surname'];
        } elseif ($ruc) {
            // Persona jurídica
            if (empty($data['company_name'])) {
                echo json_encode(["success" => false, "message" => "Debe ingresar la razón social"]);
                return;
            }

            $exists = $this->userService->findComunityUserByRuc($ruc);
            if ($exists) {
                echo json_encode(["success" => false, "message" => "La empresa ya está registrada"]);
                return;
            }

            $user = new UserComunity();
            $user->ruc = $ruc;
            $user->company_name = $data['company_name'];
            $user->rucglobal = $data['rucGlobal'];
        } else {
            echo json_encode(["success" => false, "message" => "Debe ingresar un DNI o RUC válido"]);
            return;
        }

        // 🔹 Campos comunes
        $user->phone = $data['phone'] ?? null;
        $user->email = $data['email'] ?? null;
        $user->active = 1;

        if ($user->save()) {
            echo json_encode([
                "success" => true,
                "message" => "Usuario registrado correctamente",
                "dni" => $user->dni ?? null,
                "ruc" => $user->ruc ?? null,
                "name" => $user->name ?? null,
                "paternal_surname" => $user->paternal_surname ?? null,
                "maternal_surname" => $user->maternal_surname ?? null,
                "company_name" => $user->company_name ?? null,
                "rucGlobal" => $user->rucglobal ?? null,
                "phone" => $user->phone ?? null,
                "email" => $user->email ?? null
            ]);
        } else {
            echo json_encode(["success" => false, "message" => "Error al registrar usuario"]);
        }
    }
}
