'use client';

import { Activity, RefreshCcw, AlertCircle, X, Plus, Trash2, ExternalLink, ChevronDown, ChevronUp, Pencil, Check } from 'lucide-react';
import { useState, useEffect, useCallback, useRef } from 'react';
import { format, subHours, subDays, subMonths } from 'date-fns';

// --- Types ---

type BarStatus = 'up' | 'degraded' | 'down' | 'unknown';
type TimeRange = '24h' | '7d' | '30d' | '365d';

interface HistoryBucket {
    bucket: string;
    up_count: number;
    total: number;
}

interface ServiceStatus {
    name: string;
    url: string;
    status: 'up' | 'down';
    latency: number;
    uptime24h?: number;
    uptime7d?: number;
    uptimeLifetime?: number;
    avgLatency24h?: number;
    history?: HistoryBucket[];
}

interface BarData {
    label: string;
    status: BarStatus;
    upCount: number;
    total: number;
}

// --- Constants ---

const BAR_STYLES: Record<BarStatus, { base: string; compact: string }> = {
    up:       { base: 'bg-emerald-500 [box-shadow:0_0_6px_rgba(16,185,129,0.4)]',  compact: 'bg-emerald-500 [box-shadow:0_0_4px_rgba(16,185,129,0.25)]' },
    degraded: { base: 'bg-amber-500 [box-shadow:0_0_6px_rgba(245,158,11,0.4)]',    compact: 'bg-amber-500 [box-shadow:0_0_4px_rgba(245,158,11,0.25)]' },
    down:     { base: 'bg-red-500 [box-shadow:0_0_6px_rgba(239,68,68,0.4)]',       compact: 'bg-red-500 [box-shadow:0_0_4px_rgba(239,68,68,0.25)]' },
    unknown:  { base: 'bg-neutral-700',                                              compact: 'bg-neutral-700' },
};

const RANGE_OPTIONS: { value: TimeRange; label: string }[] = [
    { value: '24h', label: '24H' },
    { value: '7d', label: '7D' },
    { value: '30d', label: '30D' },
    { value: '365d', label: '1Y' },
];

const RANGE_CONFIG: Record<TimeRange, { bars: number; bucketMs: number }> = {
    '24h':  { bars: 24, bucketMs: 3600_000 },
    '7d':   { bars: 7,  bucketMs: 86400_000 },
    '30d':  { bars: 30, bucketMs: 86400_000 },
    '365d': { bars: 12, bucketMs: 0 }, // months handled specially
};

// --- Helpers ---

function toUTCKey(d: Date, mode: 'hour' | 'day' | 'month'): string {
    const Y = d.getUTCFullYear();
    const M = String(d.getUTCMonth() + 1).padStart(2, '0');
    if (mode === 'month') return `${Y}-${M}`;
    const D = String(d.getUTCDate()).padStart(2, '0');
    if (mode === 'day') return `${Y}-${M}-${D}`;
    const H = String(d.getUTCHours()).padStart(2, '0');
    return `${Y}-${M}-${D} ${H}:00`;
}

function bucketStatus(upCount: number, total: number): BarStatus {
    if (total === 0) return 'unknown';
    if (upCount === total) return 'up';
    if (upCount === 0) return 'down';
    return 'degraded';
}

function buildBars(range: TimeRange, history: HistoryBucket[] | undefined): BarData[] {
    const config = RANGE_CONFIG[range];
    const now = new Date();
    const bars: BarData[] = [];

    const bucketMap = new Map<string, HistoryBucket>();
    if (history) {
        for (const h of history) {
            bucketMap.set(h.bucket, h);
        }
    }

    if (range === '24h') {
        for (let i = config.bars - 1; i >= 0; i--) {
            const d = subHours(now, i);
            const key = toUTCKey(d, 'hour');
            const h = bucketMap.get(key);
            const hourStart = new Date(d);
            hourStart.setMinutes(0, 0, 0);
            bars.push({
                label: format(hourStart, 'MMM d, h a') + ' – ' + format(new Date(hourStart.getTime() + 3600_000), 'h a'),
                status: h ? bucketStatus(h.up_count, h.total) : 'unknown',
                upCount: h?.up_count ?? 0,
                total: h?.total ?? 0,
            });
        }
    } else if (range === '7d' || range === '30d') {
        for (let i = config.bars - 1; i >= 0; i--) {
            const d = subDays(now, i);
            const key = toUTCKey(d, 'day');
            const h = bucketMap.get(key);
            bars.push({
                label: format(d, 'MMM d, yyyy'),
                status: h ? bucketStatus(h.up_count, h.total) : 'unknown',
                upCount: h?.up_count ?? 0,
                total: h?.total ?? 0,
            });
        }
    } else {
        // 365d — monthly buckets
        for (let i = 11; i >= 0; i--) {
            const d = subMonths(now, i);
            const key = toUTCKey(d, 'month');
            const h = bucketMap.get(key);
            bars.push({
                label: format(d, 'MMM yyyy'),
                status: h ? bucketStatus(h.up_count, h.total) : 'unknown',
                upCount: h?.up_count ?? 0,
                total: h?.total ?? 0,
            });
        }
    }

    return bars;
}

function rangeEdgeLabels(range: TimeRange): [string, string] {
    switch (range) {
        case '24h':  return ['-24h', 'now'];
        case '7d':   return ['-7d', 'today'];
        case '30d':  return ['-30d', 'today'];
        case '365d': return ['-12mo', 'now'];
    }
}

// --- Components ---

function BarTooltip({ bar, visible }: { bar: BarData; visible: boolean }) {
    if (!visible) return null;

    const pct = bar.total > 0 ? ((bar.upCount / bar.total) * 100).toFixed(1) : null;

    return (
        <div className="absolute bottom-full left-1/2 -translate-x-1/2 mb-2 z-50 pointer-events-none">
            <div className="bg-neutral-800 border border-neutral-700 rounded-lg px-3 py-2 text-xs whitespace-nowrap shadow-xl">
                <div className="text-neutral-200 font-medium mb-0.5">{bar.label}</div>
                {bar.status === 'unknown' ? (
                    <div className="text-neutral-500">No data</div>
                ) : (
                    <>
                        <div className="text-neutral-400">{pct}% uptime</div>
                        <div className="text-neutral-500">{bar.upCount}/{bar.total} checks passed</div>
                    </>
                )}
            </div>
        </div>
    );
}

function HistoryBars({
    history,
    large,
    range,
}: {
    history?: HistoryBucket[];
    large?: boolean;
    range: TimeRange;
}) {
    const [hoveredIndex, setHoveredIndex] = useState<number | null>(null);
    const bars = buildBars(range, history);
    const h = large ? 'h-6' : 'h-3';
    const styleKey = large ? 'base' : 'compact';

    return (
        <div className={`flex gap-[2px] ${h} ${large ? '' : 'opacity-70'}`}>
            {bars.map((b, i) => (
                <div
                    key={i}
                    className="flex-1 relative"
                    onMouseEnter={() => setHoveredIndex(i)}
                    onMouseLeave={() => setHoveredIndex(null)}
                >
                    <div
                        className={`w-full h-full rounded-sm transition-transform duration-150 hover:scale-y-[1.3] origin-bottom ${BAR_STYLES[b.status][styleKey]}`}
                    />
                    <BarTooltip bar={b} visible={hoveredIndex === i} />
                </div>
            ))}
        </div>
    );
}

function TimeRangeSelector({
    value,
    onChange,
}: {
    value: TimeRange;
    onChange: (range: TimeRange) => void;
}) {
    return (
        <div className="flex bg-neutral-800/60 rounded-lg p-0.5 gap-0.5">
            {RANGE_OPTIONS.map((opt) => (
                <button
                    key={opt.value}
                    onClick={(e) => { e.stopPropagation(); onChange(opt.value); }}
                    className={`px-2 py-0.5 text-[10px] font-medium rounded-md transition-colors ${
                        value === opt.value
                            ? 'bg-neutral-700 text-white'
                            : 'text-neutral-500 hover:text-neutral-300'
                    }`}
                >
                    {opt.label}
                </button>
            ))}
        </div>
    );
}

function InlineNameEditor({ service, onRenamed }: { service: ServiceStatus; onRenamed: () => void }) {
    const [editing, setEditing] = useState(false);
    const [name, setName] = useState(service.name);
    const [saving, setSaving] = useState(false);
    const inputRef = useRef<HTMLInputElement>(null);

    useEffect(() => {
        if (editing) inputRef.current?.focus();
    }, [editing]);

    const save = async () => {
        const trimmed = name.trim();
        if (!trimmed || trimmed === service.name) {
            setName(service.name);
            setEditing(false);
            return;
        }
        setSaving(true);
        try {
            const listRes = await fetch('/api/services');
            const list = await listRes.json();
            const svc = list.find((s: { name: string }) => s.name === service.name);
            if (!svc) return;

            const res = await fetch('/api/services', {
                method: 'PATCH',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ id: svc.id, name: trimmed }),
            });
            if (res.ok) {
                setEditing(false);
                onRenamed();
            } else {
                const data = await res.json();
                alert(data.error || 'Rename failed');
                setName(service.name);
                setEditing(false);
            }
        } catch {
            setName(service.name);
            setEditing(false);
        } finally {
            setSaving(false);
        }
    };

    if (!editing) {
        return (
            <div className="flex items-center gap-1.5 min-w-0">
                <span className="text-sm text-neutral-300 font-medium group-hover:text-white transition-colors truncate">{service.name}</span>
                <button
                    onClick={(e) => { e.stopPropagation(); setEditing(true); }}
                    className="opacity-0 group-hover:opacity-60 hover:!opacity-100 transition-opacity text-neutral-400 hover:text-white shrink-0"
                    title="Rename"
                >
                    <Pencil size={11} />
                </button>
            </div>
        );
    }

    return (
        <div className="flex items-center gap-1.5 min-w-0" onClick={(e) => e.stopPropagation()}>
            <input
                ref={inputRef}
                type="text"
                value={name}
                onChange={(e) => setName(e.target.value)}
                onKeyDown={(e) => {
                    if (e.key === 'Enter') save();
                    if (e.key === 'Escape') { setName(service.name); setEditing(false); }
                }}
                onBlur={save}
                disabled={saving}
                className="bg-neutral-800 border border-neutral-600 rounded px-1.5 py-0.5 text-sm text-white font-medium focus:outline-none focus:border-neutral-400 w-24 min-w-0"
            />
            <button onClick={save} disabled={saving} className="text-emerald-500 hover:text-emerald-400 shrink-0">
                <Check size={13} />
            </button>
        </div>
    );
}

function DetailModal({
    service,
    onClose,
    onDelete,
    onRenamed,
    timeRange,
    onTimeRangeChange,
}: {
    service: ServiceStatus;
    onClose: () => void;
    onDelete: (name: string) => void;
    onRenamed: () => void;
    timeRange: TimeRange;
    onTimeRangeChange: (range: TimeRange) => void;
}) {
    const overlayRef = useRef<HTMLDivElement>(null);

    useEffect(() => {
        const handleKey = (e: KeyboardEvent) => {
            if (e.key === 'Escape') onClose();
        };
        document.addEventListener('keydown', handleKey);
        return () => document.removeEventListener('keydown', handleKey);
    }, [onClose]);

    const [leftLabel, rightLabel] = rangeEdgeLabels(timeRange);

    return (
        <div
            ref={overlayRef}
            className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm"
            onClick={(e) => {
                if (e.target === overlayRef.current) onClose();
            }}
        >
            <div className="bg-neutral-900 border border-neutral-700 rounded-2xl p-6 w-full max-w-lg mx-4 shadow-2xl">
                {/* Header */}
                <div className="flex items-center justify-between mb-5">
                    <div className="flex items-center gap-3">
                        <div className={`w-2.5 h-2.5 rounded-full shrink-0 ${service.status === 'up' ? 'bg-emerald-500 [box-shadow:0_0_8px_rgba(16,185,129,0.5)]' : 'bg-red-500 [box-shadow:0_0_8px_rgba(239,68,68,0.5)]'}`} />
                        <h2 className="text-lg font-semibold text-white">{service.name}</h2>
                        <button
                            onClick={() => {
                                const newName = prompt('Rename service:', service.name);
                                if (newName && newName.trim() && newName.trim() !== service.name) {
                                    (async () => {
                                        const listRes = await fetch('/api/services');
                                        const list = await listRes.json();
                                        const svc = list.find((s: { name: string }) => s.name === service.name);
                                        if (!svc) return;
                                        const res = await fetch('/api/services', {
                                            method: 'PATCH',
                                            headers: { 'Content-Type': 'application/json' },
                                            body: JSON.stringify({ id: svc.id, name: newName.trim() }),
                                        });
                                        if (res.ok) { onRenamed(); onClose(); }
                                    })();
                                }
                            }}
                            className="text-neutral-500 hover:text-neutral-300 transition-colors"
                            title="Rename"
                        >
                            <Pencil size={14} />
                        </button>
                    </div>
                    <button onClick={onClose} className="text-neutral-500 hover:text-white transition-colors p-1 rounded-lg hover:bg-neutral-800">
                        <X size={18} />
                    </button>
                </div>

                {/* URL */}
                <div className="flex items-center gap-2 mb-5 text-xs text-neutral-500 font-mono bg-neutral-800/50 rounded-lg px-3 py-2">
                    <ExternalLink size={12} className="shrink-0" />
                    <span className="truncate">{service.url}</span>
                </div>

                {/* Status + Latency Row */}
                <div className="grid grid-cols-2 gap-3 mb-5">
                    <div className="bg-neutral-800/50 rounded-xl p-3">
                        <div className="text-[10px] uppercase tracking-wider text-neutral-500 mb-1">Status</div>
                        <span className={`text-sm font-semibold ${service.status === 'up' ? 'text-emerald-400' : 'text-red-400'}`}>
                            {service.status === 'up' ? 'Operational' : 'Down'}
                        </span>
                    </div>
                    <div className="bg-neutral-800/50 rounded-xl p-3">
                        <div className="text-[10px] uppercase tracking-wider text-neutral-500 mb-1">Current Latency</div>
                        <span className="text-sm font-semibold text-white font-mono">{service.latency}ms</span>
                    </div>
                </div>

                {/* Uptime Stats */}
                <div className="grid grid-cols-4 gap-3 mb-5">
                    <div className="bg-neutral-800/50 rounded-xl p-3 text-center">
                        <div className="text-[10px] uppercase tracking-wider text-neutral-500 mb-1">24h</div>
                        <span className="text-base font-bold text-white">{service.uptime24h ?? 100}%</span>
                    </div>
                    <div className="bg-neutral-800/50 rounded-xl p-3 text-center">
                        <div className="text-[10px] uppercase tracking-wider text-neutral-500 mb-1">7d</div>
                        <span className="text-base font-bold text-white">{service.uptime7d ?? 100}%</span>
                    </div>
                    <div className="bg-neutral-800/50 rounded-xl p-3 text-center">
                        <div className="text-[10px] uppercase tracking-wider text-neutral-500 mb-1">Lifetime</div>
                        <span className="text-base font-bold text-white">{service.uptimeLifetime ?? 100}%</span>
                    </div>
                    <div className="bg-neutral-800/50 rounded-xl p-3 text-center">
                        <div className="text-[10px] uppercase tracking-wider text-neutral-500 mb-1">Avg Lat</div>
                        <span className="text-base font-bold text-white font-mono">{service.avgLatency24h ?? 0}ms</span>
                    </div>
                </div>

                {/* History Bar (large) */}
                <div className="mb-2">
                    <div className="flex items-center justify-between mb-2">
                        <div className="text-[10px] uppercase tracking-wider text-neutral-500">History</div>
                        <TimeRangeSelector value={timeRange} onChange={onTimeRangeChange} />
                    </div>
                    <HistoryBars history={service.history} large range={timeRange} />
                    <div className="flex justify-between text-[9px] text-neutral-600 font-mono mt-1">
                        <span>{leftLabel}</span>
                        <span>{rightLabel}</span>
                    </div>
                </div>

                {/* Legend */}
                <div className="flex gap-4 text-[9px] text-neutral-500 mb-2">
                    <span className="flex items-center gap-1"><span className="w-2 h-2 rounded-sm bg-emerald-500 inline-block" /> Up</span>
                    <span className="flex items-center gap-1"><span className="w-2 h-2 rounded-sm bg-amber-500 inline-block" /> Degraded</span>
                    <span className="flex items-center gap-1"><span className="w-2 h-2 rounded-sm bg-red-500 inline-block" /> Down</span>
                    <span className="flex items-center gap-1"><span className="w-2 h-2 rounded-sm bg-neutral-700 inline-block" /> No data</span>
                </div>

                {/* Delete Button */}
                <div className="mt-5 pt-4 border-t border-neutral-800">
                    <button
                        onClick={() => { onDelete(service.name); onClose(); }}
                        className="flex items-center gap-2 text-xs text-red-400/70 hover:text-red-400 transition-colors"
                    >
                        <Trash2 size={13} />
                        Remove service
                    </button>
                </div>
            </div>
        </div>
    );
}

function AddServiceForm({ onAdded }: { onAdded: () => void }) {
    const [open, setOpen] = useState(false);
    const [name, setName] = useState('');
    const [url, setUrl] = useState('');
    const [submitting, setSubmitting] = useState(false);
    const [error, setError] = useState('');

    const handleSubmit = async (e: React.FormEvent) => {
        e.preventDefault();
        setError('');
        setSubmitting(true);
        try {
            const res = await fetch('/api/services', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ name: name.trim(), url: url.trim() }),
            });
            if (!res.ok) {
                const data = await res.json();
                throw new Error(data.error || 'Failed to add');
            }
            setName('');
            setUrl('');
            setOpen(false);
            onAdded();
        } catch (err: unknown) {
            setError(err instanceof Error ? err.message : 'Failed to add service');
        } finally {
            setSubmitting(false);
        }
    };

    if (!open) {
        return (
            <button
                onClick={() => setOpen(true)}
                className="flex items-center gap-1.5 text-xs text-neutral-500 hover:text-neutral-300 transition-colors pt-2"
            >
                <Plus size={14} />
                Add service
            </button>
        );
    }

    return (
        <form onSubmit={handleSubmit} className="space-y-2 pt-2">
            <div className="flex gap-2">
                <input
                    type="text"
                    placeholder="Name"
                    value={name}
                    onChange={(e) => setName(e.target.value)}
                    required
                    autoFocus
                    className="flex-1 bg-neutral-800 border border-neutral-700 rounded-lg px-2.5 py-1.5 text-xs text-white placeholder-neutral-500 focus:outline-none focus:border-neutral-500"
                />
                <input
                    type="url"
                    placeholder="https://example.com"
                    value={url}
                    onChange={(e) => setUrl(e.target.value)}
                    required
                    className="flex-[2] bg-neutral-800 border border-neutral-700 rounded-lg px-2.5 py-1.5 text-xs text-white placeholder-neutral-500 focus:outline-none focus:border-neutral-500"
                />
            </div>
            {error && <p className="text-[10px] text-red-400">{error}</p>}
            <div className="flex gap-2">
                <button
                    type="submit"
                    disabled={submitting}
                    className="text-xs bg-neutral-700 hover:bg-neutral-600 text-white px-3 py-1.5 rounded-lg transition-colors disabled:opacity-50"
                >
                    {submitting ? 'Adding...' : 'Add'}
                </button>
                <button
                    type="button"
                    onClick={() => { setOpen(false); setError(''); }}
                    className="text-xs text-neutral-500 hover:text-neutral-300 px-2 py-1.5 transition-colors"
                >
                    Cancel
                </button>
            </div>
        </form>
    );
}

export function UptimeCard() {
    const [services, setServices] = useState<ServiceStatus[]>([]);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(false);
    const [selectedService, setSelectedService] = useState<ServiceStatus | null>(null);
    const [expanded, setExpanded] = useState(false);
    const [timeRange, setTimeRange] = useState<TimeRange>('24h');

    const fetchStatus = useCallback(async (range?: TimeRange) => {
        try {
            const r = range ?? timeRange;
            const res = await fetch(`/api/status?range=${r}`);
            if (!res.ok) throw new Error('Failed to fetch');
            const data = await res.json();
            setServices(data);
            setError(false);
        } catch (e) {
            console.error(e);
            setError(true);
        } finally {
            setLoading(false);
        }
    }, [timeRange]);

    useEffect(() => {
        fetchStatus();
        const interval = setInterval(() => fetchStatus(), 30000);
        return () => clearInterval(interval);
    }, [fetchStatus]);

    const handleTimeRangeChange = useCallback((range: TimeRange) => {
        setTimeRange(range);
        fetchStatus(range);
    }, [fetchStatus]);

    const handleDelete = async (serviceName: string) => {
        try {
            const listRes = await fetch('/api/services');
            const list = await listRes.json();
            const svc = list.find((s: { name: string }) => s.name === serviceName);
            if (!svc) return;

            await fetch('/api/services', {
                method: 'DELETE',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ id: svc.id }),
            });
            fetchStatus();
        } catch (e) {
            console.error('Delete failed:', e);
        }
    };

    const rowSpan = expanded ? 'row-span-2' : 'row-span-1';
    const [leftLabel, rightLabel] = rangeEdgeLabels(timeRange);

    return (
        <>
            <div className={`col-span-1 md:col-span-2 lg:col-span-2 ${rowSpan} bg-neutral-900 border border-neutral-800 rounded-xl p-5 flex flex-col hover:border-neutral-700 transition-all duration-300 overflow-hidden`}>
                {/* Header */}
                <div className="flex justify-between items-center shrink-0 mb-3">
                    <div className="flex items-center gap-2 text-neutral-400">
                        <Activity size={18} />
                        <span className="text-sm font-medium">Uptime Monitor</span>
                        {loading && <RefreshCcw size={12} className="animate-spin ml-2 opacity-50" />}
                    </div>
                    <div className="flex items-center gap-2">
                        <TimeRangeSelector value={timeRange} onChange={handleTimeRangeChange} />
                        <button
                            onClick={() => setExpanded(!expanded)}
                            className="text-neutral-500 hover:text-neutral-300 transition-colors p-1 rounded-lg hover:bg-neutral-800"
                            title={expanded ? 'Collapse' : 'Expand'}
                        >
                            {expanded ? <ChevronUp size={16} /> : <ChevronDown size={16} />}
                        </button>
                    </div>
                </div>

                {error ? (
                    <div className="flex flex-col items-center justify-center flex-1 text-red-400 gap-2">
                        <AlertCircle size={24} />
                        <span className="text-xs">Failed to load status</span>
                    </div>
                ) : (
                    <div className="flex-1 overflow-y-auto min-h-0 space-y-3 pr-1 scrollbar-thin">
                        {services.map((service) => (
                            <div
                                key={service.name}
                                className="flex flex-col gap-1 cursor-pointer group rounded-lg hover:bg-neutral-800/40 px-2 py-1.5 -mx-2 transition-colors"
                                onClick={() => setSelectedService(service)}
                            >
                                <div className="flex items-center justify-between gap-2">
                                    <InlineNameEditor service={service} onRenamed={fetchStatus} />
                                    <div className="flex items-center gap-2 shrink-0">
                                        <span className={`text-xs px-1.5 py-0.5 rounded ${service.status === 'up' ? 'bg-emerald-500/10 text-emerald-500' : 'bg-red-500/10 text-red-500'}`}>
                                            {service.status === 'up' ? 'UP' : 'DOWN'}
                                        </span>
                                        <span className="text-xs text-neutral-500 font-mono w-10 text-right">{service.latency}ms</span>
                                    </div>
                                </div>
                                <HistoryBars history={service.history} range={timeRange} />
                                <div className="flex justify-between text-[10px] text-neutral-600 font-mono">
                                    <span>{leftLabel}</span>
                                    <span>{service.uptime24h ?? 100}% uptime (24h)</span>
                                    <span>{rightLabel}</span>
                                </div>
                            </div>
                        ))}

                        <AddServiceForm onAdded={fetchStatus} />
                    </div>
                )}
            </div>

            {selectedService && (
                <DetailModal
                    service={selectedService}
                    onClose={() => setSelectedService(null)}
                    onDelete={handleDelete}
                    onRenamed={fetchStatus}
                    timeRange={timeRange}
                    onTimeRangeChange={handleTimeRangeChange}
                />
            )}
        </>
    );
}
