<?php

namespace WMS\Controllers;

use WMS\Core\Database;
use WMS\Core\Request;
use WMS\Core\Response;
use WMS\Helpers\Validator;
use WMS\Middleware\AuthMiddleware;

class UserController
{
    /**
     * GET /api/users
     */
    public static function index(array $params): void
    {
        try {
            $db = Database::getConnection();
            $stmt = $db->query(
                "SELECT id, username, full_name, email, role, warehouse_id, is_active, last_login_at, created_at
                 FROM users ORDER BY full_name ASC"
            );
            Response::success($stmt->fetchAll());
        } catch (\Throwable $e) {
            Response::error('Error al obtener usuarios: ' . $e->getMessage(), 500);
        }
    }

    /**
     * GET /api/users/{id}
     */
    public static function show(array $params): void
    {
        try {
            $db = Database::getConnection();
            $stmt = $db->prepare(
                "SELECT id, username, full_name, email, role, warehouse_id, is_active, last_login_at, created_at
                 FROM users WHERE id = ?"
            );
            $stmt->execute([(int) $params['id']]);
            $user = $stmt->fetch();
            if (!$user) {
                Response::error('Usuario no encontrado', 404);
                return;
            }
            Response::success($user);
        } catch (\Throwable $e) {
            Response::error('Error: ' . $e->getMessage(), 500);
        }
    }


    private static function validatePassword(string $password): ?string
    {
        $db = \WMS\Core\Database::getConnection();
        $stmt = $db->query("SELECT setting_key, setting_value FROM settings WHERE setting_key LIKE 'pwd_%'");
        $cfg = [];
        foreach ($stmt->fetchAll() as $r) {
            $cfg[str_replace('pwd_', '', $r['setting_key'])] = $r['setting_value'];
        }

        $minLen = (int) ($cfg['min_length'] ?? 8);
        if (strlen($password) < $minLen) {
            return "La contrasena debe tener al menos {$minLen} caracteres";
        }
        if (($cfg['require_uppercase'] ?? '1') === '1' && !preg_match('/[A-Z]/', $password)) {
            return 'La contrasena debe contener al menos una letra mayuscula';
        }
        if (($cfg['require_lowercase'] ?? '1') === '1' && !preg_match('/[a-z]/', $password)) {
            return 'La contrasena debe contener al menos una letra minuscula';
        }
        if (($cfg['require_number'] ?? '1') === '1' && !preg_match('/[0-9]/', $password)) {
            return 'La contrasena debe contener al menos un numero';
        }
        if (($cfg['require_special'] ?? '1') === '1') {
            $chars = $cfg['special_chars'] ?? "*.'!";
            $found = false;
            for ($i = 0; $i < strlen($chars); $i++) {
                if (strpos($password, $chars[$i]) !== false) {
                    $found = true;
                    break;
                }
            }
            if (!$found) {
                return 'La contrasena debe contener al menos uno de estos caracteres: ' . implode(' ', str_split($chars));
            }
        }
        return null;
    }

    /**
     * POST /api/users
     */
    public static function create(array $params): void
    {
        $body = Request::body();
        $v = (new Validator($body))->required(['username', 'password', 'full_name', 'role']);
        if (!$v->passes()) {
            Response::error('Datos invalidos', 422, $v->errors());
            return;
        }

        // Validate password policy
        $passErr = self::validatePassword($body['password']);
        if ($passErr) {
            Response::error($passErr, 422);
            return;
        }

        try {
            $db = Database::getConnection();

            // Check username unique
            $stmt = $db->prepare("SELECT id FROM users WHERE username = ?");
            $stmt->execute([$body['username']]);
            if ($stmt->fetch()) {
                Response::error('El usuario ya existe', 409);
                return;
            }

            $stmt = $db->prepare(
                "INSERT INTO users (username, password_hash, full_name, email, role, warehouse_id, is_active)
                 VALUES (?, ?, ?, ?, ?, ?, ?)"
            );
            $stmt->execute([
                $body['username'],
                password_hash($body['password'], PASSWORD_DEFAULT),
                $body['full_name'],
                $body['email'] ?? null,
                $body['role'],
                $body['warehouse_id'] ?? null,
                $body['is_active'] ?? 1,
            ]);

            $id = (int) $db->lastInsertId();
            Response::success(['id' => $id, 'username' => $body['username']], 'Usuario creado', 201);
        } catch (\Throwable $e) {
            Response::error('Error al crear usuario: ' . $e->getMessage(), 500);
        }
    }

    /**
     * PUT /api/users/{id}
     */
    public static function update(array $params): void
    {
        $body = Request::body();
        $id = (int) $params['id'];

        try {
            $db = Database::getConnection();

            $stmt = $db->prepare("SELECT id FROM users WHERE id = ?");
            $stmt->execute([$id]);
            if (!$stmt->fetch()) {
                Response::error('Usuario no encontrado', 404);
                return;
            }

            // Build dynamic update
            $fields = [];
            $values = [];

            foreach (['full_name', 'email', 'role', 'is_active'] as $f) {
                if (array_key_exists($f, $body)) {
                    $fields[] = "{$f} = ?";
                    $values[] = $body[$f];
                }
            }
            if (array_key_exists('warehouse_id', $body)) {
                $fields[] = "warehouse_id = ?";
                $values[] = $body['warehouse_id'] ?: null;
            }
            if (!empty($body['password'])) {
                $passErr = self::validatePassword($body['password']);
                if ($passErr) {
                    Response::error($passErr, 422);
                    return;
                }
                $fields[] = "password_hash = ?";
                $values[] = password_hash($body['password'], PASSWORD_DEFAULT);
            }
            if (!empty($body['username'])) {
                // Check unique
                $chk = $db->prepare("SELECT id FROM users WHERE username = ? AND id != ?");
                $chk->execute([$body['username'], $id]);
                if ($chk->fetch()) {
                    Response::error('El nombre de usuario ya existe', 409);
                    return;
                }
                $fields[] = "username = ?";
                $values[] = $body['username'];
            }

            if (empty($fields)) {
                Response::error('Nada que actualizar', 400);
                return;
            }

            $values[] = $id;
            $db->prepare("UPDATE users SET " . implode(', ', $fields) . " WHERE id = ?")->execute($values);

            Response::success(null, 'Usuario actualizado');
        } catch (\Throwable $e) {
            Response::error('Error al actualizar usuario: ' . $e->getMessage(), 500);
        }
    }

    /**
     * DELETE /api/users/{id}
     */
    public static function delete(array $params): void
    {
        $id = (int) $params['id'];

        try {
            if ($id === AuthMiddleware::userId()) {
                Response::error('No puede eliminar su propio usuario', 400);
                return;
            }

            $db = Database::getConnection();
            // Soft delete - deactivate
            $stmt = $db->prepare("UPDATE users SET is_active = 0 WHERE id = ?");
            $stmt->execute([$id]);

            if ($stmt->rowCount() === 0) {
                Response::error('Usuario no encontrado', 404);
                return;
            }

            Response::success(null, 'Usuario desactivado');
        } catch (\Throwable $e) {
            Response::error('Error: ' . $e->getMessage(), 500);
        }
    }

    /**
     * GET /api/users/operators
     */
    public static function operators(array $params): void
    {
        try {
            $db = Database::getConnection();
            $sql = "SELECT id, username, full_name, role, warehouse_id
                    FROM users
                    WHERE role IN ('operator','supervisor','op_recepcion','op_almacen','op_picking','qc_muestrista','qa_liberador','jefe','admin')
                      AND is_active = 1";
            $bindings = [];

            $warehouseId = Request::query('warehouse_id');
            if ($warehouseId) {
                $sql .= " AND (warehouse_id = ? OR warehouse_id IS NULL)";
                $bindings[] = (int) $warehouseId;
            }

            $sql .= " ORDER BY full_name ASC";
            $stmt = $db->prepare($sql);
            $stmt->execute($bindings);

            Response::success($stmt->fetchAll());
        } catch (\Throwable $e) {
            Response::error('Error al obtener operadores: ' . $e->getMessage(), 500);
        }
    }
}
