import { useEffect, useMemo, useState } from 'react';
import ReactECharts from 'echarts-for-react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faTriangleExclamation } from '@fortawesome/pro-duotone-svg-icons';
import { Badge } from '@/components/base/badges/badges';
import { Table } from '@/components/application/table/table';
import { apiClient } from '@/lib/api-client';
import { cx } from '@/utils/cx';

// Shared rollup surfaces for the supervisor dashboard: agent performance
// table (richer — NPS, idle, follow-ups, leads), per-agent time breakdown,
// NPS gauge + conversion metrics, and performance alerts. Kept in one file
// so both the Team Dashboard and the legacy Team Performance page render
// identically from a single data fetch.

type DateRange = 'today' | 'week' | 'month' | 'year';

type AgentPerf = {
    name: string;
    ozonetelAgentId: string;
    npsScore: number | null;
    maxIdleMinutes: number | null;
    minNpsThreshold: number | null;
    minConversionPercent: number | null;
    calls: number;
    inbound: number;
    missed: number;
    followUps: number;
    leads: number;
    appointments: number;
    convPercent: number;
    idleMinutes: number;
    activeMinutes: number;
    wrapMinutes: number;
    breakMinutes: number;
};

const getDateRange = (range: DateRange): { gte: string; lte: string } => {
    const now = new Date();
    const lte = now.toISOString();
    const start = new Date(now);
    if (range === 'today') start.setHours(0, 0, 0, 0);
    else if (range === 'week') { start.setDate(start.getDate() - start.getDay() + 1); start.setHours(0, 0, 0, 0); }
    else if (range === 'month') { start.setDate(1); start.setHours(0, 0, 0, 0); }
    else if (range === 'year') { start.setMonth(0, 1); start.setHours(0, 0, 0, 0); }
    return { gte: start.toISOString(), lte };
};

const parseTime = (timeStr: string): number => {
    if (!timeStr) return 0;
    const parts = timeStr.split(':').map(Number);
    if (parts.length === 3) return parts[0] * 3600 + parts[1] * 60 + parts[2];
    return 0;
};

export const useSupervisorRollup = (range: DateRange) => {
    const [agents, setAgents] = useState<AgentPerf[]>([]);
    const [loading, setLoading] = useState(true);

    useEffect(() => {
        const load = async () => {
            setLoading(true);
            const { gte, lte } = getDateRange(range);
            const dateStr = new Date().toISOString().split('T')[0];

            try {
                const [callsData, leadsData, followUpsData, teamData] = await Promise.all([
                    apiClient.graphql<any>(`{ calls(first: 500, filter: { startedAt: { gte: "${gte}", lte: "${lte}" } }) { edges { node { id direction callStatus agentName startedAt agentId agent { id name ozonetelAgentId } } } } }`, undefined, { silent: true }),
                    apiClient.graphql<any>(`{ leads(first: 200) { edges { node { id assignedAgent status } } } }`, undefined, { silent: true }),
                    apiClient.graphql<any>(`{ followUps(first: 200) { edges { node { id assignedAgent } } } }`, undefined, { silent: true }),
                    apiClient.get<any>(`/api/supervisor/team-performance?date=${dateStr}`, { silent: true }).catch(() => ({ agents: [] })),
                ]);

                const calls = callsData?.calls?.edges?.map((e: any) => e.node) ?? [];
                const leads = leadsData?.leads?.edges?.map((e: any) => e.node) ?? [];
                const followUps = followUpsData?.followUps?.edges?.map((e: any) => e.node) ?? [];
                const teamAgents = teamData?.agents ?? [];

                let agentPerfs: AgentPerf[];

                if (teamAgents.length > 0) {
                    agentPerfs = teamAgents.map((agent: any) => {
                        const agentCalls = calls.filter((c: any) => {
                            if (c.agentId && c.agentId === agent.id) return true;
                            if (!c.agentId && (c.agentName === agent.name || c.agentName === agent.ozonetelAgentId)) return true;
                            return false;
                        });
                        const agentLeads = leads.filter((l: any) => l.assignedAgent === agent.name);
                        const agentFollowUps = followUps.filter((f: any) => f.assignedAgent === agent.name);
                        const agentAppts = agentCalls.filter((c: any) => c.callStatus === 'COMPLETED').length;
                        const totalCalls = agentCalls.length;
                        const inbound = agentCalls.filter((c: any) => c.direction === 'INBOUND').length;
                        const missed = agentCalls.filter((c: any) => c.callStatus === 'MISSED').length;

                        const tb = agent.timeBreakdown;
                        const idleSec = tb ? parseTime(tb.totalIdleTime ?? '0:0:0') : 0;
                        const activeSec = tb ? parseTime(tb.totalBusyTime ?? '0:0:0') : 0;
                        const wrapSec = tb ? parseTime(tb.totalWrapupTime ?? '0:0:0') : 0;
                        const breakSec = tb ? parseTime(tb.totalPauseTime ?? '0:0:0') : 0;

                        return {
                            name: agent.name ?? agent.ozonetelAgentId,
                            ozonetelAgentId: agent.ozonetelAgentId,
                            npsScore: agent.npsScore,
                            maxIdleMinutes: agent.maxIdleMinutes,
                            minNpsThreshold: agent.minNpsThreshold,
                            minConversionPercent: agent.minConversionPercent,
                            calls: totalCalls,
                            inbound,
                            missed,
                            followUps: agentFollowUps.length,
                            leads: agentLeads.length,
                            appointments: agentAppts,
                            convPercent: totalCalls > 0 ? Math.round((agentAppts / totalCalls) * 100) : 0,
                            idleMinutes: Math.round(idleSec / 60),
                            activeMinutes: Math.round(activeSec / 60),
                            wrapMinutes: Math.round(wrapSec / 60),
                            breakMinutes: Math.round(breakSec / 60),
                        };
                    });
                } else {
                    const byKey = new Map<string, { key: string; name: string }>();
                    for (const c of calls) {
                        if (c.agent?.id) byKey.set(c.agent.id, { key: c.agent.id, name: c.agent.name ?? c.agent.ozonetelAgentId });
                        else if (c.agentName) byKey.set(`legacy:${c.agentName}`, { key: `legacy:${c.agentName}`, name: c.agentName });
                    }
                    agentPerfs = Array.from(byKey.values()).map(({ key, name }) => {
                        const agentCalls = calls.filter((c: any) => {
                            if (key.startsWith('legacy:')) return c.agentName === name && !c.agent?.id;
                            return c.agent?.id === key;
                        });
                        const agentLeads = leads.filter((l: any) => l.assignedAgent === name);
                        const agentFollowUps = followUps.filter((f: any) => f.assignedAgent === name);
                        const completed = agentCalls.filter((c: any) => c.callStatus === 'COMPLETED').length;
                        const totalCalls = agentCalls.length;

                        return {
                            name,
                            ozonetelAgentId: name,
                            npsScore: null,
                            maxIdleMinutes: null,
                            minNpsThreshold: null,
                            minConversionPercent: null,
                            calls: totalCalls,
                            inbound: agentCalls.filter((c: any) => c.direction === 'INBOUND').length,
                            missed: agentCalls.filter((c: any) => c.callStatus === 'MISSED').length,
                            followUps: agentFollowUps.length,
                            leads: agentLeads.length,
                            appointments: completed,
                            convPercent: totalCalls > 0 ? Math.round((completed / totalCalls) * 100) : 0,
                            idleMinutes: 0,
                            activeMinutes: 0,
                            wrapMinutes: 0,
                            breakMinutes: 0,
                        };
                    });
                }

                setAgents(agentPerfs);
            } catch (err) {
                console.error('Failed to load supervisor rollup:', err);
            } finally {
                setLoading(false);
            }
        };
        load();
    }, [range]);

    return { agents, loading };
};

export const RichAgentTable = ({ agents }: { agents: AgentPerf[] }) => (
    <div className="rounded-xl border border-secondary bg-primary p-4">
        <h3 className="text-sm font-semibold text-secondary mb-3">Agent Performance</h3>
        <Table size="sm">
            <Table.Header>
                <Table.Head label="Agent" isRowHeader />
                <Table.Head label="Calls" />
                <Table.Head label="Inbound" />
                <Table.Head label="Missed" />
                <Table.Head label="Follow-ups" />
                <Table.Head label="Leads" />
                <Table.Head label="Conv%" />
                <Table.Head label="NPS" />
                <Table.Head label="Idle" />
            </Table.Header>
            <Table.Body items={agents}>
                {(agent) => (
                    <Table.Row id={agent.ozonetelAgentId || agent.name}>
                        <Table.Cell><span className="text-sm font-medium text-primary">{agent.name}</span></Table.Cell>
                        <Table.Cell><span className="text-sm text-primary">{agent.calls}</span></Table.Cell>
                        <Table.Cell><span className="text-sm text-primary">{agent.inbound}</span></Table.Cell>
                        <Table.Cell><span className="text-sm text-primary">{agent.missed}</span></Table.Cell>
                        <Table.Cell><span className="text-sm text-primary">{agent.followUps}</span></Table.Cell>
                        <Table.Cell><span className="text-sm text-primary">{agent.leads}</span></Table.Cell>
                        <Table.Cell>
                            <span className={cx('text-sm font-medium', agent.convPercent >= 25 ? 'text-success-primary' : 'text-error-primary')}>
                                {agent.convPercent}%
                            </span>
                        </Table.Cell>
                        <Table.Cell>
                            <span className={cx('text-sm font-bold', (agent.npsScore ?? 0) >= 70 ? 'text-success-primary' : (agent.npsScore ?? 0) >= 50 ? 'text-warning-primary' : 'text-error-primary')}>
                                {agent.npsScore ?? '—'}
                            </span>
                        </Table.Cell>
                        <Table.Cell>
                            <span className={cx('text-sm', agent.maxIdleMinutes && agent.idleMinutes > agent.maxIdleMinutes ? 'text-error-primary font-bold' : 'text-primary')}>
                                {agent.idleMinutes}m
                            </span>
                        </Table.Cell>
                    </Table.Row>
                )}
            </Table.Body>
        </Table>
    </div>
);

export const TimeBreakdown = ({ agents }: { agents: AgentPerf[] }) => {
    const teamAvg = useMemo(() => {
        if (agents.length === 0) return { active: 0, wrap: 0, idle: 0, break_: 0 };
        return {
            active: Math.round(agents.reduce((s, a) => s + a.activeMinutes, 0) / agents.length),
            wrap: Math.round(agents.reduce((s, a) => s + a.wrapMinutes, 0) / agents.length),
            idle: Math.round(agents.reduce((s, a) => s + a.idleMinutes, 0) / agents.length),
            break_: Math.round(agents.reduce((s, a) => s + a.breakMinutes, 0) / agents.length),
        };
    }, [agents]);

    // QA flagged the earlier stacked-bar rendering as misleading — per-agent
    // totals varied wildly, making the visual width comparison meaningless.
    // Rendered as a table so the numbers speak for themselves; team-average
    // row sits at the top as the reference point.
    return (
        <div className="rounded-xl border border-secondary bg-primary p-4">
            <h3 className="text-sm font-semibold text-secondary mb-3">Time Breakdown</h3>
            {teamAvg.active === 0 && teamAvg.idle === 0 && teamAvg.wrap === 0 && teamAvg.break_ === 0 && (
                <p className="text-xs text-tertiary mb-3">Time utilisation data unavailable — requires Ozonetel agent session data.</p>
            )}
            <Table size="sm">
                <Table.Header>
                    <Table.Head label="Agent" isRowHeader />
                    <Table.Head label="Active" />
                    <Table.Head label="Wrap" />
                    <Table.Head label="Idle" />
                    <Table.Head label="Break" />
                    <Table.Head label="Total" />
                </Table.Header>
                <Table.Body
                    items={[
                        { id: '__team_avg__', name: 'Team average', isAvg: true, agent: null },
                        ...agents.map((a) => ({ id: a.ozonetelAgentId || a.name, name: a.name, isAvg: false, agent: a })),
                    ]}
                >
                    {(item) => {
                        const active = item.isAvg ? teamAvg.active : item.agent!.activeMinutes;
                        const wrap = item.isAvg ? teamAvg.wrap : item.agent!.wrapMinutes;
                        const idle = item.isAvg ? teamAvg.idle : item.agent!.idleMinutes;
                        const breakM = item.isAvg ? teamAvg.break_ : item.agent!.breakMinutes;
                        const total = active + wrap + idle + breakM;
                        const isHighIdle = !item.isAvg && item.agent!.maxIdleMinutes && idle > (item.agent!.maxIdleMinutes ?? 0);
                        return (
                            <Table.Row id={item.id}>
                                <Table.Cell>
                                    <span className={cx('text-sm', item.isAvg ? 'font-bold text-secondary' : 'font-medium text-primary')}>
                                        {item.name}
                                    </span>
                                </Table.Cell>
                                <Table.Cell><span className="text-sm text-primary">{active}m</span></Table.Cell>
                                <Table.Cell><span className="text-sm text-primary">{wrap}m</span></Table.Cell>
                                <Table.Cell>
                                    <span className={cx('text-sm', isHighIdle ? 'font-bold text-error-primary' : 'text-primary')}>
                                        {idle}m
                                    </span>
                                </Table.Cell>
                                <Table.Cell><span className="text-sm text-primary">{breakM}m</span></Table.Cell>
                                <Table.Cell><span className="text-sm text-secondary">{total}m</span></Table.Cell>
                            </Table.Row>
                        );
                    }}
                </Table.Body>
            </Table>
        </div>
    );
};

export const NpsConversion = ({ agents, convRate }: { agents: AgentPerf[]; convRate: number }) => {
    const avgNps = useMemo(() => {
        const withNps = agents.filter(a => a.npsScore != null);
        if (withNps.length === 0) return 0;
        return Math.round(withNps.reduce((sum, a) => sum + (a.npsScore ?? 0), 0) / withNps.length);
    }, [agents]);

    const npsOption = useMemo(() => ({
        tooltip: { trigger: 'item' },
        series: [{
            type: 'gauge', startAngle: 180, endAngle: 0,
            min: 0, max: 100,
            pointer: { show: false },
            progress: { show: true, width: 18, roundCap: true, itemStyle: { color: avgNps >= 70 ? '#22C55E' : avgNps >= 50 ? '#F59E0B' : '#EF4444' } },
            axisLine: { lineStyle: { width: 18, color: [[1, '#E5E7EB']] } },
            axisTick: { show: false }, splitLine: { show: false }, axisLabel: { show: false },
            detail: { valueAnimation: true, fontSize: 28, fontWeight: 'bold', offsetCenter: [0, '-10%'], formatter: '{value}' },
            data: [{ value: avgNps }],
        }],
    }), [avgNps]);

    return (
        <div className="flex gap-4">
            <div className="flex-1 rounded-xl border border-secondary bg-primary p-4">
                <h3 className="text-sm font-semibold text-secondary mb-2">Overall NPS</h3>
                {agents.every(a => a.npsScore == null) ? (
                    <div className="flex items-center justify-center py-8">
                        <p className="text-xs text-tertiary">NPS data unavailable — configure NPS scores on agent profiles.</p>
                    </div>
                ) : (
                    <>
                        <ReactECharts option={npsOption} style={{ height: 150 }} />
                        <div className="space-y-1 mt-2">
                            {agents.filter(a => a.npsScore != null).map(a => (
                                <div key={a.name} className="flex items-center gap-2">
                                    <span className="text-xs text-secondary w-28 truncate">{a.name}</span>
                                    <div className="flex-1 h-2 rounded-full bg-tertiary overflow-hidden">
                                        <div className={cx('h-full rounded-full', (a.npsScore ?? 0) >= 70 ? 'bg-success-solid' : (a.npsScore ?? 0) >= 50 ? 'bg-warning-solid' : 'bg-error-solid')} style={{ width: `${a.npsScore ?? 0}%` }} />
                                    </div>
                                    <span className="text-xs font-bold text-primary w-8 text-right">{a.npsScore}</span>
                                </div>
                            ))}
                        </div>
                    </>
                )}
            </div>
            <div className="flex-1 rounded-xl border border-secondary bg-primary p-4">
                <h3 className="text-sm font-semibold text-secondary mb-3">Conversion Metrics</h3>
                <div className="flex gap-3 mb-4">
                    <div className="flex-1 rounded-lg bg-secondary p-4 text-center">
                        <p className="text-2xl font-bold text-brand-secondary">{convRate}%</p>
                        <p className="text-xs text-tertiary">Call → Appointment</p>
                    </div>
                    <div className="flex-1 rounded-lg bg-secondary p-4 text-center">
                        <p className="text-2xl font-bold text-brand-secondary">
                            {agents.length > 0 ? Math.round(agents.reduce((s, a) => s + (a.leads > 0 ? 1 : 0), 0) / agents.length * 100) : 0}%
                        </p>
                        <p className="text-xs text-tertiary">Lead → Contact</p>
                    </div>
                </div>
                <div className="space-y-1">
                    {agents.map(a => (
                        <div key={a.name} className="flex items-center gap-2 text-xs">
                            <span className="text-secondary w-28 truncate">{a.name}</span>
                            <Badge size="sm" color={a.convPercent >= 25 ? 'success' : 'error'}>{a.convPercent}%</Badge>
                        </div>
                    ))}
                </div>
            </div>
        </div>
    );
};

export const PerformanceAlerts = ({ agents }: { agents: AgentPerf[] }) => {
    const alerts = useMemo(() => {
        const list: { agent: string; type: string; value: string; severity: 'error' | 'warning' }[] = [];
        for (const a of agents) {
            if (a.maxIdleMinutes && a.idleMinutes > a.maxIdleMinutes) {
                list.push({ agent: a.name, type: 'Excessive Idle Time', value: `${a.idleMinutes}m`, severity: 'error' });
            }
            if (a.minNpsThreshold && (a.npsScore ?? 100) < a.minNpsThreshold) {
                list.push({ agent: a.name, type: 'Low NPS', value: String(a.npsScore ?? 0), severity: 'warning' });
            }
            if (a.minConversionPercent && a.convPercent < a.minConversionPercent) {
                list.push({ agent: a.name, type: 'Low Conversion', value: `${a.convPercent}%`, severity: 'warning' });
            }
        }
        return list;
    }, [agents]);

    if (alerts.length === 0) return null;

    return (
        <div className="rounded-xl border border-secondary bg-primary p-4">
            <h3 className="text-sm font-semibold text-error-primary mb-3">
                <FontAwesomeIcon icon={faTriangleExclamation} className="size-3.5 mr-1.5" />
                Performance Alerts ({alerts.length})
            </h3>
            <div className="space-y-2">
                {alerts.map((alert, i) => (
                    <div key={i} className={cx(
                        'flex items-center justify-between rounded-lg px-4 py-3',
                        alert.severity === 'error' ? 'bg-error-secondary' : 'bg-warning-secondary',
                    )}>
                        <div className="flex items-center gap-2">
                            <FontAwesomeIcon icon={faTriangleExclamation} className={cx('size-3.5', alert.severity === 'error' ? 'text-fg-error-primary' : 'text-fg-warning-primary')} />
                            <span className="text-sm font-medium text-primary">{alert.agent}</span>
                            <span className="text-sm text-secondary">— {alert.type}</span>
                        </div>
                        <Badge size="sm" color={alert.severity}>{alert.value}</Badge>
                    </div>
                ))}
            </div>
        </div>
    );
};
