<?php
/**
 * ASISMA CRM - Alcance del Franquiciado
 *
 * Regla de oro: un franquiciado opera SOLO dentro de su vertical, su región y
 * lo que la matriz le autorizó VENDER. La autorización tiene dos niveles:
 *   - MARCA completa (franquiciado_marcas): todos los productos de la marca,
 *     incluidos los que se agreguen después.
 *   - PRODUCTO específico (franquiciado_productos): solo ese producto.
 * Puede vender un producto = su marca está completa O el producto está suelto.
 * Los leads le caen según lo que puede vender: por el producto de interés, o
 * si el lead solo trae marca, por tener la marca completa o algún producto
 * de esa marca. Este helper centraliza esas reglas para creación de leads,
 * catálogo, cotizaciones, derivación y rotación.
 */
class AlcanceHelper {

    /** Datos base del franquiciado (region_id, vertical_id) o null. */
    public static function getFranquiciado($franquiciadoId) {
        if (!$franquiciadoId) return null;
        $db = Database::getInstance();
        return $db->fetchOne(
            "SELECT f.id, f.region_id, f.vertical_id, f.estado,
                    r.nombre AS region_nombre, v.nombre AS vertical_nombre
             FROM franquiciados f
             LEFT JOIN regiones r ON f.region_id = r.id
             LEFT JOIN verticales v ON f.vertical_id = v.id
             WHERE f.id = :id",
            array('id' => $franquiciadoId)
        );
    }

    /** IDs de marcas COMPLETAS asignadas al franquiciado. */
    public static function marcasIds($franquiciadoId) {
        $db = Database::getInstance();
        $rows = $db->fetchAll(
            "SELECT marca_id FROM franquiciado_marcas WHERE franquiciado_id = :fid",
            array('fid' => $franquiciadoId)
        );
        $ids = array();
        foreach ($rows as $r) $ids[] = (int)$r['marca_id'];
        return $ids;
    }

    /** IDs de productos SUELTOS asignados al franquiciado. */
    public static function productosSueltosIds($franquiciadoId) {
        $db = Database::getInstance();
        $rows = $db->fetchAll(
            "SELECT producto_id FROM franquiciado_productos WHERE franquiciado_id = :fid",
            array('fid' => $franquiciadoId)
        );
        $ids = array();
        foreach ($rows as $r) $ids[] = (int)$r['producto_id'];
        return $ids;
    }

    /**
     * Condición SQL reutilizable: el franquiciado (alias $aliasFranq.id) puede
     * vender el producto :pid — marca completa O producto suelto.
     * (Los parámetros :pid_marca y :pid_suelto deben venir en $params.)
     */
    public static function condicionPuedeVenderProducto($aliasFranq = 'f') {
        return "(EXISTS (SELECT 1 FROM franquiciado_marcas fmv
                          INNER JOIN productos pv ON pv.id = :pid_marca AND pv.marca_id = fmv.marca_id
                          WHERE fmv.franquiciado_id = {$aliasFranq}.id)
              OR EXISTS (SELECT 1 FROM franquiciado_productos fpv
                          WHERE fpv.franquiciado_id = {$aliasFranq}.id AND fpv.producto_id = :pid_suelto))";
    }

    /**
     * Condición SQL reutilizable: el franquiciado puede atender un lead GENERICO
     * de la marca :mid_completa — SOLO si tiene la marca COMPLETA autorizada.
     * Regla de negocio (20-07-2026): los franquiciados que venden solo productos
     * sueltos NO reciben leads por marca; a ellos los leads les llegan únicamente
     * por producto específico (condicionPuedeVenderProducto).
     */
    public static function condicionPuedeVenderMarca($aliasFranq = 'f') {
        return "EXISTS (SELECT 1 FROM franquiciado_marcas fmm
                        WHERE fmm.franquiciado_id = {$aliasFranq}.id AND fmm.marca_id = :mid_completa)";
    }

    /** Marcas donde el franquiciado puede vender (completas o con productos sueltos). */
    public static function marcas($franquiciadoId) {
        $db = Database::getInstance();
        return $db->fetchAll(
            "SELECT DISTINCT m.id, m.vertical_id, m.nombre
             FROM marcas m
             WHERE m.activa = 1
               AND (EXISTS (SELECT 1 FROM franquiciado_marcas fm
                            WHERE fm.franquiciado_id = :fid AND fm.marca_id = m.id)
                 OR EXISTS (SELECT 1 FROM franquiciado_productos fp
                            INNER JOIN productos p ON p.id = fp.producto_id
                            WHERE fp.franquiciado_id = :fid2 AND p.marca_id = m.id))
             ORDER BY m.nombre ASC",
            array('fid' => $franquiciadoId, 'fid2' => $franquiciadoId)
        );
    }

    /** Productos activos que el franquiciado puede VENDER (marca completa + sueltos). */
    public static function productos($franquiciadoId) {
        $db = Database::getInstance();
        return $db->fetchAll(
            "SELECT p.id, p.marca_id, p.vertical_id, p.nombre, p.descripcion,
                    p.precio_minimo, p.precio_sugerido, p.activo
             FROM productos p
             WHERE p.activo = 1
               AND (p.marca_id IN (SELECT marca_id FROM franquiciado_marcas WHERE franquiciado_id = :fid)
                 OR p.id IN (SELECT producto_id FROM franquiciado_productos WHERE franquiciado_id = :fid2))
             ORDER BY p.nombre ASC",
            array('fid' => $franquiciadoId, 'fid2' => $franquiciadoId)
        );
    }

    /** ¿Puede vender ALGO de la marca? (completa o con productos sueltos de ella) */
    public static function marcaPermitida($franquiciadoId, $marcaId) {
        if (!$marcaId) return true; // sin marca = dentro de la vertical
        if (in_array((int)$marcaId, self::marcasIds($franquiciadoId))) return true;
        $db = Database::getInstance();
        $row = $db->fetchOne(
            "SELECT 1 FROM franquiciado_productos fp
             INNER JOIN productos p ON p.id = fp.producto_id
             WHERE fp.franquiciado_id = :fid AND p.marca_id = :mid LIMIT 1",
            array('fid' => $franquiciadoId, 'mid' => $marcaId)
        );
        return $row ? true : false;
    }

    /** ¿Puede vender el producto? (marca completa autorizada O producto suelto) */
    public static function productoPermitido($franquiciadoId, $productoId) {
        if (!$productoId) return true;
        $db = Database::getInstance();
        $row = $db->fetchOne(
            "SELECT p.id FROM productos p
             INNER JOIN franquiciado_marcas fm ON fm.marca_id = p.marca_id AND fm.franquiciado_id = :fid
             WHERE p.id = :pid",
            array('fid' => $franquiciadoId, 'pid' => $productoId)
        );
        if ($row) return true;
        $row = $db->fetchOne(
            "SELECT 1 FROM franquiciado_productos
             WHERE franquiciado_id = :fid AND producto_id = :pid",
            array('fid' => $franquiciadoId, 'pid' => $productoId)
        );
        return $row ? true : false;
    }

    /**
     * Un franquiciado puede cotizar un SERVICIO según el PRODUCTO del maestro
     * que lo representa (servicios.producto_id): marca completa autorizada o
     * producto suelto, igual que cualquier producto.
     */
    public static function servicioPermitido($franquiciadoId, $servicioId) {
        if (!$servicioId) return true;
        $db = Database::getInstance();
        $fila = $db->fetchOne("SELECT producto_id FROM servicios WHERE id = :sid", array('sid' => $servicioId));
        // OJO: productoPermitido(0) devuelve true (sin producto = sin filtro);
        // un servicio sin producto puente NO debe quedar autorizado para todos
        if (!$fila || !$fila['producto_id']) return false;
        return self::productoPermitido($franquiciadoId, (int)$fila['producto_id']);
    }

    /**
     * Valida que (region, vertical, marca, producto) estén dentro del alcance.
     * Devuelve null si todo bien, o el mensaje de error.
     */
    public static function validarLead($franquiciadoId, $regionId, $verticalId, $marcaId, $productoId) {
        $franq = self::getFranquiciado($franquiciadoId);
        if (!$franq) return 'Franquiciado no encontrado.';

        if ($regionId && (int)$regionId !== (int)$franq['region_id']) {
            return 'Solo puedes operar en tu región asignada (' . $franq['region_nombre'] . ').';
        }
        if ($verticalId && (int)$verticalId !== (int)$franq['vertical_id']) {
            return 'Solo puedes vender en tu vertical asignada (' . $franq['vertical_nombre'] . ').';
        }
        if ($productoId && !self::productoPermitido($franquiciadoId, $productoId)) {
            return 'Ese producto no está autorizado para tu franquicia. Contacta a la matriz.';
        }
        // Sin producto: basta poder vender algo de la marca
        if (!$productoId && $marcaId && !self::marcaPermitida($franquiciadoId, $marcaId)) {
            return 'Esa marca no está autorizada para tu franquicia. Contacta a la matriz.';
        }
        return null;
    }
}
