const axios = require('axios');
const config = require('../config');
const logger = require('../utils/logger');

class NocoDBService {
    constructor() {
        this.apiUrl = config.nocodb.apiUrl;
        this.apiToken = config.nocodb.apiToken;
        this.projectId = config.nocodb.projectId;
        this.timeout = 10000; // 10 seconds
        
        // Create axios instance with defaults
        this.client = axios.create({
            baseURL: this.apiUrl,
            timeout: this.timeout,
            headers: {
                'xc-token': this.apiToken,
                'Content-Type': 'application/json'
            }
        });
        
        // Add response interceptor for error handling
        this.client.interceptors.response.use(
            response => response,
            error => {
                logger.error('NocoDB API Error:', {
                    message: error.message,
                    url: error.config?.url,
                    method: error.config?.method,
                    status: error.response?.status,
                    data: error.response?.data
                });
                throw error;
            }
        );
    }
    
    // Build table URL
    getTableUrl(tableId) {
        return `/db/data/v1/${this.projectId}/${tableId}`;
    }
    
    // Get all records from a table
    async getAll(tableId, params = {}) {
        const url = this.getTableUrl(tableId);
        const response = await this.client.get(url, { params });
        return response.data;
    }

    // Get ALL records from a table using pagination
    async getAllPaginated(tableId, params = {}) {
        try {
            let allRecords = [];
            let offset = 0;
            const limit = params.limit || 100;
            let hasMore = true;
            
            while (hasMore) {
                const response = await this.getAll(tableId, {
                    ...params,
                    limit: limit,
                    offset: offset
                });
                
                const records = response.list || [];
                allRecords = allRecords.concat(records);
                
                // Check if there are more records
                hasMore = records.length === limit;
                offset += limit;
                
                // Safety check to prevent infinite loops
                if (offset > 10000) {
                    logger.warn(`Reached maximum offset limit while fetching records from table ${tableId}`);
                    break;
                }
            }
            
            logger.info(`Fetched ${allRecords.length} total records from table ${tableId}`);
            
            return {
                list: allRecords,
                pageInfo: {
                    totalRows: allRecords.length,
                    page: 1,
                    pageSize: allRecords.length,
                    isFirstPage: true,
                    isLastPage: true
                }
            };
        } catch (error) {
            logger.error('Error fetching paginated records:', error);
            throw error;
        }
    }
    
    // Get single record
    async getById(tableId, recordId) {
        const url = `${this.getTableUrl(tableId)}/${recordId}`;
        const response = await this.client.get(url);
        return response.data;
    }
    
    // Create record
    async create(sheetId, data) {
        try {
            // Explicitly remove any ID field to prevent NocoDB conflicts
            const cleanData = { ...data };
            
            // Remove all possible ID field variations
            delete cleanData.ID;
            delete cleanData.id;
            delete cleanData.Id;
            delete cleanData.iD;
            
            // Remove any undefined values to prevent issues
            Object.keys(cleanData).forEach(key => {
                if (cleanData[key] === undefined) {
                    delete cleanData[key];
                }
            });
            
            logger.info(`Creating record in sheet ${sheetId}`);
            logger.info(`Data being sent to NocoDB:`, JSON.stringify(cleanData, null, 2));
            
            const url = this.getTableUrl(sheetId);
            const response = await this.client.post(url, cleanData);
            
            logger.info(`Create response status: ${response.status}`);
            logger.info(`Create response:`, JSON.stringify(response.data, null, 2));
            
            return response.data;
        } catch (error) {
            logger.error('Error creating record:', error);
            logger.error('Error response data:', JSON.stringify(error.response?.data, null, 2));
            logger.error('Error response status:', error.response?.status);
            logger.error('Error response headers:', JSON.stringify(error.response?.headers, null, 2));
            logger.error('Request URL:', error.config?.url);
            logger.error('Request method:', error.config?.method);
            logger.error('Request data:', JSON.stringify(error.config?.data, null, 2));
            throw error;
        }
    }
    
    // Update record
    async update(tableId, recordId, data) {
        const url = `${this.getTableUrl(tableId)}/${recordId}`;
        const response = await this.client.patch(url, data);
        return response.data;
    }
    
    // Delete record
    async delete(tableId, recordId) {
        const url = `${this.getTableUrl(tableId)}/${recordId}`;
        const response = await this.client.delete(url);
        return response.data;
    }
    
    // Get locations with proper filtering
    async getLocations(params = {}) {
        // For locations, we want all records by default, so use getAllPaginated
        // unless specific limit/offset are provided
        if (!params.limit && !params.offset) {
            return this.getAllPaginated(config.nocodb.tableId, params);
        }
        
        const defaultParams = {
            limit: 1000,
            offset: 0,
            ...params
        };
        
        return this.getAll(config.nocodb.tableId, defaultParams);
    }
    
    // Get user by email
    async getUserByEmail(email) {
        if (!config.nocodb.loginSheetId) {
            throw new Error('Login sheet not configured');
        }
        
        const response = await this.getAll(config.nocodb.loginSheetId, {
            where: `(Email,eq,${email})`,
            limit: 1
        });
        
        return response.list?.[0] || null;
    }
    
    // Get latest settings
    async getLatestSettings() {
        if (!config.nocodb.settingsSheetId) {
            return null;
        }
        
        const response = await this.getAll(config.nocodb.settingsSheetId, {
            sort: '-created_at',
            limit: 1
        });
        
        return response.list?.[0] || null;
    }
    
    // Get settings with walk sheet data
    async getWalkSheetSettings() {
        if (!config.nocodb.settingsSheetId) {
            return null;
        }
        
        const response = await this.getAll(config.nocodb.settingsSheetId, {
            sort: '-created_at',
            limit: 20
        });
        
        // Find first row with walk sheet data
        const settings = response.list?.find(row => 
            row.walk_sheet_title || 
            row.walk_sheet_subtitle || 
            row.walk_sheet_footer ||
            row.qr_code_1_url ||
            row.qr_code_2_url ||
            row.qr_code_3_url
        ) || response.list?.[0];
        
        return settings || null;
    }
}

// Export singleton instance
module.exports = new NocoDBService();