import React from 'react';
import superagent from 'superagent';
import {
    Header, Segment, Button, Icon, Table, Label, Statistic,
    Loader, Dropdown, Grid, Message
} from 'semantic-ui-react';
import {
    PieChart, Pie, Cell, BarChart, Bar, XAxis, YAxis, CartesianGrid,
    Tooltip, Legend, ResponsiveContainer
} from 'recharts';
import { formatDistanceToNow, parseISO } from 'date-fns';
import ExperimentalWrapper from './ExperimentalWrapper.jsx';

const STATUS_COLORS = {
    DELIVERED: '#21ba45',
    IN_TRANSIT: '#2185d0',
    PRE_TRANSIT: '#fbbd08',
    RETURNED: '#db2828',
    FAILURE: '#a04050',
    UNKNOWN: '#767676',
};

const ALL_STATUSES_COLOR = '#999999';

const DATE_RANGE_OPTIONS = [
    { key: '7', text: 'Last 7 days', value: 7 },
    { key: '14', text: 'Last 14 days', value: 14 },
    { key: '30', text: 'Last 30 days', value: 30 },
    { key: '90', text: 'Last 90 days', value: 90 },
];

function getStatusColor(status) {
    return STATUS_COLORS[status] || ALL_STATUSES_COLOR;
}

export default class ShippoAnalyticsPage extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            // Data
            cacheStatus: null,
            analytics: null,
            transactions: [],
            transactionsTotal: 0,

            // UI state
            loading: false,
            refreshing: false,
            loadingTransactions: false,

            // Filters
            statusFilter: '',
            chartDays: 30,
            txOffset: 0,
            txLimit: 50,

            // Error
            error: null,
        };
    }

    componentDidMount() {
        this.fetchCacheStatus();
        this.fetchAnalytics();
        this.fetchTransactions();
    }

    async fetchCacheStatus() {
        try {
            const res = await superagent.get('/api/admin/shippo/analytics/cache-status');
            this.setState({ cacheStatus: res.body });
        } catch (err) {
            if (err.status !== 404) {
                console.error('Failed to fetch cache status', err);
            }
            this.setState({ cacheStatus: null });
        }
    }

    async fetchAnalytics() {
        this.setState({ loading: true });
        try {
            const res = await superagent.get('/api/admin/shippo/analytics');
            this.setState({ analytics: res.body, loading: false, error: null });
        } catch (err) {
            if (err.status === 404) {
                this.setState({ analytics: null, loading: false });
            } else {
                this.setState({ loading: false, error: 'Failed to load analytics.' });
            }
        }
    }

    async fetchTransactions() {
        const { statusFilter, txOffset, txLimit } = this.state;
        this.setState({ loadingTransactions: true });
        try {
            let req = superagent.get('/api/admin/shippo/analytics/transactions')
                .query({ limit: txLimit, offset: txOffset });
            if (statusFilter) {
                req = req.query({ status: statusFilter });
            }
            const res = await req;
            this.setState({
                transactions: res.body.transactions,
                transactionsTotal: res.body.total,
                loadingTransactions: false,
            });
        } catch (err) {
            console.error('Failed to fetch transactions', err);
            this.setState({ loadingTransactions: false });
        }
    }

    async refreshCache() {
        this.setState({ refreshing: true });
        try {
            await superagent.post('/api/admin/shippo/analytics/refresh');
            this.setState({ refreshing: false });
            // Refetch after a short delay to let the worker start
            setTimeout(() => {
                this.fetchCacheStatus();
                this.fetchAnalytics();
                this.fetchTransactions();
            }, 2000);
        } catch (err) {
            console.error('Failed to refresh cache', err);
            this.setState({ refreshing: false, error: 'Failed to start refresh.' });
        }
    }

    handleStatusFilterChange(value) {
        this.setState({ statusFilter: value, txOffset: 0 }, () => this.fetchTransactions());
    }

    handlePageChange(direction) {
        const { txOffset, txLimit, transactionsTotal } = this.state;
        let newOffset = txOffset;
        if (direction === 'next') {
            newOffset = Math.min(txOffset + txLimit, transactionsTotal - 1);
        } else {
            newOffset = Math.max(txOffset - txLimit, 0);
        }
        this.setState({ txOffset: newOffset }, () => this.fetchTransactions());
    }

    renderCacheStatus() {
        const { cacheStatus, refreshing } = this.state;

        return (
            <Segment>
                <Grid columns={3} verticalAlign="middle">
                    <Grid.Column width={6}>
                        <Header as="h4">
                            <Icon name="database" />
                            <Header.Content>Cache Status</Header.Content>
                        </Header>
                        {cacheStatus ? (
                            <div>
                                <p>
                                    Last refreshed: <strong>
                                        {formatDistanceToNow(parseISO(cacheStatus.metadata.fetchedAt), { addSuffix: true })}
                                    </strong>
                                </p>
                                <p>TTL: {cacheStatus.ttlSeconds}s remaining</p>
                            </div>
                        ) : (
                            <p>No cache available. Click refresh to populate.</p>
                        )}
                    </Grid.Column>
                    <Grid.Column width={5} textAlign="center">
                        {cacheStatus && (
                            <Statistic size="small">
                                <Statistic.Value>{cacheStatus.metadata.totalCached.toLocaleString()}</Statistic.Value>
                                <Statistic.Label>Cached Transactions</Statistic.Label>
                            </Statistic>
                        )}
                    </Grid.Column>
                    <Grid.Column width={5} textAlign="right">
                        <Button
                            primary
                            loading={refreshing}
                            disabled={refreshing}
                            onClick={() => this.refreshCache()}
                        >
                            <Icon name="refresh" />
                            Refresh Cache
                        </Button>
                    </Grid.Column>
                </Grid>
            </Segment>
        );
    }

    renderSummary() {
        const { analytics } = this.state;
        if (!analytics) return null;

        const { summary, statusBreakdown } = analytics;

        return (
            <Segment>
                <Header as="h4">Summary</Header>
                <Statistic.Group size="small" widths="four">
                    <Statistic>
                        <Statistic.Value>{summary.totalTransactions.toLocaleString()}</Statistic.Value>
                        <Statistic.Label>Total Transactions</Statistic.Label>
                    </Statistic>
                    <Statistic color="green">
                        <Statistic.Value>{(summary.byShippoStatus['SUCCESS'] || 0).toLocaleString()}</Statistic.Value>
                        <Statistic.Label>Successful Labels</Statistic.Label>
                    </Statistic>
                    <Statistic color="red">
                        <Statistic.Value>{(summary.byShippoStatus['ERROR'] || 0).toLocaleString()}</Statistic.Value>
                        <Statistic.Label>Error Labels</Statistic.Label>
                    </Statistic>
                    <Statistic>
                        <Statistic.Value>{Object.keys(statusBreakdown).length}</Statistic.Value>
                        <Statistic.Label>Unique Statuses</Statistic.Label>
                    </Statistic>
                </Statistic.Group>
            </Segment>
        );
    }

    renderStatusBreakdown() {
        const { analytics } = this.state;
        if (!analytics) return null;

        const { statusBreakdown, summary } = analytics;

        const pieData = Object.entries(statusBreakdown).map(([status, data]) => ({
            name: status,
            value: data.count,
        }));

        return (
            <Segment>
                <Header as="h4">Status Breakdown</Header>
                <Grid columns={2}>
                    <Grid.Column width={8}>
                        <ResponsiveContainer width="100%" height={300}>
                            <PieChart>
                                <Pie
                                    data={pieData}
                                    dataKey="value"
                                    nameKey="name"
                                    cx="50%"
                                    cy="50%"
                                    outerRadius={110}
                                    label={({ name, percent }) => `${name} (${(percent * 100).toFixed(1)}%)`}
                                >
                                    {pieData.map((entry, index) => (
                                        <Cell key={index} fill={getStatusColor(entry.name)} />
                                    ))}
                                </Pie>
                                <Tooltip />
                            </PieChart>
                        </ResponsiveContainer>
                    </Grid.Column>
                    <Grid.Column width={8}>
                        <Table compact="very" basic="very">
                            <Table.Header>
                                <Table.Row>
                                    <Table.HeaderCell>Status</Table.HeaderCell>
                                    <Table.HeaderCell textAlign="right">Count</Table.HeaderCell>
                                    <Table.HeaderCell textAlign="right">%</Table.HeaderCell>
                                </Table.Row>
                            </Table.Header>
                            <Table.Body>
                                {Object.entries(statusBreakdown)
                                    .sort(([, a], [, b]) => b.count - a.count)
                                    .map(([status, data]) => (
                                        <Table.Row key={status}>
                                            <Table.Cell>
                                                <Label
                                                    size="tiny"
                                                    style={{ backgroundColor: getStatusColor(status), color: '#fff' }}
                                                >
                                                    {status}
                                                </Label>
                                            </Table.Cell>
                                            <Table.Cell textAlign="right">{data.count.toLocaleString()}</Table.Cell>
                                            <Table.Cell textAlign="right">
                                                {((data.count / summary.totalTransactions) * 100).toFixed(1)}%
                                            </Table.Cell>
                                        </Table.Row>
                                    ))}
                            </Table.Body>
                        </Table>
                    </Grid.Column>
                </Grid>
            </Segment>
        );
    }

    renderTimeSeries() {
        const { analytics, chartDays } = this.state;
        if (!analytics || !analytics.timeSeries) return null;

        // Filter to selected day range
        const cutoff = new Date();
        cutoff.setDate(cutoff.getDate() - chartDays);
        const cutoffStr = cutoff.toISOString().split('T')[0];

        const filtered = analytics.timeSeries.filter(d => d.date >= cutoffStr);

        // Collect all status keys from the data
        const allStatuses = new Set();
        for (const entry of filtered) {
            for (const key of Object.keys(entry)) {
                if (key !== 'date') allStatuses.add(key);
            }
        }

        return (
            <Segment>
                <Grid columns={2} verticalAlign="middle">
                    <Grid.Column>
                        <Header as="h4">Transactions Over Time</Header>
                    </Grid.Column>
                    <Grid.Column textAlign="right">
                        <Dropdown
                            selection
                            compact
                            options={DATE_RANGE_OPTIONS}
                            value={chartDays}
                            onChange={(e, { value }) => this.setState({ chartDays: value })}
                        />
                    </Grid.Column>
                </Grid>
                <ResponsiveContainer width="100%" height={350}>
                    <BarChart data={filtered}>
                        <CartesianGrid strokeDasharray="3 3" />
                        <XAxis dataKey="date" tick={{ fontSize: 11 }} />
                        <YAxis />
                        <Tooltip />
                        <Legend />
                        {Array.from(allStatuses).map(status => (
                            <Bar
                                key={status}
                                dataKey={status}
                                stackId="a"
                                fill={getStatusColor(status)}
                            />
                        ))}
                    </BarChart>
                </ResponsiveContainer>
            </Segment>
        );
    }

    renderTransactionsTable() {
        const { transactions, transactionsTotal, loadingTransactions, txOffset, txLimit, statusFilter, analytics } = this.state;

        // Build status options from analytics
        const statusOptions = [{ key: '', text: 'All Statuses', value: '' }];
        if (analytics && analytics.statusBreakdown) {
            for (const status of Object.keys(analytics.statusBreakdown).sort()) {
                statusOptions.push({ key: status, text: status, value: status });
            }
        }

        const currentPage = Math.floor(txOffset / txLimit) + 1;
        const totalPages = Math.ceil(transactionsTotal / txLimit);

        return (
            <Segment>
                <Grid columns={2} verticalAlign="middle" style={{ marginBottom: 10 }}>
                    <Grid.Column>
                        <Header as="h4">Transactions</Header>
                    </Grid.Column>
                    <Grid.Column textAlign="right">
                        <Dropdown
                            selection
                            compact
                            placeholder="Filter by status"
                            options={statusOptions}
                            value={statusFilter}
                            onChange={(e, { value }) => this.handleStatusFilterChange(value)}
                        />
                    </Grid.Column>
                </Grid>

                {loadingTransactions ? (
                    <Loader active inline="centered" />
                ) : (
                    <>
                        <Table compact="very" striped>
                            <Table.Header>
                                <Table.Row>
                                    <Table.HeaderCell>Tracking Number</Table.HeaderCell>
                                    <Table.HeaderCell>Tracking Status</Table.HeaderCell>
                                    <Table.HeaderCell>Shippo Status</Table.HeaderCell>
                                    <Table.HeaderCell>Created At</Table.HeaderCell>
                                    <Table.HeaderCell>Tracking URL</Table.HeaderCell>
                                </Table.Row>
                            </Table.Header>
                            <Table.Body>
                                {transactions.map((tx, i) => (
                                    <Table.Row key={i}>
                                        <Table.Cell>{tx.trackingNumber || tx._trackingNumber}</Table.Cell>
                                        <Table.Cell>
                                            <Label
                                                size="tiny"
                                                style={{
                                                    backgroundColor: getStatusColor(tx.trackingStatus),
                                                    color: '#fff'
                                                }}
                                            >
                                                {tx.trackingStatus || 'UNKNOWN'}
                                            </Label>
                                        </Table.Cell>
                                        <Table.Cell>{tx.status}</Table.Cell>
                                        <Table.Cell>
                                            {tx.createdAt ? new Date(tx.createdAt).toLocaleDateString() : '-'}
                                        </Table.Cell>
                                        <Table.Cell>
                                            {tx.trackingUrlProvider ? (
                                                <a href={tx.trackingUrlProvider} target="_blank" rel="noopener noreferrer">
                                                    <Icon name="external" /> Track
                                                </a>
                                            ) : '-'}
                                        </Table.Cell>
                                    </Table.Row>
                                ))}
                                {transactions.length === 0 && (
                                    <Table.Row>
                                        <Table.Cell colSpan="5" textAlign="center">
                                            No transactions found.
                                        </Table.Cell>
                                    </Table.Row>
                                )}
                            </Table.Body>
                        </Table>
                        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                            <span>{transactionsTotal.toLocaleString()} total</span>
                            <div>
                                <Button
                                    size="small"
                                    disabled={txOffset === 0}
                                    onClick={() => this.handlePageChange('prev')}
                                >
                                    <Icon name="chevron left" /> Prev
                                </Button>
                                <span style={{ margin: '0 10px' }}>
                                    Page {currentPage} of {totalPages || 1}
                                </span>
                                <Button
                                    size="small"
                                    disabled={txOffset + txLimit >= transactionsTotal}
                                    onClick={() => this.handlePageChange('next')}
                                >
                                    Next <Icon name="chevron right" />
                                </Button>
                            </div>
                        </div>
                    </>
                )}
            </Segment>
        );
    }

    render() {
        const { loading, error, analytics } = this.state;

        return (
            <ExperimentalWrapper title="Shippo Analytics">
                <Segment>
                    <Header as="h2">
                        <Icon name="shipping fast" />
                        <Header.Content>
                            Shippo Analytics
                            <Header.Subheader>
                                Shipping transaction analytics from Shippo
                            </Header.Subheader>
                        </Header.Content>
                    </Header>
                </Segment>

                {error && (
                    <Message negative>
                        <Message.Header>Error</Message.Header>
                        <p>{error}</p>
                    </Message>
                )}

                {this.renderCacheStatus()}

                {loading ? (
                    <Segment>
                        <Loader active inline="centered" content="Loading analytics..." />
                    </Segment>
                ) : !analytics ? (
                    <Message info>
                        <Message.Header>No Analytics Available</Message.Header>
                        <p>Click "Refresh Cache" above to compute analytics from Shippo data.</p>
                    </Message>
                ) : (
                    <>
                        {this.renderSummary()}
                        {this.renderStatusBreakdown()}
                        {this.renderTimeSeries()}
                    </>
                )}

                {this.renderTransactionsTable()}
            </ExperimentalWrapper>
        );
    }
}
