<?php

declare(strict_types=1);

namespace App\Models;

class User extends BaseModel
{
    protected string $table = 'usuarios';

    public function findProfileById(int $userId): ?array
    {
        if ($userId <= 0) {
            return null;
        }

        $stmt = $this->db()->prepare(
            'SELECT
                u.id,
                u.nombre,
                u.email,
                u.telefono,
                u.empresa_id,
                u.sucursal_id,
                u.activo,
                u.updated_at,
                r.nombre AS rol_nombre,
                r.slug AS rol_slug,
                e.nombre AS empresa_nombre,
                s.nombre AS sucursal_nombre
             FROM usuarios u
             LEFT JOIN roles r ON r.id = u.rol_id
             LEFT JOIN empresas e ON e.id = u.empresa_id
             LEFT JOIN sucursales s ON s.id = u.sucursal_id
             WHERE u.id = :id
             LIMIT 1'
        );
        $stmt->execute([':id' => $userId]);

        $row = $stmt->fetch();
        return $row ?: null;
    }

    public function listByCompany(int $companyId): array
    {
        $sql = 'SELECT
                    u.id,
                    u.nombre,
                    u.email,
                    u.activo,
                    u.sucursal_id,
                    r.nombre AS rol,
                    s.nombre AS sucursal
                FROM usuarios u
                LEFT JOIN roles r ON r.id = u.rol_id
                LEFT JOIN sucursales s ON s.id = u.sucursal_id
                WHERE u.empresa_id = :empresa_id
                ORDER BY u.id DESC';

        $stmt = $this->db()->prepare($sql);
        $stmt->execute([':empresa_id' => $companyId]);
        return $stmt->fetchAll() ?: [];
    }

    public function existsByEmail(string $email): bool
    {
        $stmt = $this->db()->prepare('SELECT id FROM usuarios WHERE email = :email LIMIT 1');
        $stmt->execute([':email' => strtolower(trim($email))]);
        return (bool) $stmt->fetch();
    }

    public function existsByEmailExceptId(string $email, int $userId): bool
    {
        $stmt = $this->db()->prepare(
            'SELECT id
             FROM usuarios
             WHERE email = :email
               AND id <> :id
             LIMIT 1'
        );
        $stmt->execute([
            ':email' => strtolower(trim($email)),
            ':id' => $userId,
        ]);

        return (bool) $stmt->fetch();
    }

    public function assignableByCompany(int $companyId): array
    {
        $stmt = $this->db()->prepare(
            'SELECT id, nombre, email, sucursal_id
             FROM usuarios
             WHERE empresa_id = :empresa_id
               AND activo = 1
             ORDER BY nombre ASC'
        );
        $stmt->execute([':empresa_id' => $companyId]);

        return $stmt->fetchAll() ?: [];
    }

    public function belongsToCompany(int $companyId, int $userId): bool
    {
        $stmt = $this->db()->prepare(
            'SELECT 1
             FROM usuarios
             WHERE id = :id
               AND empresa_id = :empresa_id
             LIMIT 1'
        );
        $stmt->execute([
            ':id' => $userId,
            ':empresa_id' => $companyId,
        ]);

        return (bool) $stmt->fetchColumn();
    }

    public function assignedBranchId(int $companyId, int $userId): ?int
    {
        if ($companyId <= 0 || $userId <= 0) {
            return null;
        }

        $stmt = $this->db()->prepare(
            'SELECT sucursal_id
             FROM usuarios
             WHERE id = :id
               AND empresa_id = :empresa_id
             LIMIT 1'
        );
        $stmt->execute([
            ':id' => $userId,
            ':empresa_id' => $companyId,
        ]);

        $value = $stmt->fetchColumn();
        if ($value === false || $value === null) {
            return null;
        }

        return (int) $value;
    }

    public function updateProfile(int $userId, string $name, string $email, ?string $phone): bool
    {
        if ($userId <= 0) {
            return false;
        }

        $stmt = $this->db()->prepare(
            'UPDATE usuarios
             SET nombre = :nombre,
                 email = :email,
                 telefono = :telefono,
                 updated_at = NOW()
             WHERE id = :id
             LIMIT 1'
        );

        return $stmt->execute([
            ':nombre' => $name,
            ':email' => strtolower(trim($email)),
            ':telefono' => $phone !== null && trim($phone) !== '' ? trim($phone) : null,
            ':id' => $userId,
        ]);
    }

    public function passwordHashById(int $userId): ?string
    {
        if ($userId <= 0) {
            return null;
        }

        $stmt = $this->db()->prepare(
            'SELECT password
             FROM usuarios
             WHERE id = :id
             LIMIT 1'
        );
        $stmt->execute([':id' => $userId]);
        $hash = $stmt->fetchColumn();

        if (!is_string($hash) || $hash === '') {
            return null;
        }

        return $hash;
    }

    public function updatePassword(int $userId, string $passwordHash): bool
    {
        if ($userId <= 0 || trim($passwordHash) === '') {
            return false;
        }

        $stmt = $this->db()->prepare(
            'UPDATE usuarios
             SET password = :password,
                 updated_at = NOW()
             WHERE id = :id
             LIMIT 1'
        );

        return $stmt->execute([
            ':password' => $passwordHash,
            ':id' => $userId,
        ]);
    }
}
