import React, { useEffect, useMemo, useState } from 'react';
import { __ } from '@wordpress/i18n';

const appData = window.manfietExpenseTrackerData || {};

const requestJson = (url, options = {}) => {
    const headers = {
        'Content-Type': 'application/json',
        ...(options.headers || {}),
    };

    if (appData.restNonce) {
        headers['X-WP-Nonce'] = appData.restNonce;
    }

    return fetch(url, {
        credentials: 'same-origin',
        ...options,
        headers,
    }).then(async (response) => {
        const data = await response.json().catch(() => ({}));
        if (!response.ok) {
            throw new Error(data.message || 'Request failed');
        }

        return data;
    });
};

const toAmount = (value) => {
    const parsed = Number(value);
    return Number.isFinite(parsed) ? parsed : 0;
};

const toDate = (value) => {
    if (!value) {
        return null;
    }

    const parsed = new Date(`${value}T00:00:00`);
    return Number.isNaN(parsed.getTime()) ? null : parsed;
};

const formatMoney = (value) => `${appData.currencySymbol || '$'}${toAmount(value).toFixed(2)}`;

const getWeekStart = (dateObj) => {
    const copy = new Date(dateObj.getTime());
    const day = copy.getDay();
    const diff = day === 0 ? -6 : 1 - day;
    copy.setDate(copy.getDate() + diff);
    return copy;
};

const dateKey = (dateObj) => dateObj.toISOString().slice(0, 10);

const aggregateByPeriod = (expenses, period) => {
    const totals = new Map();

    expenses.forEach((expense) => {
        const amount = toAmount(expense.amount);
        const dateObj = toDate(expense.date);

        if (!dateObj) {
            return;
        }

        let key = '';
        if (period === 'daily') {
            key = dateKey(dateObj);
        } else if (period === 'weekly') {
            key = dateKey(getWeekStart(dateObj));
        } else if (period === 'monthly') {
            key = `${dateObj.getFullYear()}-${String(dateObj.getMonth() + 1).padStart(2, '0')}`;
        } else {
            key = String(dateObj.getFullYear());
        }

        totals.set(key, (totals.get(key) || 0) + amount);
    });

    return Array.from(totals.entries())
        .sort((a, b) => String(a[0]).localeCompare(String(b[0])))
        .map(([label, value]) => ({ label, value }));
};

const PieChart = ({ data }) => {
    const total = data.reduce((sum, item) => sum + item.value, 0);

    if (total <= 0) {
        return <p>{__('No data available.', 'manfi-expense-tracker')}</p>;
    }

    const center = 110;
    const radius = 88;
    const colors = ['#1d4ed8', '#0ea5e9', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6', '#14b8a6'];

    let cumulative = 0;
    const slices = data.map((item, index) => {
        const fraction = item.value / total;
        const startAngle = cumulative * Math.PI * 2 - Math.PI / 2;
        cumulative += fraction;
        const endAngle = cumulative * Math.PI * 2 - Math.PI / 2;

        const startX = center + radius * Math.cos(startAngle);
        const startY = center + radius * Math.sin(startAngle);
        const endX = center + radius * Math.cos(endAngle);
        const endY = center + radius * Math.sin(endAngle);
        const largeArcFlag = fraction > 0.5 ? 1 : 0;

        const path = [
            `M ${center} ${center}`,
            `L ${startX} ${startY}`,
            `A ${radius} ${radius} 0 ${largeArcFlag} 1 ${endX} ${endY}`,
            'Z',
        ].join(' ');

        return {
            key: item.label,
            path,
            color: colors[index % colors.length],
            label: item.label,
            amount: item.value,
            percent: ((fraction || 0) * 100).toFixed(1),
        };
    });

    return (
        <div className="manfiet-chart-pie-wrap">
            <svg width="220" height="220" viewBox="0 0 220 220" role="img" aria-label={__('Category share pie chart', 'manfi-expense-tracker')}>
                {slices.map((slice) => (
                    <path key={slice.key} d={slice.path} fill={slice.color} stroke="#ffffff" strokeWidth="1" />
                ))}
            </svg>

            <div>
                {slices.map((slice) => (
                    <div key={slice.key} className="manfiet-chart-legend-item">
                        <span className="manfiet-chart-legend-dot" style={{ backgroundColor: slice.color }} />
                        <span className="manfiet-chart-legend-label">
                            {slice.label}: {formatMoney(slice.amount)} ({slice.percent}%)
                        </span>
                    </div>
                ))}
            </div>
        </div>
    );
};

const BarChart = ({ data }) => {
    const maxValue = Math.max(...data.map((item) => item.value), 0);

    if (maxValue <= 0) {
        return <p>{__('No data available.', 'manfi-expense-tracker')}</p>;
    }

    return (
        <div className="manfiet-chart-bars-wrap">
            {data.map((item, index) => {
                const widthPercent = Math.max(3, Math.round((item.value / maxValue) * 100));
                return (
                    <div key={item.label} className="manfiet-bar-item">
                        <div className="manfiet-bar-header">
                            <span>{item.label}</span>
                            <span>{formatMoney(item.value)}</span>
                        </div>
                        <div className="manfiet-progress-track manfiet-progress-track-sm">
                            <div
                                className="manfiet-progress-bar"
                                style={{
                                    width: `${widthPercent}%`,
                                    backgroundColor: index % 2 === 0 ? '#2563eb' : '#0ea5e9',
                                }}
                            />
                        </div>
                    </div>
                );
            })}
        </div>
    );
};

const LineChart = ({ data }) => {
    if (!data.length) {
        return <p>{__('No data available for this period.', 'manfi-expense-tracker')}</p>;
    }

    const baseWidth = 640;
    const height = 260;
    const paddingLeftRight = 35;
    const paddingTop = 20;
    const paddingBottom = 60;
    const chartWidth = Math.max(baseWidth, data.length * 30);
    const maxY = Math.max(...data.map((item) => item.value), 1);
    const stepX = data.length > 1 ? (chartWidth - paddingLeftRight * 2) / (data.length - 1) : 0;

    const points = data.map((item, index) => {
        const x = paddingLeftRight + index * stepX;
        const y = height - paddingBottom - (item.value / maxY) * (height - paddingTop - paddingBottom);
        return { ...item, x, y };
    });

    const d = points
        .map((point, index) => `${index === 0 ? 'M' : 'L'} ${point.x} ${point.y}`)
        .join(' ');

    const labelInterval = stepX > 0 ? Math.ceil(45 / stepX) : 1;

    return (
        <div className="manfiet-chart-line-wrap">
            <svg width={chartWidth} height={height} role="img" aria-label={__('Expense trend chart', 'manfi-expense-tracker')}>
                <line x1={paddingLeftRight} y1={height - paddingBottom} x2={chartWidth - paddingLeftRight} y2={height - paddingBottom} stroke="#cbd5e1" strokeWidth="1" />
                <line x1={paddingLeftRight} y1={paddingTop} x2={paddingLeftRight} y2={height - paddingBottom} stroke="#cbd5e1" strokeWidth="1" />
                <path d={d} fill="none" stroke="#1d4ed8" strokeWidth="3" strokeLinejoin="round" strokeLinecap="round" />

                {points.map((point, index) => {
                    const showLabel = index % labelInterval === 0;
                    return (
                        <g key={point.label}>
                            <circle cx={point.x} cy={point.y} r="4" fill="#1d4ed8" />
                            {showLabel && (
                                <text
                                    x={point.x}
                                    y={height - paddingBottom + 12}
                                    textAnchor="end"
                                    fontSize="10"
                                    fill="#475569"
                                    transform={`rotate(-45, ${point.x}, ${height - paddingBottom + 12})`}
                                >
                                    {point.label}
                                </text>
                            )}
                        </g>
                    );
                })}
            </svg>
        </div>
    );
};

const ReportsDashboard = () => {
    const restBase = appData.restBase || '/wp-json/manfi-expense-tracker/v1/';
    const exportUrls = appData.exportUrls || {};

    const [expenses, setExpenses] = useState([]);
    const [timePeriod, setTimePeriod] = useState('monthly');
    const [startDate, setStartDate] = useState('');
    const [endDate, setEndDate] = useState('');
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState('');

    const loadExpenses = (filters = {}, showLoader = true) => {
        const params = new URLSearchParams();
        const effectiveStartDate = filters.startDate ?? startDate;
        const effectiveEndDate = filters.endDate ?? endDate;

        if (effectiveStartDate && effectiveEndDate) {
            params.set('start_date', effectiveStartDate);
            params.set('end_date', effectiveEndDate);
        }

        if (showLoader) {
            setLoading(true);
        }

        const query = params.toString() ? `?${params.toString()}` : '';

        return requestJson(`${restBase}expenses${query}`)
            .then((data) => {
                setExpenses(Array.isArray(data) ? data : []);
                setError('');
            })
            .catch((requestError) => {
                setError(requestError.message || __('Failed to load reports.', 'manfi-expense-tracker'));
            })
            .finally(() => {
                if (showLoader) {
                    setLoading(false);
                }
            });
    };

    useEffect(() => {
        loadExpenses({}, true);
    }, [restBase]);

    useEffect(() => {
        const refresh = () => {
            loadExpenses({}, false);
        };

        window.addEventListener('manfiet-expense-added', refresh);
        return () => window.removeEventListener('manfiet-expense-added', refresh);
    }, [restBase, startDate, endDate]);

    const applyDateFilter = () => {
        if ((startDate && !endDate) || (!startDate && endDate)) {
            setError(__('Select both start and end date to filter reports.', 'manfi-expense-tracker'));
            return;
        }

        if (startDate && endDate && startDate > endDate) {
            setError(__('Start date cannot be later than end date.', 'manfi-expense-tracker'));
            return;
        }

        loadExpenses({ startDate, endDate }, true);
    };

    const resetDateFilter = () => {
        setStartDate('');
        setEndDate('');
        loadExpenses({ startDate: '', endDate: '' }, true);
    };

    const categoryTotals = useMemo(() => {
        const totals = new Map();

        expenses.forEach((expense) => {
            const category = expense.category || __('Uncategorized', 'manfi-expense-tracker');
            totals.set(category, (totals.get(category) || 0) + toAmount(expense.amount));
        });

        return Array.from(totals.entries())
            .map(([label, value]) => ({ label, value }))
            .sort((a, b) => b.value - a.value)
            .slice(0, 8);
    }, [expenses]);

    const timeSeriesData = useMemo(() => aggregateByPeriod(expenses, timePeriod), [expenses, timePeriod]);

    const totalSpent = expenses.reduce((sum, expense) => sum + toAmount(expense.amount), 0);

    const buildExportUrl = (baseUrl) => {
        if (!baseUrl) {
            return '';
        }

        try {
            const exportUrl = new URL(baseUrl, window.location.origin);

            if (startDate && endDate) {
                exportUrl.searchParams.set('start_date', startDate);
                exportUrl.searchParams.set('end_date', endDate);
            } else {
                exportUrl.searchParams.delete('start_date');
                exportUrl.searchParams.delete('end_date');
            }

            return exportUrl.toString();
        } catch (error) {
            return baseUrl;
        }
    };

    return (
        <div className="manfiet-page-shell manfiet-page-shell-wide">
            <div className="manfiet-page-hero">
                <div className="left-section">
                    <h2 className="manfiet-page-title">{__('Expense Reports', 'manfi-expense-tracker')}</h2>
                    <p className="manfiet-page-subtitle">
                        {__('Visual reports, exports, and trend analysis for spending behavior.', 'manfi-expense-tracker')}
                    </p>
                </div>
            </div>

            <div className="manfiet-card manfiet-mb-16">
                <h3 className="manfiet-card-title">{__('Report Range', 'manfi-expense-tracker')}</h3>
                <div className="manfiet-form-row manfiet-form-row-end">
                    <label className="manfiet-field manfiet-field-sm">
                        <span className="manfiet-label">{__('Start Date', 'manfi-expense-tracker')}</span>
                        <input className="manfiet-input" type="date" value={startDate} onChange={(event) => setStartDate(event.target.value)} />
                    </label>
                    <label className="manfiet-field manfiet-field-sm">
                        <span className="manfiet-label">{__('End Date', 'manfi-expense-tracker')}</span>
                        <input className="manfiet-input" type="date" value={endDate} onChange={(event) => setEndDate(event.target.value)} />
                    </label>
                    <button
                        type="button"
                        onClick={applyDateFilter}
                        className="manfiet-button manfiet-button-primary"
                    >
                        {__('Apply Filter', 'manfi-expense-tracker')}
                    </button>
                    <button
                        type="button"
                        onClick={resetDateFilter}
                        className="manfiet-button manfiet-button-secondary"
                    >
                        {__('Reset', 'manfi-expense-tracker')}
                    </button>
                </div>
            </div>

            <div className="manfiet-card manfiet-mb-16">
                <h3 className="manfiet-card-title">{__('Export Full Report', 'manfi-expense-tracker')}</h3>
                <div className="manfiet-form-row">
                    <button type="button" className="manfiet-button manfiet-button-primary" onClick={() => { window.location.href = buildExportUrl(exportUrls.csv); }}>
                        {__('Export Full Report (CSV)', 'manfi-expense-tracker')}
                    </button>
                    <button type="button" className="manfiet-button manfiet-button-info" onClick={() => { window.location.href = buildExportUrl(exportUrls.excel); }}>
                        {__('Export Full Report (Excel)', 'manfi-expense-tracker')}
                    </button>
                    <button type="button" className="manfiet-button manfiet-button-danger" onClick={() => { window.location.href = buildExportUrl(exportUrls.pdf); }}>
                        {__('Export Full Report (PDF)', 'manfi-expense-tracker')}
                    </button>
                </div>
            </div>

            <div className="manfiet-stats-grid manfiet-mb-16">
                <div className="manfiet-card manfiet-stat-card">
                    <div className="manfiet-stat-label">{__('Total Expenses', 'manfi-expense-tracker')}</div>
                    <div className="manfiet-stat-value">{expenses.length}</div>
                </div>
                <div className="manfiet-card manfiet-stat-card">
                    <div className="manfiet-stat-label">{__('Total Spent', 'manfi-expense-tracker')}</div>
                    <div className="manfiet-stat-value">{formatMoney(totalSpent)}</div>
                </div>
                <div className="manfiet-card manfiet-stat-card">
                    <div className="manfiet-stat-label">{__('Average Expense', 'manfi-expense-tracker')}</div>
                    <div className="manfiet-stat-value">
                        {formatMoney(expenses.length ? totalSpent / expenses.length : 0)}
                    </div>
                </div>
            </div>

            {error && <p className="manfiet-alert manfiet-alert-error">{error}</p>}
            {loading ? <p>{__('Loading...', 'manfi-expense-tracker')}</p> : null}

            {!loading && !error && (
                <>
                    <div className="manfiet-reports-grid manfiet-mb-16">
                        <div className="manfiet-card">
                            <h3 className="manfiet-card-title">{__('Pie Chart by Category', 'manfi-expense-tracker')}</h3>
                            <PieChart data={categoryTotals} />
                        </div>

                        <div className="manfiet-card">
                            <h3 className="manfiet-card-title">{__('Bar Chart by Category', 'manfi-expense-tracker')}</h3>
                            <BarChart data={categoryTotals} />
                        </div>
                    </div>

                    <div className="manfiet-card">
                        <div className="manfiet-card-head-row">
                            <h3 className="manfiet-card-title manfiet-card-title-no-margin">{__('Expense Trend Graph', 'manfi-expense-tracker')}</h3>
                            <select className="manfiet-input" value={timePeriod} onChange={(event) => setTimePeriod(event.target.value)}>
                                <option value="daily">{__('Daily', 'manfi-expense-tracker')}</option>
                                <option value="weekly">{__('Weekly', 'manfi-expense-tracker')}</option>
                                <option value="monthly">{__('Monthly', 'manfi-expense-tracker')}</option>
                                <option value="yearly">{__('Yearly', 'manfi-expense-tracker')}</option>
                            </select>
                        </div>
                        <div className="manfiet-mt-12">
                            <LineChart data={timeSeriesData} />
                        </div>
                    </div>
                </>
            )}
        </div>
    );
};

export default ReportsDashboard;
