import { WS, ES, FORMAT } from "./constant";

// Add new type for table style
export type TableStyle = 'simple' | 'ascii';

export function addSpaces(string: string, spaceCount: number): string {
    for (let index = 0; index < spaceCount; index++) {
        string += WS;
    }
    return string;
}

export function removeDoubleQuotes(value: string): string {
    return value.replace(/"/g, ' ');
}

// Fixed ASCII border creation
function createAsciiBorder(startPoints: number[]): string {
    const border = startPoints.map((point, index) => {
        if (index === 0) return '-'.repeat(startPoints[1] - startPoints[0]);
        if (index === startPoints.length - 1) return '';
        return '-'.repeat(startPoints[index + 1] - startPoints[index]);
    }).filter(Boolean).join('+');
    return '+' + border + '+';
}

// Format complex values for better display
function formatComplexValue(value: any): string {
    if (value === null || value === undefined) return 'null';
    if (typeof value !== 'object') return String(value);
    
    if (Array.isArray(value)) {
        if (value.length === 0) return '[]';
        return value.map(item => {
            if (typeof item === 'object' && item !== null) {
                return formatComplexValue(item);
            }
            return String(item);
        }).join('\n');
    }
    
    const entries = Object.entries(value)
        .map(([k, v]) => {
            if (typeof v === 'object' && v !== null) {
                return `${k}: ${formatComplexValue(v)}`;
            }
            return `${k}: ${v}`;
        })
        .join('\n');
    return `{${entries}}`;
}

function wrapText(text: string, maxWidth: number): string[] {
    if (!text || text.length <= maxWidth) return [text || ''];
    
    // Split by newlines first to preserve array/object structure
    const lines = text.split('\n');
    const wrappedLines: string[] = [];
    
    lines.forEach(line => {
        if (line.length <= maxWidth) {
            wrappedLines.push(line);
        } else {
            const words = line.split(' ');
            let currentLine = '';
            
            words.forEach(word => {
                if ((currentLine + word).length <= maxWidth) {
                    currentLine += (currentLine ? ' ' : '') + word;
                } else {
                    if (currentLine) wrappedLines.push(currentLine);
                    currentLine = word;
                }
            });
            
            if (currentLine) wrappedLines.push(currentLine);
        }
    });
    
    return wrappedLines;
}

export function getRow(headers: string[], startPoints: number[], isHeaderRow: boolean, obj?: any): string[] {
    const maxWidth = 25;
    const rows: string[] = [];
    let maxLines = 1;
    
    // First pass: calculate max lines needed
    headers.forEach((header, index) => {
        const value = isHeaderRow ? header : obj[header];
        const formattedValue = typeof value === 'object' ? formatComplexValue(value) : String(value);
        const wrappedLines = wrapText(formattedValue, maxWidth);
        maxLines = Math.max(maxLines, wrappedLines.length);
    });
    
    // Generate all lines for the row
    for (let lineIndex = 0; lineIndex < maxLines; lineIndex++) {
        let row = ES;
        headers.forEach((header, index) => {
            const value = isHeaderRow ? header : obj[header];
            const formattedValue = typeof value === 'object' ? formatComplexValue(value) : String(value);
            const wrappedLines = wrapText(formattedValue, maxWidth);
            const lineContent = wrappedLines[lineIndex] || '';
            row += lineContent;
            const spaceCount = startPoints[index + 1] - row.length;
            row = addSpaces(row, spaceCount);
        });
        rows.push(row);
    }
    
    return rows;
}

export function getRows(data: any[], headers: string[], startPoints: number[], style: TableStyle = 'simple'): string[] {
    let rows: string[] = [];
    
    if (style === 'ascii') {
        // Add top border
        rows.push(createAsciiBorder(startPoints));
        
        // Add header row with borders
        const headerRows = getRow(headers, startPoints, true);
        headerRows.forEach(row => {
            rows.push('|' + row + '|');
        });
        
        // Add separator
        rows.push(createAsciiBorder(startPoints));
        
        // Add data rows with borders
        data.forEach(obj => {
            const dataRows = getRow(headers, startPoints, false, obj);
            dataRows.forEach(row => {
                rows.push('|' + row + '|');
            });
        });
        
        // Add bottom border
        rows.push(createAsciiBorder(startPoints));
    } else {
        // Original simple style
        const headerRows = getRow(headers, startPoints, true);
        rows.push(...headerRows);
        data.forEach(obj => {
            const dataRows = getRow(headers, startPoints, false, obj);
            rows.push(...dataRows);
        });
    }
    
    return rows;
}

export function getStartPoint(header: string, data: any[], startPoint: number): number {
    let lengths = [header.length];
    data.forEach(obj => {
        if (obj[header] === null) {
            lengths.push(4);
        } else {
            const value = obj[header];
            const formattedValue = typeof value === 'object' ? formatComplexValue(value) : value;
            lengths.push(String(formattedValue).length);
        }
    });
    startPoint += Math.max(...lengths) + 5;
    return startPoint;
}

export function getStartPoints(data: any[], headers: string[]): number[] {
    let startPoints = [0];
    let startPoint = 0;

    headers.forEach(header => {
        let lengths = [header.length];
        data.forEach(obj => {
            if (obj[header] === null) {
                lengths.push(4);
            } else {
                const value = obj[header];
                const formattedValue = typeof value === 'object' ? formatComplexValue(value) : String(value);
                // Calculate width based on wrapped lines
                const wrappedLines = wrapText(formattedValue, 25);
                const maxLineLength = Math.max(...wrappedLines.map(line => line.length));
                lengths.push(maxLineLength);
            }
        });
        // Add padding for better readability
        startPoint += Math.max(...lengths) + 4;
        startPoints.push(startPoint);
    });

    return startPoints;
}

export function getData(params: any): any {
    try {
        if (!Array.isArray(params)) {
            params = [params];
        }

        return params.map((param: any) => JSON.parse(JSON.stringify(param)));
    } catch (error) {
        console.error("Error parsing data:", error);
        return null;
    }
}
