// ==========================================
// CONFIGURACIÓN Y CONSTANTES
// ==========================================
const CONFIG = {
    API_BASE_URL: 'https://sgcd.lania.edu.mx/api_candidatos',  // base para OAuth y candidatos
    FILE_PREFIX: 'candidatos'
};

// ==========================================
// ESTADO DE LA APLICACIÓN
// ==========================================
class AppState {
    constructor() {
        this.accessToken = '';
        this.candidatesData = [];
    }

    setAccessToken(token) {
        this.accessToken = token;
    }

    getAccessToken() {
        return this.accessToken;
    }

    setCandidatesData(data) {
        this.candidatesData = data;
    }

    getCandidatesData() {
        return this.candidatesData;
    }

    hasToken() {
        return !!this.accessToken;
    }

    hasData() {
        return this.candidatesData.length > 0;
    }
}

// ==========================================
// SERVICIOS API
// ==========================================
class ApiService {
    static async getAccessToken(clientId, clientSecret) {
        const formData = new URLSearchParams();
        formData.append('grant_type', 'client_credentials');
        formData.append('client_id', clientId);
        formData.append('client_secret', clientSecret);

        const response = await fetch(`${CONFIG.API_BASE_URL}/oauth/token`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
            },
            body: formData
        });

        if (!response.ok) {
            const errorData = await response.json();
            throw new Error(errorData.message || 'Error en la autenticación');
        }

        return await response.json();
    }

    static async getCandidates(accessToken) {
        if (!accessToken) {
            throw new Error('No hay token de acceso disponible');
        }

        const response = await fetch(`${CONFIG.API_BASE_URL}/candidatos/obtenerCandidatos`, {
            method: 'GET',
            headers: {
                'Authorization': `Bearer ${accessToken}`,
                'Content-Type': 'application/json'
            }
        });

        if (!response.ok) {
            const errorData = await response.json();
            throw new Error(errorData.message || 'Error al obtener candidatos');
        }

        return await response.json();
    }
}

// ==========================================
// UTILIDADES
// ==========================================
class Utils {
    static getCurrentDateTime() {
        const now = new Date();
        const year = now.getFullYear();
        const month = String(now.getMonth() + 1).padStart(2, '0');
        const day = String(now.getDate()).padStart(2, '0');
        const hours = String(now.getHours()).padStart(2, '0');
        const minutes = String(now.getMinutes()).padStart(2, '0');
        
        return `${year}${month}${day}_${hours}${minutes}`;
    }

    static flattenObject(obj, prefix = '') {
        const flattened = {};
        
        for (const key in obj) {
            if (obj.hasOwnProperty(key)) {
                const newKey = prefix ? `${prefix}_${key}` : key;
                
                if (obj[key] !== null && typeof obj[key] === 'object' && !Array.isArray(obj[key])) {
                    Object.assign(flattened, Utils.flattenObject(obj[key], newKey));
                } else {
                    flattened[newKey] = obj[key];
                }
            }
        }
        
        return flattened;
    }

    static convertToCSV(data) {
        if (!data.length) return '';
        
        const flatData = data.map(candidato => Utils.flattenObject(candidato));
        const headers = Object.keys(flatData[0]);
        
        const csvHeaders = headers.join(',');
        const csvRows = flatData.map(row => 
            headers.map(header => {
                const value = row[header];
                if (typeof value === 'string' && (value.includes(',') || value.includes('\n') || value.includes('"'))) {
                    return `"${value.replace(/"/g, '""')}"`;
                }
                return value || '';
            }).join(',')
        );
        
        return [csvHeaders, ...csvRows].join('\n');
    }

    static downloadFile(content, filename, mimeType) {
        const blob = new Blob([content], { type: mimeType });
        const link = document.createElement('a');
        link.href = URL.createObjectURL(blob);
        link.download = filename;
        link.click();
        URL.revokeObjectURL(link.href);
    }
}

// ==========================================
// CONTROLADOR DE DESCARGA
// ==========================================
class DownloadController {
    constructor(appState) {
        this.appState = appState;
    }

    downloadJSON() {
        if (!this.appState.hasData()) {
            alert('No hay datos para descargar');
            return;
        }

        const dataStr = JSON.stringify(this.appState.getCandidatesData(), null, 2);
        const filename = `${CONFIG.FILE_PREFIX}_${Utils.getCurrentDateTime()}.json`;
        Utils.downloadFile(dataStr, filename, 'application/json');
    }

    downloadCSV() {
        if (!this.appState.hasData()) {
            alert('No hay datos para descargar');
            return;
        }

        const csvData = Utils.convertToCSV(this.appState.getCandidatesData());
        const filename = `${CONFIG.FILE_PREFIX}_${Utils.getCurrentDateTime()}.csv`;
        Utils.downloadFile(csvData, filename, 'text/csv;charset=utf-8;');
    }

    downloadExcel() {
        if (!this.appState.hasData()) {
            alert('No hay datos para descargar');
            return;
        }

        const flatData = this.appState.getCandidatesData().map(candidato => Utils.flattenObject(candidato));
        
        const wb = XLSX.utils.book_new();
        const ws = XLSX.utils.json_to_sheet(flatData);
        
        const cols = Object.keys(flatData[0]).map(() => ({ wch: 15 }));
        ws['!cols'] = cols;
        
        XLSX.utils.book_append_sheet(wb, ws, 'Candidatos');
        const filename = `${CONFIG.FILE_PREFIX}_${Utils.getCurrentDateTime()}.xlsx`;
        XLSX.writeFile(wb, filename);
    }
}

// ==========================================
// CONTROLADOR DE UI
// ==========================================
class UIController {
    constructor() {
        this.elements = {
            tokenType: document.getElementById('token-type'),
            expiresIn: document.getElementById('expires-in'),
            tokenSection: document.getElementById('token-section'),
            noTokenMessage: document.getElementById('no-token-message'),
            downloadSection: document.getElementById('download-section'),
            recordsCount: document.getElementById('records-count'),
            candidatesSection: document.getElementById('candidates-section'),
            candidatesTableBody: document.getElementById('candidates-table-body'),
            apiResponseSection: document.getElementById('api-response-section'),
            apiResponse: document.getElementById('api-response'),
            errorSection: document.getElementById('error-section'),
            errorMessage: document.getElementById('error-message'),
            noResultsMessage: document.getElementById('no-results-message')
        };
    }

    displayTokenInfo(tokenData) {
        this.elements.tokenType.textContent = tokenData.token_type;
        this.elements.expiresIn.textContent = tokenData.expires_in;
        
        this.elements.tokenSection.classList.remove('hidden');
        this.elements.noTokenMessage.classList.add('hidden');
        
        console.log('Token obtenido y almacenado de forma segura');
    }

    displayCandidates(candidates) {
        this.elements.apiResponse.textContent = JSON.stringify(candidates, null, 2);
        this.elements.apiResponseSection.classList.remove('hidden');
        
        this.elements.downloadSection.classList.remove('hidden');
        this.elements.recordsCount.textContent = candidates.length;
        
        this._fillCandidatesTable(candidates);
        
        this.elements.candidatesSection.classList.remove('hidden');
        this.elements.noResultsMessage.classList.add('hidden');
    }

    _fillCandidatesTable(candidates) {
        this.elements.candidatesTableBody.innerHTML = '';
        
        candidates.forEach(candidato => {
            const dem = candidato.demograficos || {};
            const ubi = dem.ubicacion || {};
            const form = candidato.formacion || {};
            const exam = candidato.examen || {};
            const exp = candidato.experiencia_servicio || {};
            const fechas = candidato.fechas || {};
            
            const row = document.createElement('tr');
            row.innerHTML = `
                <td>${candidato.nombre_completo ?? ''}</td>
                <td>${candidato.contacto?.correo ?? ''}</td>
                <td>${candidato.contacto?.telefono ?? ''}</td>
                <td>${dem.genero ?? ''}</td>
                <td>${dem.rango_edad ?? ''}</td>
                <td>${dem.tipo_identificacion ?? ''}</td>
                <td>${ubi.pais ?? ''}</td>
                <td>${ubi.estado ?? ''}</td>
                <td>${ubi.municipio ?? ''}</td>
                <td>${ubi.colonia ?? ''}</td>
                <td>${form.nivel_estudio ?? ''}</td>
                <td>${form.giro ?? ''}</td>
                <td>${form.nombre_empresa_institucion ?? ''}</td>
                <td>${exam.id_examen ?? ''}</td>
                <td>${exam.nombre_examen ?? ''}</td>
                <td>${exam.motivo ?? ''}</td>
                <td>${exp.calificacion_servicio ?? ''}</td>
                <td>${exp.consentimiento_publicidad !== undefined ? (exp.consentimiento_publicidad ? 'Sí' : 'No') : ''}</td>
                <td>${fechas.entrada ?? ''}</td>
                <td>${fechas.salida ?? ''}</td>
            `;
            
            this.elements.candidatesTableBody.appendChild(row);
        });
    }

    showError(message) {
        this.elements.errorMessage.textContent = message;
        this.elements.errorSection.classList.remove('hidden');
        this.elements.noResultsMessage.classList.add('hidden');
    }

    hideAllMessages() {
        this.elements.errorSection.classList.add('hidden');
        this.elements.apiResponseSection.classList.add('hidden');
        this.elements.downloadSection.classList.add('hidden');
    }
}

// ==========================================
// CONTROLADOR PRINCIPAL DE LA APLICACIÓN
// ==========================================
class AppController {
    constructor() {
        this.appState = new AppState();
        this.uiController = new UIController();
        this.downloadController = new DownloadController(this.appState);
        
        this._initializeEventListeners();
    }

    _initializeEventListeners() {
        // OAuth form
        document.getElementById('oauth-form').addEventListener('submit', (e) => this._handleOAuthSubmit(e));
        
        // Get candidates button
        document.getElementById('get-candidates').addEventListener('click', () => this._handleGetCandidates());
        
        // Download buttons
        document.getElementById('download-json').addEventListener('click', () => this.downloadController.downloadJSON());
        document.getElementById('download-csv').addEventListener('click', () => this.downloadController.downloadCSV());
        document.getElementById('download-excel').addEventListener('click', () => this.downloadController.downloadExcel());
    }

    async _handleOAuthSubmit(e) {
        e.preventDefault();
        
        const clientId = document.getElementById('clientId').value;
        const clientSecret = document.getElementById('clientSecret').value;
        
        this.uiController.hideAllMessages();
        
        try {
            const response = await ApiService.getAccessToken(clientId, clientSecret);
            this.appState.setAccessToken(response.access_token);
            this.uiController.displayTokenInfo(response);
        } catch (error) {
            this.uiController.showError(`Error al obtener token, las credenciales son incorrectas: ${error.message}`);
        }
    }

    async _handleGetCandidates() {
        this.uiController.hideAllMessages();
        
        try {
            const candidates = await ApiService.getCandidates(this.appState.getAccessToken());
            this.appState.setCandidatesData(candidates);
            this.uiController.displayCandidates(candidates);
        } catch (error) {
            this.uiController.showError(`Error al obtener candidatos: ${error.message}`);
        }
    }
}

// ==========================================
// INICIALIZACIÓN DE LA APLICACIÓN
// ==========================================
document.addEventListener('DOMContentLoaded', function() {
    new AppController();
});