import { useMemo } from 'react';
import ReactECharts from 'echarts-for-react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import {
    faArrowTrendUp,
    faArrowTrendDown,
    faPhoneVolume,
    faPhoneArrowDownLeft,
    faPhoneArrowUpRight,
    faPercent,
} from '@fortawesome/pro-duotone-svg-icons';
import { BadgeWithIcon } from '@/components/base/badges/badges';
import { ArrowUp, ArrowDown } from '@untitledui/icons';
import { TopBar } from '@/components/layout/top-bar';
import { useData } from '@/providers/data-provider';
import type { Call } from '@/types/entities';

// Chart color palette — hardcoded from CSS tokens so ECharts can use them
const COLORS = {
    brand600: 'rgb(21, 112, 239)',
    brand500: 'rgb(59, 130, 246)',
    gray300: 'rgb(213, 215, 218)',
    gray400: 'rgb(164, 167, 174)',
    success500: 'rgb(23, 178, 106)',
    warning500: 'rgb(247, 144, 9)',
    error500: 'rgb(240, 68, 56)',
    purple500: 'rgb(158, 119, 237)',
};

// Helpers

const getLast7Days = (): { label: string; dateKey: string }[] => {
    const days: { label: string; dateKey: string }[] = [];
    const now = new Date();

    for (let i = 6; i >= 0; i--) {
        const date = new Date(now);
        date.setDate(now.getDate() - i);
        const label = date.toLocaleDateString('en-IN', { weekday: 'short', day: 'numeric' });
        const dateKey = date.toISOString().slice(0, 10);
        days.push({ label, dateKey });
    }

    return days;
};

const groupCallsByDate = (calls: Call[]): Record<string, { inbound: number; outbound: number }> => {
    const grouped: Record<string, { inbound: number; outbound: number }> = {};

    for (const call of calls) {
        const dateStr = call.startedAt ?? call.createdAt;
        if (!dateStr) continue;
        const dateKey = new Date(dateStr).toISOString().slice(0, 10);

        if (!grouped[dateKey]) {
            grouped[dateKey] = { inbound: 0, outbound: 0 };
        }

        if (call.callDirection === 'INBOUND') {
            grouped[dateKey].inbound++;
        } else if (call.callDirection === 'OUTBOUND') {
            grouped[dateKey].outbound++;
        }
    }

    return grouped;
};

const computeTrendPercent = (current: number, previous: number): number => {
    if (previous === 0) return current > 0 ? 100 : 0;
    return Math.round(((current - previous) / previous) * 100);
};

// Components

type KpiCardProps = {
    label: string;
    value: string | number;
    trend: number;
    icon: typeof faPhoneVolume;
    iconColor: string;
};

const KpiCard = ({ label, value, trend, icon, iconColor }: KpiCardProps) => {
    const isPositive = trend >= 0;

    return (
        <div className="flex flex-col gap-2 rounded-xl border border-secondary bg-primary p-5">
            <div className="flex items-center justify-between">
                <span className="text-sm font-medium text-tertiary">{label}</span>
                <FontAwesomeIcon icon={icon} className="size-5" style={{ color: iconColor }} />
            </div>
            <div className="flex items-end gap-3">
                <span className="text-display-sm font-bold text-primary">{value}</span>
                <BadgeWithIcon
                    size="sm"
                    color={isPositive ? 'success' : 'error'}
                    iconLeading={isPositive ? ArrowUp : ArrowDown}
                >
                    {Math.abs(trend)}%
                </BadgeWithIcon>
            </div>
            <span className="text-xs text-quaternary">vs previous 7 days</span>
        </div>
    );
};

export const ReportsPage = () => {
    const { calls, loading } = useData();

    // Split current 7 days vs previous 7 days
    const { currentCalls, previousCalls } = useMemo(() => {
        const now = new Date();
        const sevenDaysAgo = new Date(now);
        sevenDaysAgo.setDate(now.getDate() - 7);
        const fourteenDaysAgo = new Date(now);
        fourteenDaysAgo.setDate(now.getDate() - 14);

        const current: Call[] = [];
        const previous: Call[] = [];

        for (const call of calls) {
            const dateStr = call.startedAt ?? call.createdAt;
            if (!dateStr) continue;
            const date = new Date(dateStr);

            if (date >= sevenDaysAgo) {
                current.push(call);
            } else if (date >= fourteenDaysAgo) {
                previous.push(call);
            }
        }

        return { currentCalls: current, previousCalls: previous };
    }, [calls]);

    // KPI values
    const kpis = useMemo(() => {
        const totalCurrent = currentCalls.length;
        const totalPrevious = previousCalls.length;

        const inboundCurrent = currentCalls.filter((c) => c.callDirection === 'INBOUND').length;
        const inboundPrevious = previousCalls.filter((c) => c.callDirection === 'INBOUND').length;

        const outboundCurrent = currentCalls.filter((c) => c.callDirection === 'OUTBOUND').length;
        const outboundPrevious = previousCalls.filter((c) => c.callDirection === 'OUTBOUND').length;

        const bookedCurrent = currentCalls.filter((c) => c.disposition === 'APPOINTMENT_BOOKED').length;
        const bookedPrevious = previousCalls.filter((c) => c.disposition === 'APPOINTMENT_BOOKED').length;
        const conversionCurrent = totalCurrent > 0 ? Math.round((bookedCurrent / totalCurrent) * 100) : 0;
        const conversionPrevious = totalPrevious > 0 ? Math.round((bookedPrevious / totalPrevious) * 100) : 0;

        return {
            total: { value: totalCurrent, trend: computeTrendPercent(totalCurrent, totalPrevious) },
            inbound: { value: inboundCurrent, trend: computeTrendPercent(inboundCurrent, inboundPrevious) },
            outbound: { value: outboundCurrent, trend: computeTrendPercent(outboundCurrent, outboundPrevious) },
            conversion: { value: conversionCurrent, trend: computeTrendPercent(conversionCurrent, conversionPrevious) },
        };
    }, [currentCalls, previousCalls]);

    // Bar chart data — last 7 days
    const barChartOption = useMemo(() => {
        const days = getLast7Days();
        const grouped = groupCallsByDate(calls);

        const inboundData = days.map((d) => grouped[d.dateKey]?.inbound ?? 0);
        const outboundData = days.map((d) => grouped[d.dateKey]?.outbound ?? 0);
        const labels = days.map((d) => d.label);

        return {
            tooltip: {
                trigger: 'axis' as const,
                backgroundColor: '#fff',
                borderColor: '#e5e7eb',
                borderWidth: 1,
                textStyle: { color: '#344054', fontSize: 12 },
            },
            legend: {
                bottom: 0,
                itemWidth: 12,
                itemHeight: 12,
                textStyle: { color: '#667085', fontSize: 12 },
                data: ['Inbound', 'Outbound'],
            },
            grid: { left: 40, right: 16, top: 16, bottom: 40 },
            xAxis: {
                type: 'category' as const,
                data: labels,
                axisLine: { lineStyle: { color: '#e5e7eb' } },
                axisTick: { show: false },
                axisLabel: { color: '#667085', fontSize: 12 },
            },
            yAxis: {
                type: 'value' as const,
                splitLine: { lineStyle: { color: '#f2f4f7' } },
                axisLabel: { color: '#667085', fontSize: 12 },
            },
            series: [
                {
                    name: 'Inbound',
                    type: 'bar' as const,
                    data: inboundData,
                    barGap: '10%',
                    itemStyle: { color: COLORS.gray400, borderRadius: [4, 4, 0, 0] },
                },
                {
                    name: 'Outbound',
                    type: 'bar' as const,
                    data: outboundData,
                    itemStyle: { color: COLORS.brand600, borderRadius: [4, 4, 0, 0] },
                },
            ],
        };
    }, [calls]);

    // Donut chart data — call outcomes
    const { donutOption, donutTotal } = useMemo(() => {
        const booked = currentCalls.filter((c) => c.disposition === 'APPOINTMENT_BOOKED').length;
        const followUp = currentCalls.filter((c) => c.disposition === 'FOLLOW_UP_SCHEDULED').length;
        const infoOnly = currentCalls.filter((c) => c.disposition === 'INFO_PROVIDED').length;
        const missed = currentCalls.filter((c) => c.callStatus === 'MISSED').length;
        const other = currentCalls.length - booked - followUp - infoOnly - missed;
        const total = currentCalls.length;

        const data = [
            { value: booked, name: 'Booked', itemStyle: { color: COLORS.success500 } },
            { value: followUp, name: 'Follow-up', itemStyle: { color: COLORS.brand600 } },
            { value: infoOnly, name: 'Info Only', itemStyle: { color: COLORS.purple500 } },
            { value: missed, name: 'Missed', itemStyle: { color: COLORS.error500 } },
            ...(other > 0 ? [{ value: other, name: 'Other', itemStyle: { color: COLORS.gray300 } }] : []),
        ].filter((d) => d.value > 0);

        const option = {
            tooltip: {
                trigger: 'item' as const,
                backgroundColor: '#fff',
                borderColor: '#e5e7eb',
                borderWidth: 1,
                textStyle: { color: '#344054', fontSize: 12 },
                formatter: (params: { name: string; value: number; percent: number }) =>
                    `${params.name}: ${params.value} (${params.percent}%)`,
            },
            legend: {
                bottom: 0,
                itemWidth: 12,
                itemHeight: 12,
                textStyle: { color: '#667085', fontSize: 12 },
            },
            series: [
                {
                    type: 'pie' as const,
                    radius: ['55%', '80%'],
                    center: ['50%', '45%'],
                    avoidLabelOverlap: false,
                    label: {
                        show: true,
                        position: 'center' as const,
                        formatter: () => `${total}`,
                        fontSize: 28,
                        fontWeight: 700,
                        color: '#101828',
                    },
                    emphasis: {
                        label: { show: true, fontSize: 28, fontWeight: 700 },
                    },
                    labelLine: { show: false },
                    data,
                },
            ],
        };

        return { donutOption: option, donutTotal: total };
    }, [currentCalls]);

    if (loading) {
        return (
            <div className="flex flex-1 flex-col">
                <TopBar title="Reports" subtitle="Call analytics and insights" />
                <div className="flex flex-1 items-center justify-center">
                    <p className="text-sm text-tertiary">Loading data...</p>
                </div>
            </div>
        );
    }

    return (
        <div className="flex flex-1 flex-col overflow-hidden">
            <TopBar title="Reports" subtitle="Call analytics and insights" />
            <div className="flex-1 overflow-y-auto p-7 space-y-6">
                {/* KPI Cards */}
                <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4">
                    <KpiCard
                        label="Total Calls"
                        value={kpis.total.value}
                        trend={kpis.total.trend}
                        icon={faPhoneVolume}
                        iconColor={COLORS.brand600}
                    />
                    <KpiCard
                        label="Inbound"
                        value={kpis.inbound.value}
                        trend={kpis.inbound.trend}
                        icon={faPhoneArrowDownLeft}
                        iconColor={COLORS.gray400}
                    />
                    <KpiCard
                        label="Outbound"
                        value={kpis.outbound.value}
                        trend={kpis.outbound.trend}
                        icon={faPhoneArrowUpRight}
                        iconColor={COLORS.success500}
                    />
                    <KpiCard
                        label="Conversion %"
                        value={`${kpis.conversion.value}%`}
                        trend={kpis.conversion.trend}
                        icon={faPercent}
                        iconColor={COLORS.warning500}
                    />
                </div>

                {/* Charts row */}
                <div className="grid grid-cols-1 gap-6 xl:grid-cols-3">
                    {/* Call Volume Trend — 2/3 width */}
                    <div className="col-span-1 xl:col-span-2 rounded-xl border border-secondary bg-primary p-5">
                        <h2 className="text-md font-semibold text-primary mb-1">Call Volume Trend</h2>
                        <p className="text-sm text-tertiary mb-4">Inbound vs outbound calls — last 7 days</p>
                        <ReactECharts option={barChartOption} style={{ height: 340 }} />
                    </div>

                    {/* Call Outcomes Donut — 1/3 width */}
                    <div className="col-span-1 rounded-xl border border-secondary bg-primary p-5">
                        <h2 className="text-md font-semibold text-primary mb-1">Call Outcomes</h2>
                        <p className="text-sm text-tertiary mb-4">Disposition breakdown — last 7 days</p>
                        {donutTotal === 0 ? (
                            <div className="flex h-[340px] items-center justify-center">
                                <p className="text-sm text-tertiary">No call data in this period</p>
                            </div>
                        ) : (
                            <ReactECharts option={donutOption} style={{ height: 340 }} />
                        )}
                    </div>
                </div>
            </div>
        </div>
    );
};
