'use client';

import { useState, useEffect, useMemo } from 'react';
import {
  Dialog,
  DialogContent,
  DialogClose,
} from '@/components/ui/dialog';
import {
  Collapsible,
  CollapsibleContent,
  CollapsibleTrigger,
} from '@/components/ui/collapsible';
import { Badge } from '@/components/ui/badge';
import { Separator } from '@/components/ui/separator';
import { 
  Ticket as TicketIcon,
  User,
  Calendar,
  Clock,
  AlertCircle,
  CheckCircle,
  ExternalLink,
  Loader2,
  ChevronRight,
  MessageSquare,
  Timer,
  Bot,
  UserCircle,
  Mail,
  X,
} from 'lucide-react';
import { useUserTimezone } from '@/lib/hooks/use-user-timezone';

// noteType values that are system/automated (workflow rules, monitoring, auto-close, etc.)
const SYSTEM_NOTE_TYPES = new Set([13, 91, 93, 94, 99, 101]);
// publish=2 means Internal Users Only in Autotask
const INTERNAL_PUBLISH = 2;
// noteType=2 is Service Desk Notification (email communication)
const EMAIL_NOTE_TYPE = 2;

const URL_REGEX = /https?:\/\/[^\s<>"'\[\]()]+/g;

function renderTextWithLinks(text: string): React.ReactNode[] {
  const parts: React.ReactNode[] = [];
  let lastIndex = 0;
  let match: RegExpExecArray | null;
  URL_REGEX.lastIndex = 0;
  while ((match = URL_REGEX.exec(text)) !== null) {
    if (match.index > lastIndex) {
      // Strip orphaned bracket that wraps the URL e.g. "link [https://..."
      const before = text.slice(lastIndex, match.index).replace(/\s*\[$/, ' ');
      if (before) parts.push(before);
    }
    const url = match[0].replace(/[.,;:!?]+$/, '');
    const label = 'link';
    parts.push(
      <a
        key={match.index}
        href={url}
        target="_blank"
        rel="noopener noreferrer"
        className="text-blue-500 hover:underline"
      >
        {label}
      </a>
    );
    lastIndex = match.index + match[0].length;
    // Consume trailing bracket/paren that closed around the URL
    if (lastIndex < text.length && /^[\])]/.test(text[lastIndex])) lastIndex++;
  }
  if (lastIndex < text.length) parts.push(text.slice(lastIndex));
  return parts;
}

function LinkedText({ text, className }: { text: string; className?: string }) {
  const lines = text.split('\n');
  return (
    <span className={className}>
      {lines.map((line, i) => (
        <span key={i}>
          {renderTextWithLinks(line)}
          {i < lines.length - 1 && <br />}
        </span>
      ))}
    </span>
  );
}

interface TicketDetailModalProps {
  ticketNumber: string;
  open: boolean;
  onOpenChange: (open: boolean) => void;
}

type TimelineItem =
  | { kind: 'note'; ts: number; data: any }
  | { kind: 'time'; ts: number; data: any };

export function TicketDetailModal({ ticketNumber, open, onOpenChange }: TicketDetailModalProps) {
  const tz = useUserTimezone();
  const [ticket, setTicket] = useState<any>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const [notes, setNotes] = useState<any[]>([]);
  const [timeEntries, setTimeEntries] = useState<any[]>([]);
  const [timelineLoading, setTimelineLoading] = useState(false);
  const [timelineOpen, setTimelineOpen] = useState(false);
  const [timelineFetched, setTimelineFetched] = useState(false);
  const [showSystem, setShowSystem] = useState(false);
  const [showInternal, setShowInternal] = useState(false);

  const fetchTicketDetails = async () => {
    setLoading(true);
    setError(null);
    setTicket(null);
    setNotes([]);
    setTimeEntries([]);
    setTimelineFetched(false);
    setTimelineOpen(false);
    setShowSystem(false);
    setShowInternal(false);
    try {
      const response = await fetch(`/api/tickets/by-number/${encodeURIComponent(ticketNumber)}`);
      if (response.ok) {
        const data = await response.json();
        setTicket(data.ticket);
      } else if (response.status === 404) {
        setError(`Ticket ${ticketNumber} not found`);
      } else {
        setError('Failed to fetch ticket details');
      }
    } catch (err) {
      setError('Failed to fetch ticket');
      console.error('Error fetching ticket:', err);
    } finally {
      setLoading(false);
    }
  };

  const fetchTimeline = async (ticketId: number) => {
    if (timelineFetched) return;
    setTimelineLoading(true);
    try {
      const [notesRes, timeRes] = await Promise.all([
        fetch(`/api/tickets/${ticketId}/notes`),
        fetch(`/api/tickets/${ticketId}/time-entries`),
      ]);
      if (notesRes.ok) setNotes((await notesRes.json()).notes || []);
      if (timeRes.ok) setTimeEntries((await timeRes.json()).timeEntries || []);
    } catch (err) {
      console.error('Error fetching timeline:', err);
    } finally {
      setTimelineLoading(false);
      setTimelineFetched(true);
    }
  };

  useEffect(() => {
    if (open && ticketNumber) fetchTicketDetails();
  }, [open, ticketNumber]);

  // Build merged, sorted timeline
  const timeline = useMemo<TimelineItem[]>(() => {
    const items: TimelineItem[] = [
      ...notes.map((n) => ({
        kind: 'note' as const,
        ts: new Date(n.createDateTime || 0).getTime(),
        data: n,
      })),
      ...timeEntries.map((e) => ({
        kind: 'time' as const,
        ts: new Date(e.dateWorked || 0).getTime(),
        data: e,
      })),
    ];
    return items.sort((a, b) => b.ts - a.ts);
  }, [notes, timeEntries]);

  const visibleTimeline = useMemo(
    () =>
      timeline.filter((item) => {
        if (item.kind === 'time') return true;
        const n = item.data;
        if (!showSystem && SYSTEM_NOTE_TYPES.has(n.noteType)) return false;
        if (!showInternal && n.publish === INTERNAL_PUBLISH) return false;
        return true;
      }),
    [timeline, showSystem, showInternal]
  );

  const systemCount = useMemo(
    () =>
      timeline.filter(
        (item) => item.kind === 'note' && SYSTEM_NOTE_TYPES.has(item.data.noteType)
      ).length,
    [timeline]
  );

  const internalCount = useMemo(
    () =>
      timeline.filter(
        (item) => item.kind === 'note' && item.data.publish === INTERNAL_PUBLISH && !SYSTEM_NOTE_TYPES.has(item.data.noteType)
      ).length,
    [timeline]
  );

  const totalHours = timeEntries.reduce((sum, e) => sum + (e.hoursWorked || 0), 0);

  const getStatusBadge = (status: number, label?: string | null) => {
    const resolved = label || `Status ${status}`;
    const lower = resolved.toLowerCase();
    const variant =
      lower.includes('complete') || lower.includes('closed') || lower.includes('resolved') ? 'secondary' :
      lower.includes('progress') || lower.includes('waiting') ? 'default' :
      lower.includes('new') ? 'default' : 'outline';
    return <Badge variant={variant}>{resolved}</Badge>;
  };

  const getPriorityBadge = (priority: number, label?: string | null) => {
    const resolved = label || `Priority ${priority}`;
    const lower = resolved.toLowerCase();
    const variant: 'destructive' | 'default' | 'secondary' | 'outline' =
      lower.includes('critical') || lower.includes('high') ? 'destructive' :
      lower.includes('medium') ? 'default' :
      lower.includes('low') ? 'secondary' : 'outline';
    return <Badge variant={variant}>{resolved}</Badge>;
  };

  const formatDate = (dateString?: string) => {
    if (!dateString) return 'N/A';
    return new Date(dateString).toLocaleString('en-US', {
      month: 'short', day: 'numeric', year: 'numeric',
      hour: '2-digit', minute: '2-digit', timeZone: tz,
    });
  };

  const formatHours = (hours?: number) => {
    if (!hours) return '0h';
    return `${hours.toFixed(2)}h`;
  };

  const autotaskUrl = ticket
    ? `https://ww1.autotask.net/Mvc/ServiceDesk/TicketDetail.mvc?workspace=False&ids%5B0%5D=${ticket.id}&ticketId=${ticket.id}`
    : null;

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent
        showCloseButton={false}
        className="max-w-4xl w-[90vw] h-[85vh] flex flex-col p-0 gap-0 overflow-hidden"
      >
        {/* Sticky header */}
        <div className="flex items-center gap-2 px-4 py-3 border-b shrink-0 min-w-0">
          <TicketIcon className="h-4 w-4 shrink-0 text-muted-foreground" />
          <span className="font-mono text-sm font-semibold text-blue-600 dark:text-blue-400 shrink-0">{ticketNumber}</span>
          <span className="text-sm text-muted-foreground truncate flex-1 min-w-0">
            {ticket?.title ?? (loading ? 'Loading…' : '')}
          </span>
          <div className="flex items-center gap-1 shrink-0 ml-2">
            {autotaskUrl && (
              <a
                href={autotaskUrl}
                target="_blank"
                rel="noopener noreferrer"
                title="Open in Autotask"
                className="inline-flex h-7 w-7 items-center justify-center rounded-sm opacity-70 hover:opacity-100 transition-opacity"
              >
                <ExternalLink className="h-4 w-4" />
              </a>
            )}
            <DialogClose className="inline-flex h-7 w-7 items-center justify-center rounded-sm opacity-70 hover:opacity-100 transition-opacity">
              <X className="h-4 w-4" />
              <span className="sr-only">Close</span>
            </DialogClose>
          </div>
        </div>

        {/* Scrollable body */}
        <div className="flex-1 overflow-y-auto overflow-x-hidden min-w-0 p-4">

        {loading && (
          <div className="flex items-center justify-center py-6">
            <Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
          </div>
        )}

        {error && (
          <div className="flex items-center gap-2 p-3 bg-destructive/10 text-destructive rounded-lg text-sm">
            <AlertCircle className="h-4 w-4 shrink-0" />
            <span>{error}</span>
          </div>
        )}

        {ticket && !loading && (
          <div className="space-y-3 min-w-0 overflow-hidden">
            {/* Metadata */}
            <div className="flex flex-wrap items-center gap-2 text-sm">
              {getStatusBadge(ticket.status, ticket.statusLabel)}
              {getPriorityBadge(ticket.priority, ticket.priorityLabel)}
              {ticket.assignedResourceName && (
                <span className="flex items-center gap-1 text-muted-foreground">
                  <User className="h-3 w-3" />
                  {ticket.assignedResourceName}
                </span>
              )}
            </div>

            {/* Dates */}
            <div className="grid grid-cols-2 gap-x-6 gap-y-1 text-sm">
              <div className="flex items-center gap-1.5 text-muted-foreground">
                <Calendar className="h-3 w-3 shrink-0" />
                <span>Created</span>
                <span className="text-foreground font-medium">{formatDate(ticket.createDate)}</span>
              </div>
              {ticket.dueDateTime && (
                <div className="flex items-center gap-1.5 text-muted-foreground">
                  <Clock className="h-3 w-3 shrink-0" />
                  <span>Due</span>
                  <span className="text-foreground font-medium">{formatDate(ticket.dueDateTime)}</span>
                </div>
              )}
              {ticket.resolvedDateTime && (
                <div className="flex items-center gap-1.5 text-muted-foreground">
                  <CheckCircle className="h-3 w-3 shrink-0" />
                  <span>Resolved</span>
                  <span className="text-foreground font-medium">{formatDate(ticket.resolvedDateTime)}</span>
                </div>
              )}
              {ticket.purchaseOrderNumber && (
                <div className="flex items-center gap-1.5 text-muted-foreground">
                  <span>PO</span>
                  <span className="text-foreground font-medium">{ticket.purchaseOrderNumber}</span>
                </div>
              )}
            </div>

            <Separator />

            {/* Description */}
            {ticket.description && (
              <div>
                <p className="text-xs font-semibold text-muted-foreground uppercase tracking-wide mb-1">Description</p>
                <div className="p-3 bg-muted rounded-lg text-sm [overflow-wrap:anywhere]">
                  <LinkedText text={ticket.description} />
                </div>
              </div>
            )}

            {/* Resolution */}
            {ticket.resolution && (
              <div>
                <p className="text-xs font-semibold text-muted-foreground uppercase tracking-wide mb-1">Resolution</p>
                <div className="p-3 bg-muted rounded-lg text-sm [overflow-wrap:anywhere]">
                  <LinkedText text={ticket.resolution} />
                </div>
              </div>
            )}

            <Separator />

            {/* Timeline collapsible */}
            <Collapsible
              open={timelineOpen}
              onOpenChange={(val) => {
                setTimelineOpen(val);
                if (val && ticket) fetchTimeline(ticket.id);
              }}
            >
              <CollapsibleTrigger asChild>
                <button className="flex w-full items-center justify-between py-1 text-sm font-medium hover:text-foreground text-muted-foreground transition-colors">
                  <span className="flex items-center gap-2">
                    <Clock className="h-4 w-4" />
                    Activity Timeline
                    {timelineFetched && (
                      <>
                        <Badge variant="secondary" className="text-xs px-1.5 py-0">
                          {visibleTimeline.length}
                        </Badge>
                        {totalHours > 0 && (
                          <span className="text-xs text-muted-foreground">{formatHours(totalHours)} logged</span>
                        )}
                      </>
                    )}
                  </span>
                  <ChevronRight className={`h-4 w-4 transition-transform duration-200 ${timelineOpen ? 'rotate-90' : ''}`} />
                </button>
              </CollapsibleTrigger>

              <CollapsibleContent className="pt-2">
                {timelineLoading && (
                  <div className="flex items-center gap-2 text-sm text-muted-foreground py-3">
                    <Loader2 className="h-3 w-3 animate-spin" />
                    Loading activity…
                  </div>
                )}

                {!timelineLoading && timelineFetched && (
                  <>
                    {/* Toggles for system / internal notes */}
                    {(systemCount > 0 || internalCount > 0) && (
                      <div className="flex items-center justify-end gap-3 mb-2">
                        {internalCount > 0 && (
                          <button
                            onClick={() => setShowInternal((v) => !v)}
                            className="flex items-center gap-1.5 text-xs text-muted-foreground hover:text-foreground transition-colors"
                          >
                            <UserCircle className="h-3 w-3" />
                            {showInternal ? 'Hide' : 'Show'} internal notes
                            <Badge variant="outline" className="text-xs px-1.5 py-0">{internalCount}</Badge>
                          </button>
                        )}
                        {systemCount > 0 && (
                          <button
                            onClick={() => setShowSystem((v) => !v)}
                            className="flex items-center gap-1.5 text-xs text-muted-foreground hover:text-foreground transition-colors"
                          >
                            <Bot className="h-3 w-3" />
                            {showSystem ? 'Hide' : 'Show'} system notes
                            <Badge variant="outline" className="text-xs px-1.5 py-0">{systemCount}</Badge>
                          </button>
                        )}
                      </div>
                    )}

                    {visibleTimeline.length === 0 && (
                      <p className="text-sm text-muted-foreground py-1">No activity found.</p>
                    )}

                    {/* Timeline items */}
                    <div className="relative space-y-0">
                      {visibleTimeline.map((item, idx) => {
                        const isLast = idx === visibleTimeline.length - 1;
                        const isSystem = item.kind === 'note' && SYSTEM_NOTE_TYPES.has(item.data.noteType);

                        if (item.kind === 'time') {
                          const e = item.data;
                          return (
                            <div key={`time-${e.id}`} className="flex gap-3">
                              <div className="flex flex-col items-center">
                                <div className="mt-1 flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-blue-100 dark:bg-blue-900/40 text-blue-600 dark:text-blue-400">
                                  <Timer className="h-3 w-3" />
                                </div>
                                {!isLast && <div className="w-px flex-1 bg-border my-1" />}
                              </div>
                              <div className={`pb-4 min-w-0 w-0 flex-1 ${isLast ? '' : ''}`}>
                                <div className="flex items-center justify-between gap-2 mb-0.5">
                                  <span className="text-xs font-medium">{e.resourceName || 'Unknown'}</span>
                                  <div className="flex items-center gap-1.5 shrink-0">
                                    <Badge variant="outline" className="text-xs px-1.5 py-0">{formatHours(e.hoursWorked)}</Badge>
                                    <span className="text-xs text-muted-foreground">{formatDate(e.dateWorked)}</span>
                                  </div>
                                </div>
                                {e.summaryNotes && (
                                  <p className="text-xs text-muted-foreground [overflow-wrap:anywhere]">
                                    <LinkedText text={e.summaryNotes} />
                                  </p>
                                )}
                              </div>
                            </div>
                          );
                        }

                        // note
                        const n = item.data;
                        return (
                          <div key={`note-${n.id}`} className="flex gap-3">
                            <div className="flex flex-col items-center">
                              <div className={`mt-1 flex h-6 w-6 shrink-0 items-center justify-center rounded-full ${
                                isSystem
                                  ? 'bg-muted text-muted-foreground'
                                  : n.noteType === EMAIL_NOTE_TYPE
                                  ? 'bg-violet-100 dark:bg-violet-900/40 text-violet-600 dark:text-violet-400'
                                  : 'bg-emerald-100 dark:bg-emerald-900/40 text-emerald-600 dark:text-emerald-400'
                              }`}>
                                {isSystem ? <Bot className="h-3 w-3" /> : n.noteType === EMAIL_NOTE_TYPE ? <Mail className="h-3 w-3" /> : <UserCircle className="h-3 w-3" />}
                              </div>
                              {!isLast && <div className="w-px flex-1 bg-border my-1" />}
                            </div>
                            <div className={`pb-4 min-w-0 w-0 flex-1 ${isSystem ? 'opacity-60' : ''}`}>
                              <div className="flex items-center justify-between gap-2 mb-0.5">
                                <span className="text-xs font-medium">{n.creatorName || (isSystem ? 'System' : 'Unknown')}</span>
                                <span className="text-xs text-muted-foreground shrink-0">{formatDate(n.createDateTime)}</span>
                              </div>
                              {n.title && <p className="text-xs font-medium text-muted-foreground mb-0.5">{n.title}</p>}
                              {n.description && (
                                <p className="text-xs [overflow-wrap:anywhere]">
                                  <LinkedText text={n.description} />
                                </p>
                              )}
                            </div>
                          </div>
                        );
                      })}
                    </div>
                  </>
                )}
              </CollapsibleContent>
            </Collapsible>

          </div>
        )}
        </div>
      </DialogContent>
    </Dialog>
  );
}
