/* global angular, api_url */

angular.module("app").service("HikvisionService", [
    '$uhttp',
    function ($uhttp) {
        var controller = "hikvision/";

        // ================== GESTIÓN DE DISPOSITIVOS ==================
        
        /**
         * Obtiene todos los dispositivos configurados
         */
        this.getAllDevices = function () {
            return $uhttp({
                url: api_url + controller + 'get_devices',
                method: "GET"
            });
        };

        /**
         * Registra un nuevo dispositivo
         */
        this.registerDevice = function (data) {
            return $uhttp({
                url: api_url + controller + 'register_device',
                method: "POST",
                data: data
            });
        };

        /**
         * Actualiza un dispositivo existente
         */
        this.updateDevice = function (device_id, data) {
            return $uhttp({
                url: api_url + controller + 'update_device',
                method: "POST",
                data: data,
                params: {
                    id: device_id
                }
            });
        };

        /**
         * Sincroniza con todos los dispositivos Hikvision
         */
        this.sincronizarHikvision = function (hours_back) {
            return $uhttp({
                url: api_url + controller + 'sincronizar',
                method: "POST",
                data: {
                    hours_back: hours_back || 1
                }
            });
        };

        // ================== CONTROL DE ACCESO ISAPI ==================

        /**
         * Prueba la conexión con un dispositivo específico
         */
        this.testDeviceConnection = function (device_id) {
            return $uhttp({
                url: api_url + controller + 'test_device_connection',
                method: "GET",
                params: {
                    id: device_id
                }
            });
        };

        /**
         * Obtiene eventos de acceso de un dispositivo
         */
        this.getDeviceEvents = function (device_id, start_time, end_time) {
            return $uhttp({
                url: api_url + controller + 'get_device_events',
                method: "GET",
                params: {
                    id: device_id,
                    start_time: start_time,
                    end_time: end_time
                }
            });
        };

        /**
         * Abre una puerta específica del dispositivo
         */
        this.openDoor = function (device_id, door_id, reason) {
            return $uhttp({
                url: api_url + controller + 'open_door',
                method: "POST",
                data: {
                    door_id: door_id || 2,
                    reason: reason || 'Control manual desde interfaz'
                },
                params: {
                    id: device_id
                }
            });
        };

        /**
         * Obtiene el estado actual de las puertas
         */
        this.getDoorStatus = function (device_id) {
            return $uhttp({
                url: api_url + controller + 'get_door_status',
                method: "GET",
                params: {
                    id: device_id
                }
            });
        };

        /**
         * Configura el modo de trabajo de una puerta
         */
        this.setDoorMode = function (device_id, mode, door_id) {
            return $uhttp({
                url: api_url + controller + 'set_door_mode',
                method: "POST",
                data: {
                    mode: mode,
                    door_id: door_id || 1
                },
                params: {
                    id: device_id
                }
            });
        };

        /**
         * Valida un TAG específico
         */
        this.validateTag = function (card_no) {
            return $uhttp({
                url: api_url + controller + 'validate_tag',
                method: "POST",
                data: {
                    card_no: card_no
                }
            });
        };

        /**
         * Procesa un evento de acceso manualmente
         */
        this.processAccessEvent = function (device_id, event_data) {
            return $uhttp({
                url: api_url + controller + 'process_access_event',
                method: "POST",
                data: event_data,
                params: {
                    id: device_id
                }
            });
        };

        // ================== MOVIMIENTOS Y REPORTES ==================

        /**
         * Obtiene movimientos con filtros mejorados
         */
        this.getMovements = function (filters) {
            // Limpiar filtros vacíos
            var cleanFilters = {};
            Object.keys(filters).forEach(function(key) {
                if (filters[key] !== null && filters[key] !== undefined && filters[key] !== '') {
                    cleanFilters[key] = filters[key];
                }
            });
            
            return $uhttp({
                url: api_url + controller + 'get_movements',
                method: "GET",
                params: cleanFilters
            });
        };

        /**
         * Registra un nuevo movimiento
         */
        this.registerMovement = function (data) {
            return $uhttp({
                url: api_url + controller + 'register_movement',
                method: "POST",
                data: data
            });
        };

        /**
         * Obtiene estadísticas del sistema de control de acceso
         */
        this.getAccessStats = function (fecha_inicio, fecha_fin) {
            return $uhttp({
                url: api_url + controller + 'get_access_stats',
                method: "GET",
                params: {
                    fecha_inicio: fecha_inicio,
                    fecha_fin: fecha_fin
                }
            });
        };

        // ================== EXPORTACIÓN ==================

        /**
         * Genera URL para exportar movimientos a Excel
         */
        this.getExportExcelUrl = function (filters) {
            var params = new URLSearchParams();
            
            Object.keys(filters).forEach(function(key) {
                if (filters[key] !== null && filters[key] !== undefined && filters[key] !== '') {
                    params.append(key, filters[key]);
                }
            });
            
            return api_url + controller + 'export_movements_excel?' + params.toString();
        };

        /**
         * Genera URL para exportar movimientos a PDF
         */
        this.getExportPdfUrl = function (filters) {
            var params = new URLSearchParams();
            
            Object.keys(filters).forEach(function(key) {
                if (filters[key] !== null && filters[key] !== undefined && filters[key] !== '') {
                    params.append(key, filters[key]);
                }
            });
            
            return api_url + controller + 'export_movements_pdf?' + params.toString();
        };

        // ================== UTILIDADES PARA TIEMPO REAL ==================

        /**
         * Obtiene eventos recientes de todos los dispositivos
         */
        this.getRecentEvents = function (minutes_back) {
            var end_time = new Date();
            var start_time = new Date(end_time.getTime() - (minutes_back || 5) * 60000);
            
            return this.getAllDevices().then(function(devices_response) {
                if (devices_response.devices && devices_response.devices.length > 0) {
                    var promises = devices_response.devices.map(function(device) {
                        return this.getDeviceEvents(
                            device.id,
                            start_time.toISOString(),
                            end_time.toISOString()
                        );
                    }.bind(this));
                    
                    return Promise.all(promises).then(function(results) {
                        var all_events = [];
                        results.forEach(function(result, index) {
                            if (result.events) {
                                result.events.forEach(function(event) {
                                    event.device_info = devices_response.devices[index];
                                    all_events.push(event);
                                });
                            }
                        });
                        
                        // Ordenar por fecha más reciente
                        all_events.sort(function(a, b) {
                            return new Date(b.event_time) - new Date(a.event_time);
                        });
                        
                        return {
                            events: all_events,
                            total: all_events.length,
                            error: false
                        };
                    });
                } else {
                    return {
                        events: [],
                        total: 0,
                        error: false,
                        message: 'No hay dispositivos configurados'
                    };
                }
            }.bind(this));
        };

        /**
         * Monitorea el estado de conexión de todos los dispositivos
         */
        this.checkAllDevicesStatus = function () {
            return this.getAllDevices().then(function(devices_response) {
                if (devices_response.devices && devices_response.devices.length > 0) {
                    var promises = devices_response.devices.map(function(device) {
                        return this.testDeviceConnection(device.id).then(function(result) {
                            return {
                                device_id: device.id,
                                device_name: device.nombre,
                                device_ip: device.ip_address,
                                status: result.error ? 'offline' : 'online',
                                message: result.message,
                                last_check: new Date().toISOString()
                            };
                        }).catch(function(error) {
                            return {
                                device_id: device.id,
                                device_name: device.nombre,
                                device_ip: device.ip_address,
                                status: 'error',
                                message: error.message || 'Error de conexión',
                                last_check: new Date().toISOString()
                            };
                        });
                    }.bind(this));
                    
                    return Promise.all(promises).then(function(results) {
                        return {
                            devices_status: results,
                            total_devices: results.length,
                            online_devices: results.filter(function(r) { return r.status === 'online'; }).length,
                            offline_devices: results.filter(function(r) { return r.status !== 'online'; }).length,
                            error: false
                        };
                    });
                } else {
                    return {
                        devices_status: [],
                        total_devices: 0,
                        online_devices: 0,
                        offline_devices: 0,
                        error: false,
                        message: 'No hay dispositivos configurados'
                    };
                }
            }.bind(this));
        };

        // ================== CONTROL DE ACCESO AUTOMÁTICO ==================

        /**
         * Simula el proceso completo de acceso con TAG
         */
        this.simulateTagAccess = function (device_id, card_no) {
            // 1. Validar TAG
            return this.validateTag(card_no).then(function(validation_result) {
                if (validation_result.access_granted) {
                    // 2. Procesar evento de acceso
                    var event_data = {
                        card_no: card_no,
                        door_id: 1,
                        event_time: new Date().toISOString(),
                        event_id: 'sim_' + Date.now(),
                        event_type: 'card_access'
                    };
                    
                    return this.processAccessEvent(device_id, event_data).then(function(process_result) {
                        return {
                            success: true,
                            validation: validation_result,
                            processing: process_result,
                            action_taken: process_result.action,
                            message: 'Proceso de acceso completado exitosamente'
                        };
                    });
                } else {
                    return {
                        success: false,
                        validation: validation_result,
                        processing: null,
                        action_taken: 'ACCESS_DENIED',
                        message: 'Acceso denegado - TAG no válido'
                    };
                }
            }.bind(this)).catch(function(error) {
                return {
                    success: false,
                    validation: null,
                    processing: null,
                    action_taken: 'ERROR',
                    message: 'Error en el proceso: ' + (error.message || error),
                    error: error
                };
            });
        };

        // ================== CONFIGURACIÓN Y UTILIDADES ==================

        /**
         * Obtiene la configuración recomendada para un dispositivo nuevo
         */
        this.getDefaultDeviceConfig = function () {
            return {
                nombre: '',
                ip_address: '',
                puerto: 80,
                usuario: 'admin',
                password: '',
                ubicacion: '',
                tipo_acceso: 'ENTRADA'
            };
        };

        /**
         * Valida la configuración de un dispositivo antes de guardarlo
         */
        this.validateDeviceConfig = function (config) {
            var errors = [];
            
            if (!config.nombre || config.nombre.trim() === '') {
                errors.push('El nombre es requerido');
            }
            
            if (!config.ip_address || !this._isValidIP(config.ip_address)) {
                errors.push('Dirección IP inválida');
            }
            
            if (!config.puerto || config.puerto < 1 || config.puerto > 65535) {
                errors.push('Puerto inválido (1-65535)');
            }
            
            if (!config.usuario || config.usuario.trim() === '') {
                errors.push('Usuario es requerido');
            }
            
            if (!config.password || config.password.trim() === '') {
                errors.push('Contraseña es requerida');
            }
            
            return {
                valid: errors.length === 0,
                errors: errors
            };
        };

        /**
         * Formatea fechas para el protocolo ISAPI
         */
        this.formatDateForISAPI = function (date) {
            if (!date) {
                date = new Date();
            }
            if (typeof date === 'string') {
                date = new Date(date);
            }
            return date.toISOString().replace(/\.\d{3}Z$/, 'Z');
        };

        /**
         * Convierte tiempo relativo a fechas ISAPI
         */
        this.getTimeRangeForISAPI = function (minutes_back) {
            var end_time = new Date();
            var start_time = new Date(end_time.getTime() - (minutes_back || 60) * 60000);
            
            return {
                start_time: this.formatDateForISAPI(start_time),
                end_time: this.formatDateForISAPI(end_time)
            };
        };

        // ================== MÉTODOS PRIVADOS ==================

        /**
         * Valida formato de dirección IP
         */
        this._isValidIP = function (ip) {
            var regex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
            return regex.test(ip);
        };

        /**
         * Convierte respuesta de error a formato estándar
         */
        this._handleError = function (error) {
            return {
                success: false,
                error: true,
                message: error.message || error || 'Error desconocido',
                data: null
            };
        };
    }
]);