import { useEffect, useState, useRef, useCallback } from 'react';
import axios from 'axios';
import { Activity, AlertCircle, Clock, Globe, User, Loader2 } from 'lucide-react';
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@admin/components/ui/dialog';
import { Badge } from '@admin/components/ui/badge';
import { Button } from '@admin/components/ui/button';
import { format } from 'date-fns';

interface ActivityLog {
  id: number;
  user: { id: number; name: string; email: string } | null;
  module: { id: number; name: string } | null;
  action: string;
  description: string | null;
  ip_address: string | null;
  properties: Record<string, any> | null;
  created_at: string;
}

interface CursorMeta {
  per_page: number;
  next_cursor?: string | null;
  prev_cursor?: string | null;
  has_more: boolean;
  total?: number;
  remaining?: number;
  model_class?: string;
  model_id?: number | string | null;
}

interface ModelActivityLogModalProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  modelClass: string;
  modelId?: number | string;
  perPage?: number;
  title?: string;
  action?: string;
  actions?: string[];
  settingKey?: string;
  onClearFilters?: () => void;
}

export const ModelActivityLogModal = ({ open, onOpenChange, modelClass, modelId, perPage = 10, title, action, actions, settingKey, onClearFilters }: ModelActivityLogModalProps) => {
  const [logs, setLogs] = useState<ActivityLog[]>([]);
  const [meta, setMeta] = useState<CursorMeta | null>(null);
  const [loading, setLoading] = useState(false);
  const [loadingMore, setLoadingMore] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [cursor, setCursor] = useState<string | undefined>();
  const sentinelRef = useRef<HTMLDivElement | null>(null);
  const scrollRef = useRef<HTMLDivElement | null>(null);
  const observerRef = useRef<IntersectionObserver | null>(null);

  const fetchLogs = async (cursorParam?: string, append = false) => {
    try {
      append ? setLoadingMore(true) : setLoading(true);
    const response = await axios.get(route('activity-log.action', modelClass), {
        params: {
          per_page: perPage,
          model_id: modelId,
      // support single action or multiple actions
      action: actions && actions.length ? actions : action,
          setting_key: settingKey,
          ...(cursorParam ? { cursor: cursorParam } : {}),
        },
      });
      const { data, meta } = response.data;
      setLogs(prev => (append ? [...prev, ...data] : data));
      setMeta(meta);
      setCursor(meta?.next_cursor || undefined);
      setError(null);
    } catch (e) {
      console.error(e);
      setError('Failed to load activity logs');
    } finally {
      setLoading(false);
      setLoadingMore(false);
    }
  };

  // Reset and load when modal opens or identifiers change
  useEffect(() => {
    if (open) {
      setLogs([]);
      setMeta(null);
      setCursor(undefined);
      fetchLogs();
    }
  }, [open, modelClass, modelId, perPage, action, actions, settingKey]);

  const loadMore = () => {
    if (meta?.has_more && cursor) fetchLogs(cursor, true);
  };

  const handleIntersect = useCallback((entries: IntersectionObserverEntry[]) => {
    const first = entries[0];
    if (first.isIntersecting) loadMore();
  }, [cursor, meta?.has_more, loadingMore]);

  useEffect(() => {
    if (!sentinelRef.current) return;
    if (!(meta?.has_more && cursor)) {
      observerRef.current?.disconnect();
      return;
    }
    observerRef.current = new IntersectionObserver(handleIntersect, {
      root: scrollRef.current,
      rootMargin: '120px',
      threshold: 0.05,
    });
    observerRef.current.observe(sentinelRef.current);
    return () => observerRef.current?.disconnect();
  }, [handleIntersect, meta?.has_more, cursor]);

  const formatDate = (value: string) => {
    try { return format(new Date(value), 'MMM dd, yyyy HH:mm'); } catch { return value; }
  };

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="max-w-2xl">
        <DialogHeader>
          <DialogTitle className="flex items-center gap-2">
            <Activity className="w-5 h-5" />
            {title || 'Activity Log'}
            <Badge variant="secondary" className="ml-auto">{logs.length}{meta?.total !== undefined && ` / ${meta.total}`}</Badge>
          </DialogTitle>
        </DialogHeader>
        <div className="mt-2">
          {(action || (actions && actions.length) || settingKey) && (
            <div className="mb-3 flex flex-wrap items-center gap-2 text-xs">
              <Badge variant="outline" className="bg-amber-50 border-amber-300 text-amber-700 flex items-center gap-1">
                Filtered
                {actions && actions.length > 0 ? (
                  <span className="font-mono">actions=[{actions.join(', ')}]</span>
                ) : (
                  action && <span className="font-mono">action={action}</span>
                )}
                {settingKey && <span className="font-mono">key={settingKey}</span>}
              </Badge>
              {onClearFilters && (
                <Button size="sm" variant="ghost" className="h-6 px-2" onClick={onClearFilters}>Clear</Button>
              )}
            </div>
          )}
          {error && (
            <div className="p-4 border rounded bg-red-50 text-red-700 text-sm flex items-center gap-2">
              <AlertCircle className="w-4 h-4" /> {error}
              <Button size="sm" variant="outline" onClick={() => fetchLogs()}>Retry</Button>
            </div>
          )}
          {!error && (
            <div ref={scrollRef} className="max-h-[60vh] overflow-y-auto pr-1 space-y-3 custom-scrollbar">
              {loading && logs.length === 0 && (
                <div className="flex items-center justify-center py-8 text-sm text-gray-500">
                  <Loader2 className="w-4 h-4 mr-2 animate-spin" /> Loading...
                </div>
              )}
              {logs.map(log => (
                <div key={log.id} className="border rounded p-3 bg-white shadow-sm">
                  <div className="flex items-center gap-2 mb-1">
                    <Badge variant="outline" className="capitalize">{log.action}</Badge>
                    {log.module && <Badge variant="outline" className="bg-blue-50 border-blue-200 text-blue-700">{log.module.name}</Badge>}
                    <span className="text-xs text-gray-500 ml-auto flex items-center gap-1"><Clock className="w-3 h-3" /> {formatDate(log.created_at)}</span>
                  </div>
                  <div className="text-sm text-gray-800 mb-1">{log.description || 'No description'}</div>
                  <div className="flex flex-wrap gap-3 text-xs text-gray-500 mb-1">
                    {log.ip_address && <span className="flex items-center gap-1"><Globe className="w-3 h-3" />{log.ip_address}</span>}
                    {log.user && <span className="flex items-center gap-1"><User className="w-3 h-3" />{log.user.name || log.user.email}</span>}
                  </div>
                  {log.properties && Object.keys(log.properties).length > 0 && (
                    <details className="mt-1">
                      <summary className="cursor-pointer text-xs text-gray-600 hover:text-gray-800">Properties</summary>
                      <pre className="mt-1 text-[11px] bg-gray-50 p-2 rounded whitespace-pre-wrap font-mono">{JSON.stringify(log.properties, null, 2)}</pre>
                    </details>
                  )}
                </div>
              ))}

              {meta?.has_more && (
                <div className="py-3">
                  <div ref={sentinelRef} className="h-2" />
                  {!('IntersectionObserver' in window) && (
                    <div className="text-center">
                      <Button size="sm" onClick={loadMore} disabled={loadingMore} variant="outline" className="w-full">
                        {loadingMore ? <><Loader2 className="w-4 h-4 mr-2 animate-spin" /> Loading...</> : 'Load More'}
                      </Button>
                    </div>
                  )}
                  {loadingMore && (
                    <div className="flex items-center justify-center py-2 text-xs text-gray-500">
                      <Loader2 className="w-3 h-3 mr-2 animate-spin" /> Loading more...
                    </div>
                  )}
                </div>
              )}

              {!loading && logs.length === 0 && (
                <div className="py-10 text-center text-sm text-gray-500">
                  <Activity className="w-10 h-10 mx-auto mb-2 text-gray-300" />
                  No activity logs found.
                </div>
              )}
            </div>
          )}
          <div className="pt-3 text-center text-xs text-gray-500">
            Loaded {logs.length}{meta?.total !== undefined && ` of ${meta.total}`}{meta?.remaining !== undefined && meta.remaining > 0 && ` • ${meta.remaining} more`}
          </div>
        </div>
      </DialogContent>
    </Dialog>
  );
};
