'use client';

import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog';
import { Badge } from '@/components/ui/badge';
import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs';
import { Separator } from '@/components/ui/separator';
import { Calendar, Check, X, Copy, CheckCircle2, Code2, LayoutTemplate, ExternalLink, Phone, Globe, Loader2, User, Building2, MessageSquare, Clock } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { StatusBadge } from '@/components/ui/status-badge';
import {
  priorityBadge,
  ticketStatusBadge,
  sourceBadge,
  classificationBadge,
  companyTypeBadge,
  publishBadge,
  activeBadge,
  yesNoBadge,
  billableBadge,
  approvedBadge,
  toneClass,
  paletteClass,
} from '@/lib/status-registry';
import { useState, useEffect } from 'react';
import { useUserTimezone } from '@/lib/hooks/use-user-timezone';

// ── Live lookup types (fetched from DB) ───────────────────────────────────────

interface Lookups {
  statuses: Record<number, string>;
  resources: Record<number, string>;
  companies: Record<number, string>;
  issueTypes: Record<number, string>;
  subIssueTypes: Record<number, string>;
  queues: Record<number, string>;
  configItems: Record<number, string>;
}

// ── Field metadata for formatted view ─────────────────────────────────────────

type FieldType = 'date' | 'bool' | 'status' | 'priority' | 'source' | 'queue' | 'company_type' | 'classification' | 'url' | 'phone' | 'hours' | 'id' | 'resource' | 'company' | 'issue_type' | 'sub_issue_type' | 'config_item';

type FieldGroup = {
  label: string;
  fields: Array<{ key: string; label: string; type?: FieldType }>;
  paired?: string;
};

const TICKET_GROUPS: FieldGroup[] = [
  {
    label: 'Parties',
    fields: [
      { key: 'company_id', label: 'Company', type: 'company' },
      { key: 'contact_id', label: 'Contact ID', type: 'id' },
      { key: 'assigned_resource_id', label: 'Assigned Resource', type: 'resource' },
      { key: 'configuration_item_id', label: 'Configuration Item', type: 'config_item' },
    ],
  },
  {
    label: 'Details',
    fields: [
      { key: 'priority', label: 'Priority', type: 'priority' },
      { key: 'source', label: 'Source', type: 'source' },
      { key: 'queue_id', label: 'Queue', type: 'queue' },
      { key: 'issue_type', label: 'Issue Type', type: 'issue_type' },
      { key: 'sub_issue_type', label: 'Sub-Issue Type', type: 'sub_issue_type' },
    ],
  },
  {
    label: 'Dates & Time',
    paired: 'System',
    fields: [
      { key: 'create_date', label: 'Created', type: 'date' },
      { key: 'due_date_time', label: 'Due', type: 'date' },
      { key: 'last_activity_date', label: 'Last Activity', type: 'date' },
      { key: 'completed_date', label: 'Completed', type: 'date' },
      { key: 'estimated_hours', label: 'Estimated Hours', type: 'hours' },
    ],
  },
  {
    label: 'System',
    paired: 'Dates & Time',
    fields: [
      { key: 'id', label: 'Record ID', type: 'id' },
      { key: 'synced_at', label: 'Synced At', type: 'date' },
      { key: 'is_deleted', label: 'Deleted', type: 'bool' },
    ],
  },
];

const COMPANY_GROUPS: FieldGroup[] = [
  {
    label: 'Identity',
    fields: [
      { key: 'company_name', label: 'Company Name' },
      { key: 'company_number', label: 'Company #' },
      { key: 'company_type', label: 'Type', type: 'company_type' },
      { key: 'classification', label: 'Classification', type: 'classification' },
      { key: 'is_active', label: 'Active', type: 'bool' },
    ],
  },
  {
    label: 'Contact',
    fields: [
      { key: 'phone', label: 'Phone', type: 'phone' },
      { key: 'alternate_phone1', label: 'Alt Phone 1', type: 'phone' },
      { key: 'alternate_phone2', label: 'Alt Phone 2', type: 'phone' },
      { key: 'fax', label: 'Fax', type: 'phone' },
      { key: 'web_site_url', label: 'Website', type: 'url' },
    ],
  },
  {
    label: 'Address',
    fields: [
      { key: 'address1', label: 'Address 1' },
      { key: 'address2', label: 'Address 2' },
      { key: 'city', label: 'City' },
      { key: 'state', label: 'State' },
      { key: 'postal_code', label: 'Postal Code' },
      { key: 'country', label: 'Country' },
    ],
  },
  {
    label: 'System',
    paired: 'Address',
    fields: [
      { key: 'id', label: 'Record ID', type: 'id' },
      { key: 'synced_at', label: 'Synced At', type: 'date' },
      { key: 'is_deleted', label: 'Deleted', type: 'bool' },
    ],
  },
];

// PAX8 company drill-down (kind="pax8_company") — additive only, does not
// touch TICKET_GROUPS/COMPANY_GROUPS or their existing detection branches.
// Field keys are camelCase because the /pax8 page passes an already-
// transformed object (see 14-03-PLAN.md interfaces block).
const PAX8_COMPANY_GROUPS: FieldGroup[] = [
  {
    label: 'Identity',
    paired: 'System',
    fields: [
      { key: 'name', label: 'Name' },
      { key: 'status', label: 'Status' },
      { key: 'city', label: 'City' },
      { key: 'stateOrProvince', label: 'State/Province' },
      { key: 'country', label: 'Country' },
      { key: 'website', label: 'Website', type: 'url' },
    ],
  },
  {
    label: 'System',
    paired: 'Identity',
    fields: [
      { key: 'id', label: 'Record ID', type: 'id' },
      { key: 'syncedAt', label: 'Synced At', type: 'date' },
      { key: 'isDeleted', label: 'Deleted', type: 'bool' },
    ],
  },
];

// ── Helpers ────────────────────────────────────────────────────────────────────

function resolveLabel(key: string, value: any, type: FieldType | undefined, lookups: Lookups, tz: string): { display: React.ReactNode; isEmpty: boolean } {
  if (value === null || value === undefined || value === '') {
    return { display: <span className="text-muted-foreground/70 italic text-xs">—</span>, isEmpty: true };
  }

  switch (type) {
    case 'bool': {
      const badge = yesNoBadge(Boolean(value));
      return {
        display: (
          <StatusBadge variantClass={badge.variantClass}>
            {value ? <Check className="w-3 h-3 mr-1" /> : <X className="w-3 h-3 mr-1" />}
            {badge.label}
          </StatusBadge>
        ),
        isEmpty: false,
      };
    }
    case 'date': {
      try {
        const d = new Date(value);
        return {
          display: (
            <span className="inline-flex items-center gap-1.5 text-sm">
              <Calendar className="w-3.5 h-3.5 text-muted-foreground" />
              {d.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric', timeZone: tz })}
            </span>
          ),
          isEmpty: false,
        };
      } catch { break; }
    }
    case 'status': {
      const label = lookups.statuses[Number(value)] ?? `Status ${value}`;
      const badge = ticketStatusBadge(label);
      return { display: <StatusBadge {...badge} />, isEmpty: false };
    }
    case 'priority': {
      return { display: <StatusBadge {...priorityBadge(Number(value))} />, isEmpty: false };
    }
    case 'source': {
      return { display: <StatusBadge {...sourceBadge(Number(value))} />, isEmpty: false };
    }
    case 'queue': {
      const label = lookups.queues[Number(value)] ?? `Queue ${value}`;
      return { display: <StatusBadge variantClass={paletteClass('indigo')}>{label}</StatusBadge>, isEmpty: false };
    }
    case 'company_type': {
      return { display: <StatusBadge {...companyTypeBadge(Number(value))} />, isEmpty: false };
    }
    case 'classification': {
      return { display: <StatusBadge {...classificationBadge(Number(value))} />, isEmpty: false };
    }
    case 'resource': {
      const name = lookups.resources[Number(value)];
      return {
        display: name
          ? <span className="inline-flex items-center gap-1.5 text-sm"><User className="w-3.5 h-3.5 text-muted-foreground" />{name}</span>
          : <span className="font-mono text-xs bg-muted px-2 py-0.5 rounded">{value}</span>,
        isEmpty: false,
      };
    }
    case 'company': {
      const name = lookups.companies[Number(value)];
      return {
        display: name
          ? <span className="inline-flex items-center gap-1.5 text-sm"><Building2 className="w-3.5 h-3.5 text-muted-foreground" />{name}</span>
          : <span className="font-mono text-xs bg-muted px-2 py-0.5 rounded">{value}</span>,
        isEmpty: false,
      };
    }
    case 'issue_type': {
      const label = lookups.issueTypes[Number(value)] ?? `Issue ${value}`;
      return { display: <StatusBadge variantClass={paletteClass('sky')}>{label}</StatusBadge>, isEmpty: false };
    }
    case 'sub_issue_type': {
      const label = lookups.subIssueTypes[Number(value)] ?? `Sub-Issue ${value}`;
      return { display: <StatusBadge variantClass="bg-sky-500/10 text-sky-700 dark:text-sky-400">{label}</StatusBadge>, isEmpty: false };
    }
    case 'config_item': {
      const name = lookups.configItems[Number(value)];
      return {
        display: name
          ? <span className="text-sm">{name}</span>
          : <span className="font-mono text-xs bg-muted px-2 py-0.5 rounded">{value}</span>,
        isEmpty: false,
      };
    }
    case 'url':
      return {
        display: (
          <a href={String(value).startsWith('http') ? value : `https://${value}`} target="_blank" rel="noopener noreferrer"
            className="inline-flex items-center gap-1 text-sm text-blue-500 hover:underline">
            <Globe className="w-3.5 h-3.5" />{value}<ExternalLink className="w-3 h-3" />
          </a>
        ),
        isEmpty: false,
      };
    case 'phone':
      return {
        display: (
          <a href={`tel:${value}`} className="inline-flex items-center gap-1 text-sm hover:underline">
            <Phone className="w-3.5 h-3.5 text-muted-foreground" />{value}
          </a>
        ),
        isEmpty: false,
      };
    case 'id':
      return { display: <span className="font-mono text-xs bg-muted px-2 py-0.5 rounded">{value}</span>, isEmpty: false };
    case 'hours':
      return { display: <span className="text-sm">{Number(value).toFixed(1)} hrs</span>, isEmpty: false };
  }

  if (typeof value === 'string' && value.match(/^\d{4}-\d{2}-\d{2}/)) {
    return resolveLabel(key, value, 'date', lookups, tz);
  }

  return { display: <span className="text-sm">{String(value)}</span>, isEmpty: false };
}

function detectGroups(data: Record<string, any>, kind?: 'ticket' | 'company' | 'pax8_company'): FieldGroup[] {
  if (kind === 'pax8_company') return PAX8_COMPANY_GROUPS;
  if ('ticket_number' in data) return TICKET_GROUPS;
  if ('company_name' in data) return COMPANY_GROUPS;
  return [{ label: 'Fields', fields: Object.keys(data).map(k => ({ key: k, label: k })) }];
}

const EMPTY_LOOKUPS: Lookups = { statuses: {}, resources: {}, companies: {}, issueTypes: {}, subIssueTypes: {}, queues: {}, configItems: {} };

// ── Component ──────────────────────────────────────────────────────────────────

interface DetailModalProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  title: string;
  data: Record<string, any> | null;
  fields?: Array<{ key: string; label: string; render?: (value: any) => React.ReactNode }>;
  kind?: 'ticket' | 'company' | 'pax8_company';
}

export default function DetailModal({ open, onOpenChange, title, data, fields, kind }: DetailModalProps) {
  const tz = useUserTimezone();
  const [copiedField, setCopiedField] = useState<string | null>(null);
  const [lookups, setLookups] = useState<Lookups>(EMPTY_LOOKUPS);
  const [lookupsLoading, setLookupsLoading] = useState(false);
  const [notes, setNotes] = useState<any[]>([]);
  const [notesLoading, setNotesLoading] = useState(false);
  const [timeEntries, setTimeEntries] = useState<any[]>([]);
  const [timeEntriesLoading, setTimeEntriesLoading] = useState(false);

  useEffect(() => {
    if (!open) return;
    setLookupsLoading(true);
    fetch('/api/data/lookups')
      .then(r => r.json())
      .then(d => {
        setLookups({
          statuses:     Object.fromEntries((d.statuses     ?? []).map((r: any) => [r.value, r.label])),
          resources:    Object.fromEntries((d.resources    ?? []).map((r: any) => [r.id,    r.name])),
          companies:    Object.fromEntries((d.companies    ?? []).map((r: any) => [r.id,    r.name])),
          issueTypes:   Object.fromEntries((d.issueTypes   ?? []).map((r: any) => [r.value, r.label])),
          subIssueTypes:Object.fromEntries((d.subIssueTypes?? []).map((r: any) => [r.value, r.label])),
          queues:       Object.fromEntries((d.queues        ?? []).map((r: any) => [r.value, r.label])),
          configItems:  Object.fromEntries((d.configItems   ?? []).map((r: any) => [r.id,    r.name])),
        });
      })
      .catch(() => {})
      .finally(() => setLookupsLoading(false));

    if (data && 'ticket_number' in data && data.id) {
      setNotesLoading(true);
      fetch(`/api/data/ticket-notes?ticket_id=${data.id}&sort_by=create_date_time&sort_order=asc&limit=200`)
        .then(r => r.json())
        .then(d => setNotes(d.ticketNotes ?? []))
        .catch(() => setNotes([]))
        .finally(() => setNotesLoading(false));

      setTimeEntriesLoading(true);
      fetch(`/api/data/time-entries?ticket_id=${data.id}&sort_by=entry_date&sort_order=asc&limit=200`)
        .then(r => r.json())
        .then(d => setTimeEntries(d.timeEntries ?? []))
        .catch(() => setTimeEntries([]))
        .finally(() => setTimeEntriesLoading(false));
    } else {
      setNotes([]);
      setTimeEntries([]);
    }
  }, [open]);

  if (!data) return null;

  const copyToClipboard = (text: string, fieldKey: string) => {
    navigator.clipboard.writeText(text);
    setCopiedField(fieldKey);
    setTimeout(() => setCopiedField(null), 2000);
  };

  const groups = detectGroups(data, kind);

  // Raw tab: all fields
  const rawFields = fields || Object.keys(data).map(k => ({ key: k, label: k, render: undefined }));

  const renderRaw = (value: any): React.ReactNode => {
    if (value === null || value === undefined) return <span className="text-muted-foreground/50 italic text-xs">null</span>;
    if (typeof value === 'boolean') return <Badge variant={value ? 'default' : 'secondary'}>{value ? 'true' : 'false'}</Badge>;
    if (typeof value === 'object') return <pre className="text-xs bg-muted p-2 rounded border overflow-x-auto">{JSON.stringify(value, null, 2)}</pre>;
    return <span className="text-sm font-mono">{String(value)}</span>;
  };

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="max-w-7xl max-h-[90vh] overflow-hidden flex flex-col gap-0 p-0 border-2 border-blue-500/70 shadow-[0_0_0_1px_rgba(59,130,246,0.15),0_20px_60px_-10px_rgba(59,130,246,0.25)]">
        {/* Header */}
        <div className="px-6 pt-5 pb-4 border-b">
          {'ticket_number' in data ? (
            <div className="flex items-start justify-between gap-6 pr-8">
              <div className="min-w-0">
                <div className="flex items-baseline gap-2 flex-wrap">
                  <span className="font-mono text-sm font-semibold text-muted-foreground shrink-0">{data.ticket_number}</span>
                  <DialogTitle className="text-xl font-bold leading-tight" style={{overflowWrap:'anywhere', wordBreak:'break-word'}}>{data.title}</DialogTitle>
                </div>
              </div>
              <div className="shrink-0 flex flex-col items-end gap-1">
                {(() => {
                  const label = lookups.statuses[Number(data.status)] ?? `Status ${data.status}`;
                  return <StatusBadge {...ticketStatusBadge(label)} />;
                })()}
              </div>
            </div>
          ) : (
            <div className="flex items-start justify-between gap-4 pr-8">
              <div>
                <DialogTitle className="text-2xl font-bold">{title}</DialogTitle>
                <DialogDescription className="mt-1">
                  Record ID: <span className="font-mono">{data.id}</span>
                </DialogDescription>
              </div>
              {'is_active' in data && (
                <StatusBadge {...activeBadge(Boolean(data.is_active))} />
              )}
            </div>
          )}
        </div>

        {/* Tabs */}
        <Tabs defaultValue="formatted" className="flex flex-col flex-1 overflow-hidden">
          <div className="px-6 pt-3 pb-0 border-b">
            <TabsList className="h-9">
              <TabsTrigger value="formatted" className="gap-1.5">
                <LayoutTemplate className="w-3.5 h-3.5" />
                Formatted
              </TabsTrigger>
              {'ticket_number' in data && (
                <TabsTrigger value="time" className="gap-1.5">
                  <Clock className="w-3.5 h-3.5" />
                  Time
                  {timeEntries.length > 0 && (
                    <span className="ml-1 rounded-full bg-blue-500/20 text-blue-600 text-xs px-1.5 py-0.5 font-medium">
                      {timeEntries.reduce((s, e) => s + (parseFloat(e.hours_worked) || 0), 0).toFixed(1)}h
                    </span>
                  )}
                </TabsTrigger>
              )}
              {'ticket_number' in data && (
                <TabsTrigger value="notes" className="gap-1.5">
                  <MessageSquare className="w-3.5 h-3.5" />
                  Notes
                  {notes.length > 0 && (
                    <span className="ml-1 rounded-full bg-blue-500/20 text-blue-600 text-xs px-1.5 py-0.5 font-medium">{notes.length}</span>
                  )}
                </TabsTrigger>
              )}
              <TabsTrigger value="raw" className="gap-1.5">
                <Code2 className="w-3.5 h-3.5" />
                Raw
              </TabsTrigger>
            </TabsList>
          </div>

          {/* ── Formatted Tab ── */}
          <TabsContent value="formatted" className="flex-1 overflow-y-auto px-6 py-4 mt-0">
            <div className="space-y-6">
              {/* Subscriptions & cost-breakdown — renders above field groups (UI-SPEC: focal point) */}
              {Array.isArray(data.subscriptions) && (
                <div>
                  <h3 className="text-xs font-semibold uppercase tracking-wider text-muted-foreground mb-3">Subscriptions &amp; Cost</h3>
                  <div className="rounded-lg border overflow-hidden">
                    {data.subscriptions.length === 0 ? (
                      <div className="px-4 py-3 text-sm text-muted-foreground italic">No subscriptions</div>
                    ) : (
                      <>
                        <div className="grid grid-cols-[1fr_80px_140px_120px] gap-2 px-4 py-2 bg-muted/40 text-xs font-medium text-muted-foreground border-b">
                          <div>Product</div>
                          <div className="text-right">Qty</div>
                          <div>Billing Term</div>
                          <div className="text-right">Amount</div>
                        </div>
                        {data.subscriptions.map((sub: any, idx: number) => {
                          const productLabel = sub.productName || sub.sku || 'Unknown item';
                          const amount = Number(sub.latestBilledAmount ?? 0);
                          const currency = sub.currency ?? 'USD';
                          return (
                            <div key={sub.subscriptionId ?? idx}>
                              {idx > 0 && <Separator />}
                              <div className="grid grid-cols-[1fr_80px_140px_120px] gap-2 px-4 py-2.5 items-center text-sm">
                                <div className="min-w-0 truncate">{productLabel}</div>
                                <div className="text-right font-mono tabular-nums">{sub.quantity ?? '—'}</div>
                                <div className="text-muted-foreground">{sub.billingTerm ?? '—'}</div>
                                <div className="text-right font-mono tabular-nums">{currency} {amount.toFixed(2)}</div>
                              </div>
                            </div>
                          );
                        })}
                        <Separator />
                        <div className="grid grid-cols-[1fr_80px_140px_120px] gap-2 px-4 py-2.5 items-center text-sm font-semibold bg-muted/20">
                          <div className="col-span-3">Total</div>
                          <div className="text-right font-mono tabular-nums">
                            {(data.subscriptions[0]?.currency ?? 'USD')} {data.subscriptions.reduce((s: number, sub: any) => s + Number(sub.latestBilledAmount ?? 0), 0).toFixed(2)}
                          </div>
                        </div>
                      </>
                    )}
                  </div>
                </div>
              )}

              {(() => {
                const rendered = new Set<string>();
                return groups.map((group) => {
                  if (rendered.has(group.label)) return null;
                  const visibleFields = group.fields.filter(f => f.key in data);
                  if (visibleFields.length === 0) return null;

                  // Inline badge row for Details group
                  if (group.label === 'Details') {
                    return (
                      <div key="Details">
                        <h3 className="text-xs font-semibold uppercase tracking-wider text-muted-foreground mb-3">Details</h3>
                        <div className="rounded-lg border overflow-hidden">
                          <div className="flex flex-wrap gap-x-6 gap-y-3 px-4 py-3">
                            {visibleFields.map((field) => {
                              const value = data[field.key];
                              const { display, isEmpty } = resolveLabel(field.key, value, field.type, lookups, tz);
                              if (isEmpty) return null;
                              return (
                                <div key={field.key} className="flex items-center gap-1.5">
                                  <span className="text-xs text-muted-foreground">{field.label}:</span>
                                  {display}
                                </div>
                              );
                            })}
                          </div>
                        </div>
                      </div>
                    );
                  }

                  const pairedGroup = group.paired ? groups.find(g => g.label === group.paired) : null;
                  const pairedVisible = pairedGroup ? pairedGroup.fields.filter(f => f.key in data) : [];
                  const isPaired = !!pairedGroup && pairedVisible.length > 0;

                  if (isPaired) {
                    rendered.add(group.label);
                    rendered.add(pairedGroup!.label);
                  }

                  const renderGroupTable = (g: FieldGroup, fields: typeof visibleFields) => (
                    <div key={g.label} className="flex-1 min-w-0">
                      <h3 className="text-xs font-semibold uppercase tracking-wider text-muted-foreground mb-3">{g.label}</h3>
                      <div className="rounded-lg border overflow-hidden">
                        {fields.map((field, idx) => {
                          const value = data[field.key];
                          const { display, isEmpty } = resolveLabel(field.key, value, field.type, lookups, tz);
                          const stringValue = value !== null && value !== undefined ? String(value) : '';
                          return (
                            <div key={field.key}>
                              {idx > 0 && <Separator />}
                              <div className="group grid grid-cols-[140px_1fr] items-start">
                                <div className="px-3 py-2.5 bg-muted/40 text-xs font-medium text-muted-foreground border-r truncate">
                                  {field.label}
                                </div>
                                <div className="px-3 py-2.5 flex items-start justify-between gap-2 min-w-0 overflow-hidden">
                                  <div className={`flex-1 min-w-0 ${isEmpty ? 'opacity-40' : ''}`} style={{overflowWrap:'anywhere', wordBreak:'break-word'}}>
                                    {display}
                                  </div>
                                  {stringValue && !isEmpty && (
                                    <Button variant="ghost" size="icon"
                                      className="h-5 w-5 opacity-0 group-hover:opacity-100 transition-opacity shrink-0"
                                      onClick={() => copyToClipboard(stringValue, `${g.label}-${field.key}`)}
                                    >
                                      {copiedField === `${g.label}-${field.key}`
                                        ? <CheckCircle2 className="w-3 h-3 text-green-500" />
                                        : <Copy className="w-3 h-3" />}
                                    </Button>
                                  )}
                                </div>
                              </div>
                            </div>
                          );
                        })}
                      </div>
                    </div>
                  );

                  if (isPaired) {
                    return (
                      <div key={group.label} className="grid grid-cols-2 gap-4">
                        {renderGroupTable(group, visibleFields)}
                        {renderGroupTable(pairedGroup!, pairedVisible)}
                      </div>
                    );
                  }

                  return (
                    <div key={group.label}>
                      <h3 className="text-xs font-semibold uppercase tracking-wider text-muted-foreground mb-3">{group.label}</h3>
                      <div className="rounded-lg border overflow-hidden">
                        {visibleFields.map((field, idx) => {
                          const value = data[field.key];
                          const { display, isEmpty } = resolveLabel(field.key, value, field.type, lookups, tz);
                          const stringValue = value !== null && value !== undefined ? String(value) : '';
                          return (
                            <div key={field.key}>
                              {idx > 0 && <Separator />}
                              <div className="group grid grid-cols-[220px_1fr] items-start">
                                <div className="px-4 py-3 bg-muted/40 text-sm font-medium text-muted-foreground border-r">
                                  {field.label}
                                </div>
                                <div className="px-4 py-3 flex items-start justify-between gap-2 min-w-0 overflow-hidden">
                                  <div className={`flex-1 min-w-0 ${isEmpty ? 'opacity-40' : ''}`} style={{overflowWrap:'anywhere', wordBreak:'break-word'}}>
                                    {display}
                                  </div>
                                  {stringValue && !isEmpty && (
                                    <Button variant="ghost" size="icon"
                                      className="h-6 w-6 opacity-0 group-hover:opacity-100 transition-opacity shrink-0"
                                      onClick={() => copyToClipboard(stringValue, field.key)}
                                    >
                                      {copiedField === field.key
                                        ? <CheckCircle2 className="w-3.5 h-3.5 text-green-500" />
                                        : <Copy className="w-3.5 h-3.5" />}
                                    </Button>
                                  )}
                                </div>
                              </div>
                            </div>
                          );
                        })}
                      </div>
                    </div>
                  );
                });
              })()}

              {/* Description block for tickets */}
              {'description' in data && data.description && (
                <div>
                  <h3 className="text-xs font-semibold uppercase tracking-wider text-muted-foreground mb-3">Description</h3>
                  <div className="rounded-lg border p-4 text-sm whitespace-pre-wrap leading-relaxed text-muted-foreground break-words overflow-hidden" style={{overflowWrap:'anywhere', wordBreak:'break-word'}}>
                    {data.description}
                  </div>
                </div>
              )}
            </div>
          </TabsContent>

          {/* ── Time Entries Tab ── */}
          <TabsContent value="time" className="flex-1 overflow-y-auto px-6 py-4 mt-0">
            {timeEntriesLoading ? (
              <div className="flex items-center justify-center py-12">
                <Loader2 className="w-5 h-5 animate-spin text-muted-foreground" />
              </div>
            ) : timeEntries.length === 0 ? (
              <div className="flex flex-col items-center justify-center py-12 text-muted-foreground gap-2">
                <Clock className="w-8 h-8 opacity-30" />
                <p className="text-sm">No time entries on this ticket</p>
              </div>
            ) : (
              <div className="space-y-2">
                {/* Summary bar */}
                <div className="rounded-lg border px-4 py-3 flex items-center gap-6 bg-muted/30 mb-4">
                  <div className="flex items-center gap-1.5 text-sm">
                    <Clock className="w-4 h-4 text-muted-foreground" />
                    <span className="font-semibold">{timeEntries.reduce((s, e) => s + (parseFloat(e.hours_worked) || 0), 0).toFixed(2)}</span>
                    <span className="text-muted-foreground">total hours</span>
                  </div>
                  <div className="text-sm text-muted-foreground">{timeEntries.length} {timeEntries.length === 1 ? 'entry' : 'entries'}</div>
                  <div className="text-sm text-muted-foreground">
                    {timeEntries.filter(e => e.billable).length} billable
                  </div>
                </div>
                {/* Entry rows */}
                <div className="rounded-lg border overflow-hidden">
                  {timeEntries.map((entry, idx) => (
                    <div key={entry.id}>
                      {idx > 0 && <Separator />}
                      <div className="px-4 py-3 grid grid-cols-[1fr_auto] gap-4 items-start">
                        <div className="space-y-1 min-w-0">
                          <div className="flex items-center gap-2 flex-wrap">
                            {entry.resource_name && (
                              <span className="inline-flex items-center gap-1 text-sm font-medium">
                                <User className="w-3.5 h-3.5 text-muted-foreground" />
                                {entry.resource_name}
                              </span>
                            )}
                            {entry.billable && (
                              <StatusBadge {...billableBadge(true)} />
                            )}
                            {entry.approved && (
                              <StatusBadge {...approvedBadge(true)} />
                            )}
                          </div>
                          {entry.notes && (
                            <p className="text-sm text-muted-foreground" style={{overflowWrap:'anywhere', wordBreak:'break-word'}}>{entry.notes}</p>
                          )}
                        </div>
                        <div className="shrink-0 flex flex-col items-end gap-1">
                          <span className="text-sm font-semibold tabular-nums">
                            {parseFloat(entry.hours_worked).toFixed(2)}h
                          </span>
                          {entry.entry_date && (
                            <span className="inline-flex items-center gap-1 text-xs text-muted-foreground">
                              <Calendar className="w-3 h-3" />
                              {new Date(entry.entry_date).toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric', timeZone: tz })}
                            </span>
                          )}
                        </div>
                      </div>
                    </div>
                  ))}
                </div>
              </div>
            )}
          </TabsContent>

          {/* ── Notes Tab ── */}
          <TabsContent value="notes" className="flex-1 overflow-y-auto px-6 py-4 mt-0">
            {notesLoading ? (
              <div className="flex items-center justify-center py-12">
                <Loader2 className="w-5 h-5 animate-spin text-muted-foreground" />
              </div>
            ) : notes.length === 0 ? (
              <div className="flex flex-col items-center justify-center py-12 text-muted-foreground gap-2">
                <MessageSquare className="w-8 h-8 opacity-30" />
                <p className="text-sm">No notes on this ticket</p>
              </div>
            ) : (
              <div className="space-y-3">
                {notes.map((note) => {
                  return (
                    <div key={note.id} className="rounded-lg border p-4 space-y-2">
                      <div className="flex items-start justify-between gap-3">
                        <div className="flex items-center gap-2 flex-wrap">
                          {note.creator_name && (
                            <span className="inline-flex items-center gap-1 text-sm font-medium">
                              <User className="w-3.5 h-3.5 text-muted-foreground" />
                              {note.creator_name}
                            </span>
                          )}
                          {note.publish != null && (
                            <StatusBadge {...publishBadge(Number(note.publish))} />
                          )}
                          {note.title && (
                            <span className="text-sm font-semibold text-foreground">{note.title}</span>
                          )}
                        </div>
                        {note.create_date_time && (
                          <span className="inline-flex items-center gap-1 text-xs text-muted-foreground shrink-0">
                            <Calendar className="w-3 h-3" />
                            {new Date(note.create_date_time).toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric', timeZone: tz })}
                            {' '}
                            {new Date(note.create_date_time).toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit', timeZone: tz })}
                          </span>
                        )}
                      </div>
                      {note.description && (
                        <div className="text-sm text-muted-foreground whitespace-pre-wrap leading-relaxed border-t pt-2" style={{overflowWrap:'anywhere', wordBreak:'break-word'}}>
                          {note.description}
                        </div>
                      )}
                    </div>
                  );
                })}
              </div>
            )}
          </TabsContent>

          {/* ── Raw Tab ── */}
          <TabsContent value="raw" className="flex-1 overflow-y-auto px-6 py-4 mt-0">
            <div className="rounded-lg border overflow-hidden">
              {rawFields.map((field, idx) => {
                const value = data[field.key];
                const stringValue = value !== null && value !== undefined ? String(value) : '';
                return (
                  <div key={field.key}>
                    {idx > 0 && <Separator />}
                    <div className="group grid grid-cols-[220px_1fr] items-start">
                      <div className="px-4 py-2.5 bg-muted/40 text-xs font-mono text-muted-foreground border-r">
                        {field.key}
                      </div>
                      <div className="px-4 py-2.5 flex items-start justify-between gap-2 min-w-0">
                        <div className="flex-1 min-w-0 break-words">
                          {field.render ? field.render(value) : renderRaw(value)}
                        </div>
                        {stringValue && (
                          <Button
                            variant="ghost"
                            size="icon"
                            className="h-6 w-6 opacity-0 group-hover:opacity-100 transition-opacity shrink-0"
                            onClick={() => copyToClipboard(stringValue, `raw-${field.key}`)}
                          >
                            {copiedField === `raw-${field.key}`
                              ? <CheckCircle2 className="w-3.5 h-3.5 text-green-500" />
                              : <Copy className="w-3.5 h-3.5" />}
                          </Button>
                        )}
                      </div>
                    </div>
                  </div>
                );
              })}
            </div>
          </TabsContent>
        </Tabs>
      </DialogContent>
    </Dialog>
  );
}
