<?php
class Cliente
{
    private $conn;

    public function __construct($db)
    {
        $this->conn = $db;
    }

    public function obtenerTodos($filtros = [])
    {
        try {
            $where = ["c.id > 0"];
            $params = [];

            // Filtro por búsqueda (incluyendo código QR)
            if (!empty($filtros['search'])) {
                $where[] = "(c.nombre LIKE :search1 OR c.apellidos LIKE :search2 OR c.nombre_comercial LIKE :search3 OR c.codigo LIKE :search4 OR c.telefono LIKE :search5 OR qr.codigo LIKE :search6)";
                $searchTerm = '%' . $filtros['search'] . '%';
                $params[':search1'] = $searchTerm;
                $params[':search2'] = $searchTerm;
                $params[':search3'] = $searchTerm;
                $params[':search4'] = $searchTerm;
                $params[':search5'] = $searchTerm;
                $params[':search6'] = $searchTerm;
            }

            // Filtro por estado
            if (isset($filtros['activo'])) {
                $where[] = "c.activo = :activo";
                $params[':activo'] = $filtros['activo'];
            }

            // Filtro por tiene rutas
            if (isset($filtros['tiene_rutas'])) {
                if ($filtros['tiene_rutas'] == '1') {
                    $where[] = "EXISTS (SELECT 1 FROM rutas_paradas rp INNER JOIN rutas r ON rp.ruta_id = r.id WHERE rp.cliente_id = c.id AND r.activa = 1)";
                } else if ($filtros['tiene_rutas'] == '0') {
                    $where[] = "NOT EXISTS (SELECT 1 FROM rutas_paradas rp INNER JOIN rutas r ON rp.ruta_id = r.id WHERE rp.cliente_id = c.id AND r.activa = 1)";
                }
            }

            // Filtro por tiene código QR
            if (isset($filtros['tiene_qr'])) {
                if ($filtros['tiene_qr'] == '1') {
                    $where[] = "c.codigo_qr_id IS NOT NULL";
                } else if ($filtros['tiene_qr'] == '0') {
                    $where[] = "c.codigo_qr_id IS NULL";
                }
            }

            $whereClause = implode(' AND ', $where);

            // Paginación
            $limit = isset($filtros['limit']) ? intval($filtros['limit']) : null;
            $offset = isset($filtros['offset']) ? intval($filtros['offset']) : 0;

            $query = "SELECT
                        c.*,
                        CONCAT(c.nombre, ' ', COALESCE(c.apellidos, '')) as nombre_completo,
                        CASE
                            WHEN c.activo = 1 THEN 'Activo'
                            ELSE 'Inactivo'
                        END as estado_actividad,
                        qr.codigo as codigo_qr,
                        (SELECT COUNT(DISTINCT rp.ruta_id)
                         FROM rutas_paradas rp
                         INNER JOIN rutas r ON rp.ruta_id = r.id
                         WHERE rp.cliente_id = c.id AND r.activa = 1) as cantidad_rutas,
                        (SELECT GROUP_CONCAT(DISTINCT r.nombre SEPARATOR ', ')
                         FROM rutas_paradas rp
                         INNER JOIN rutas r ON rp.ruta_id = r.id
                         WHERE rp.cliente_id = c.id AND r.activa = 1) as nombres_rutas
                      FROM clientes c
                      LEFT JOIN codigos_qr qr ON c.codigo_qr_id = qr.id
                      WHERE $whereClause
                      ORDER BY c.created_at DESC";

            // Agregar LIMIT y OFFSET si se especifica limit
            if ($limit !== null) {
                $query .= " LIMIT $limit OFFSET $offset";
            }

            $stmt = $this->conn->prepare($query);
            $stmt->execute($params);

            return $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch (Exception $e) {
            error_log("Error obteniendo clientes: " . $e->getMessage());
            return [];
        }
    }

    public function contarTodos($filtros = [])
    {
        try {
            $where = ["c.id > 0"];
            $params = [];

            // Filtro por búsqueda (incluyendo código QR)
            if (!empty($filtros['search'])) {
                $where[] = "(c.nombre LIKE :search1 OR c.apellidos LIKE :search2 OR c.nombre_comercial LIKE :search3 OR c.codigo LIKE :search4 OR c.telefono LIKE :search5 OR qr.codigo LIKE :search6)";
                $searchTerm = '%' . $filtros['search'] . '%';
                $params[':search1'] = $searchTerm;
                $params[':search2'] = $searchTerm;
                $params[':search3'] = $searchTerm;
                $params[':search4'] = $searchTerm;
                $params[':search5'] = $searchTerm;
                $params[':search6'] = $searchTerm;
            }

            // Filtro por estado
            if (isset($filtros['activo'])) {
                $where[] = "c.activo = :activo";
                $params[':activo'] = $filtros['activo'];
            }

            // Filtro por tiene rutas
            if (isset($filtros['tiene_rutas'])) {
                if ($filtros['tiene_rutas'] == '1') {
                    $where[] = "EXISTS (SELECT 1 FROM rutas_paradas rp INNER JOIN rutas r ON rp.ruta_id = r.id WHERE rp.cliente_id = c.id AND r.activa = 1)";
                } else if ($filtros['tiene_rutas'] == '0') {
                    $where[] = "NOT EXISTS (SELECT 1 FROM rutas_paradas rp INNER JOIN rutas r ON rp.ruta_id = r.id WHERE rp.cliente_id = c.id AND r.activa = 1)";
                }
            }

            // Filtro por tiene código QR
            if (isset($filtros['tiene_qr'])) {
                if ($filtros['tiene_qr'] == '1') {
                    $where[] = "c.codigo_qr_id IS NOT NULL";
                } else if ($filtros['tiene_qr'] == '0') {
                    $where[] = "c.codigo_qr_id IS NULL";
                }
            }

            $whereClause = implode(' AND ', $where);

            $query = "SELECT COUNT(*) as total FROM clientes c LEFT JOIN codigos_qr qr ON c.codigo_qr_id = qr.id WHERE $whereClause";

            $stmt = $this->conn->prepare($query);
            $stmt->execute($params);

            return $stmt->fetchColumn();
        } catch (Exception $e) {
            error_log("Error contando clientes: " . $e->getMessage());
            return 0;
        }
    }

    public function obtenerPorId($id)
    {
        try {
            $query = "SELECT 
                        c.*,
                        CONCAT(c.nombre, ' ', COALESCE(c.apellidos, '')) as nombre_completo,
                        CASE 
                            WHEN c.activo = 1 THEN 'Activo'
                            ELSE 'Inactivo'
                        END as estado_actividad
                      FROM clientes c
                      WHERE c.id = :id";

            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(':id', $id);
            $stmt->execute();

            return $stmt->fetch(PDO::FETCH_ASSOC);
        } catch (Exception $e) {
            error_log("Error obteniendo cliente: " . $e->getMessage());
            return false;
        }
    }

    public function crear($datos)
    {
        try {
            // Verificar que el código no existe
            $checkQuery = "SELECT COUNT(*) as count FROM clientes WHERE codigo = :codigo";
            $checkStmt = $this->conn->prepare($checkQuery);
            $checkStmt->bindParam(':codigo', $datos['codigo']);
            $checkStmt->execute();
            $result = $checkStmt->fetch(PDO::FETCH_ASSOC);

            if ($result['count'] > 0) {
                throw new Exception("Ya existe un cliente con este código");
            }


            $query = "INSERT INTO clientes (
                        codigo, nombre, apellidos, nombre_comercial, telefono, telefono_secundario, direccion, codigo_postal, pais, latitud, longitud, activo, tiene_credito, mobiliario
                      ) VALUES (
                        :codigo, :nombre, :apellidos, :nombre_comercial, :telefono, :telefono_secundario, :direccion, :codigo_postal, :pais, :latitud, :longitud, :activo, :tiene_credito, :mobiliario
                      )";

            $stmt = $this->conn->prepare($query);

            // Bind parameters
            $stmt->bindParam(':codigo', $datos['codigo']);
            $stmt->bindParam(':nombre', $datos['nombre']);
            $stmt->bindParam(':apellidos', $datos['apellidos']);
            $stmt->bindParam(':nombre_comercial', $datos['nombre_comercial']);
            $stmt->bindParam(':telefono', $datos['telefono']);
            $stmt->bindParam(':telefono_secundario', $datos['telefono_secundario']);
            $stmt->bindParam(':direccion', $datos['direccion']);
            $stmt->bindParam(':codigo_postal', $datos['codigo_postal']);
            $stmt->bindParam(':pais', $datos['pais']);
            $stmt->bindParam(':latitud', $datos['latitud']);
            $stmt->bindParam(':longitud', $datos['longitud']);
            $stmt->bindParam(':activo', $datos['activo']);
            $tieneCredito = isset($datos['tiene_credito']) ? intval($datos['tiene_credito']) : 0;
            $stmt->bindParam(':tiene_credito', $tieneCredito);
            $mobiliario = isset($datos['mobiliario']) ? $datos['mobiliario'] : null;
            $stmt->bindParam(':mobiliario', $mobiliario);

            $stmt->execute();
            $clienteId = $this->conn->lastInsertId();

            // Registrar en historial
            $this->registrarHistorial($clienteId, null, 'creacion', 'Cliente creado', null, $datos);

            return $clienteId;
        } catch (Exception $e) {
            error_log("Error creando cliente: " . $e->getMessage());
            throw $e;
        }
    }

    public function actualizar($id, $datos)
    {
        try {
            // Obtener datos anteriores para el historial
            $datosAnteriores = $this->obtenerPorId($id);

            // Verificar que el código no existe en otro cliente
            if (isset($datos['codigo'])) {
                $checkQuery = "SELECT COUNT(*) as count FROM clientes WHERE codigo = :codigo AND id != :id";
                $checkStmt = $this->conn->prepare($checkQuery);
                $checkStmt->bindParam(':codigo', $datos['codigo']);
                $checkStmt->bindParam(':id', $id);
                $checkStmt->execute();
                $result = $checkStmt->fetch(PDO::FETCH_ASSOC);

                if ($result['count'] > 0) {
                    throw new Exception("Ya existe un cliente con este código");
                }
            }


            $updateFields = [];
            $allowedFields = [
                'codigo',
                'nombre',
                'apellidos',
                'nombre_comercial',
                'telefono',
                'telefono_secundario',
                'direccion',
                'codigo_postal',
                'pais',
                'latitud',
                'longitud',
                'activo',
                'tiene_credito',
                'mobiliario'
            ];

            foreach ($allowedFields as $field) {
                if (isset($datos[$field])) {
                    $updateFields[] = "$field = :$field";
                }
            }

            if (empty($updateFields)) {
                throw new Exception("No hay datos para actualizar");
            }

            $query = "UPDATE clientes SET " . implode(', ', $updateFields) . ", updated_at = CURRENT_TIMESTAMP WHERE id = :id";
            $stmt = $this->conn->prepare($query);

            foreach ($allowedFields as $field) {
                if (isset($datos[$field])) {
                    $stmt->bindValue(":$field", $datos[$field]);
                }
            }
            $stmt->bindParam(':id', $id);

            $result = $stmt->execute();

            // Registrar en historial
            $this->registrarHistorial($id, null, 'actualizacion', 'Cliente actualizado', $datosAnteriores, $datos);

            return $result;
        } catch (Exception $e) {
            error_log("Error actualizando cliente: " . $e->getMessage());
            throw $e;
        }
    }

    public function eliminar($id)
    {
        try {
            // Soft delete
            $query = "UPDATE clientes SET activo = 0, updated_at = CURRENT_TIMESTAMP WHERE id = :id";
            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(':id', $id);

            $result = $stmt->execute();

            // Registrar en historial
            $this->registrarHistorial($id, null, 'suspension', 'Cliente desactivado');

            return $result;
        } catch (Exception $e) {
            error_log("Error eliminando cliente: " . $e->getMessage());
            return false;
        }
    }

    public function obtenerEstadisticas()
    {
        try {
            $stats = [];

            // Total clientes
            $query = "SELECT COUNT(*) as total FROM clientes WHERE activo = 1";
            $stmt = $this->conn->prepare($query);
            $stmt->execute();
            $stats['total_clientes'] = $stmt->fetchColumn();


            // Nuevos clientes (último mes)
            $query = "SELECT COUNT(*) as total FROM clientes WHERE activo = 1 AND created_at >= DATE_SUB(NOW(), INTERVAL 1 MONTH)";
            $stmt = $this->conn->prepare($query);
            $stmt->execute();
            $stats['nuevos_mes'] = $stmt->fetchColumn();

            // Clientes inactivos (sin compras en 6 meses)
            $query = "SELECT COUNT(*) as total FROM clientes WHERE activo = 1 AND (ultima_compra IS NULL OR ultima_compra < DATE_SUB(NOW(), INTERVAL 6 MONTH))";
            $stmt = $this->conn->prepare($query);
            $stmt->execute();
            $stats['inactivos'] = $stmt->fetchColumn();

            // Top ciudades
            $query = "SELECT 
                        ciudad,
                        COUNT(*) as cantidad
                      FROM clientes 
                      WHERE activo = 1 AND ciudad IS NOT NULL
                      GROUP BY ciudad 
                      ORDER BY cantidad DESC 
                      LIMIT 5";
            $stmt = $this->conn->prepare($query);
            $stmt->execute();
            $stats['top_ciudades'] = $stmt->fetchAll(PDO::FETCH_ASSOC);

            return $stats;
        } catch (Exception $e) {
            error_log("Error obteniendo estadísticas de clientes: " . $e->getMessage());
            return [];
        }
    }

    public function obtenerHistorial($clienteId, $limit = 50)
    {
        try {
            $query = "SELECT 
                        h.*,
                        u.nombre as usuario_nombre
                      FROM historial_clientes h
                      LEFT JOIN usuarios u ON h.usuario_id = u.id
                      WHERE h.cliente_id = :cliente_id
                      ORDER BY h.created_at DESC
                      LIMIT :limit";

            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(':cliente_id', $clienteId);
            $stmt->bindParam(':limit', $limit, PDO::PARAM_INT);
            $stmt->execute();

            return $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch (Exception $e) {
            error_log("Error obteniendo historial: " . $e->getMessage());
            return [];
        }
    }

    public function registrarHistorial($clienteId, $usuarioId, $accion, $descripcion, $datosAnteriores = null, $datosNuevos = null, $monto = null)
    {
        try {
            $query = "INSERT INTO historial_clientes (cliente_id, usuario_id, accion, descripcion, datos_anteriores, datos_nuevos, monto)
                      VALUES (:cliente_id, :usuario_id, :accion, :descripcion, :datos_anteriores, :datos_nuevos, :monto)";

            $stmt = $this->conn->prepare($query);
            $datosAnterioresJson = json_encode($datosAnteriores);
            $datosNuevosJson = json_encode($datosNuevos);
            
            $stmt->bindParam(':cliente_id', $clienteId);
            $stmt->bindParam(':usuario_id', $usuarioId);
            $stmt->bindParam(':accion', $accion);
            $stmt->bindParam(':descripcion', $descripcion);
            $stmt->bindParam(':datos_anteriores', $datosAnterioresJson);
            $stmt->bindParam(':datos_nuevos', $datosNuevosJson);
            $stmt->bindParam(':monto', $monto);

            return $stmt->execute();
        } catch (Exception $e) {
            error_log("Error registrando historial: " . $e->getMessage());
            return false;
        }
    }

    public function generarCodigoAutomatico()
    {
        try {
            // Obtener el último código
            $query = "SELECT codigo FROM clientes WHERE codigo REGEXP '^CLI-[0-9]+$' ORDER BY CAST(SUBSTRING(codigo, 5) AS UNSIGNED) DESC LIMIT 1";
            $stmt = $this->conn->prepare($query);
            $stmt->execute();
            $ultimoCodigo = $stmt->fetchColumn();

            if ($ultimoCodigo) {
                $numero = intval(substr($ultimoCodigo, 4)) + 1;
            } else {
                $numero = 1;
            }

            return 'CLI-' . str_pad($numero, 3, '0', STR_PAD_LEFT);
        } catch (Exception $e) {
            error_log("Error generando código: " . $e->getMessage());
            return 'CLI-001';
        }
    }
}
