import { Calendar, ChevronRight, ExternalLink, Trash2 } from 'lucide-react';

import { memo, useCallback, useState } from 'react';

import { router } from '@inertiajs/react';

import { Badge } from '@/Components/ui/badge';
import { Button } from '@/Components/ui/button';
import { ConfirmDialog } from '@/Components/ui/confirm-dialog';
import { formatDateOnly, formatDateTime } from '@/lib/format';
import { cn } from '@/lib/utils';

export interface CalendarEntry {
  id: number;
  title: string;
  description: string | null;
  due_date: string;
  scheduled_date: string | null;
  status: 'planned' | 'in_progress' | 'completed' | 'overdue';
  source_type: string | null;
  source_id: number | null;
  page_url: string | null;
  metadata: Record<string, unknown> | null;
}

interface EventCardProps {
  entry: CalendarEntry;
  siteId: number;
  onEdit?: (entry: CalendarEntry) => void;
  onStatusChange?: (entry: CalendarEntry, newStatus: string) => void;
  selected?: boolean;
  onToggleSelection?: () => void;
}

function truncateUrl(url: string, maxLength: number): string {
  try {
    const parsed = new URL(url);
    const path = parsed.pathname + parsed.search;
    return path.length > maxLength ? path.slice(0, maxLength) + '...' : path;
  } catch {
    return url.length > maxLength ? url.slice(0, maxLength) + '...' : url;
  }
}

function getTimezoneAbbr(): string {
  const formatter = new Intl.DateTimeFormat('en-US', {
    timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
    timeZoneName: 'short',
  });
  const parts = formatter.formatToParts(new Date());
  const tzPart = parts.find((p) => p.type === 'timeZoneName');
  return tzPart?.value || 'Local';
}

const STATUS_CONFIG: Record<
  string,
  { label: string; variant: 'default' | 'secondary' | 'success' | 'destructive' }
> = {
  planned: { label: 'Planned', variant: 'default' },
  in_progress: { label: 'In Progress', variant: 'secondary' },
  completed: { label: 'Completed', variant: 'success' },
  overdue: { label: 'Overdue', variant: 'destructive' },
};

const StatusBadge = memo(({ status }: { status: string }) => {
  const config = STATUS_CONFIG[status] ?? {
    label: status.replace(/_/g, ' '),
    variant: 'default' as const,
  };
  return <Badge variant={config.variant}>{config.label}</Badge>;
});
StatusBadge.displayName = 'StatusBadge';

const SOURCE_TYPE_CONFIG: Record<
  string,
  { label: string; variant: 'default' | 'secondary' | 'outline' }
> = {
  freshness_recommendation: { label: 'Freshness', variant: 'outline' },
  topic_gap_suggestion: { label: 'Topic Gap', variant: 'outline' },
  analysis_run: { label: 'Analysis', variant: 'outline' },
  wp_post: { label: 'WordPress', variant: 'outline' },
  manual: { label: 'Manual', variant: 'default' },
};

const SourceTypeBadge = memo(({ sourceType }: { sourceType: string | null }) => {
  if (!sourceType) {
    return <Badge variant="default">Manual</Badge>;
  }
  const config = SOURCE_TYPE_CONFIG[sourceType] ?? {
    label: sourceType.replace(/_/g, ' '),
    variant: 'default' as const,
  };
  return <Badge variant={config.variant}>{config.label}</Badge>;
});
SourceTypeBadge.displayName = 'SourceTypeBadge';

function EventCard({
  entry,
  siteId,
  onEdit,
  onStatusChange,
  selected = false,
  onToggleSelection,
}: EventCardProps) {
  const [detailsOpen, setDetailsOpen] = useState(false);
  const [deleteOpen, setDeleteOpen] = useState(false);

  const toggleDetails = useCallback(() => {
    setDetailsOpen((prev) => !prev);
  }, []);

  const handleMarkComplete = useCallback(() => {
    if (entry.status !== 'completed') {
      onStatusChange?.(entry, 'completed');
    }
  }, [entry, onStatusChange]);

  const handleEdit = useCallback(() => {
    onEdit?.(entry);
  }, [entry, onEdit]);

  const handleDelete = useCallback(() => {
    router.delete(route('calendar.destroy', { site: siteId, calendarEntry: entry.id }));
  }, [entry.id, siteId]);

  const detailsId = `details-${entry.id}`;
  const isOverdue = entry.status === 'overdue';

  return (
    <div className={cn('rounded-lg border bg-card p-4', isOverdue && 'border-destructive/50')}>
      <div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between sm:gap-4">
        <div className="flex items-start gap-3 min-w-0">
          {onToggleSelection && (
            <input
              type="checkbox"
              checked={selected}
              onChange={onToggleSelection}
              className="mt-1 h-4 w-4 cursor-pointer rounded border-input text-primary focus:ring-2 focus:ring-ring focus:ring-offset-2"
              aria-label={`Select task: ${entry.title}`}
            />
          )}
          <div className="flex flex-col gap-2">
            <StatusBadge status={entry.status} />
            <SourceTypeBadge sourceType={entry.source_type} />
          </div>
          <div className="min-w-0">
            <div className="flex items-center gap-2">
              <p className="font-medium">{entry.title}</p>
              {isOverdue && <span className="text-xs text-destructive font-medium">Past due</span>}
            </div>
            <div className="flex items-center gap-2 text-xs text-muted-foreground mt-0.5">
              <Calendar className="h-3 w-3" />
              <span>Due: {formatDateOnly(entry.due_date)}</span>
            </div>
            {entry.page_url && (
              <a
                href={entry.page_url}
                target="_blank"
                rel="noopener noreferrer"
                className="inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-primary hover:underline mt-0.5 max-w-full"
                title={entry.page_url}
              >
                <span className="truncate">{truncateUrl(entry.page_url, 60)}</span>
                <ExternalLink className="h-3 w-3 shrink-0" />
              </a>
            )}
            {entry.description && (
              <p className="text-sm text-muted-foreground mt-1 line-clamp-2">{entry.description}</p>
            )}
          </div>
        </div>
        <div className="flex items-center gap-2 sm:shrink-0 sm:flex-col">
          {entry.status !== 'completed' && onStatusChange && (
            <Button variant="outline" size="sm" onClick={handleMarkComplete}>
              Mark Complete
            </Button>
          )}
          {onEdit && (
            <Button variant="ghost" size="sm" onClick={handleEdit}>
              Edit
            </Button>
          )}
          <ConfirmDialog
            open={deleteOpen}
            onOpenChange={setDeleteOpen}
            title="Delete calendar entry"
            description="Delete this calendar entry? This action cannot be undone."
            variant="destructive"
            confirmLabel="Delete"
            onConfirm={handleDelete}
            trigger={
              <Button variant="ghost" size="sm" aria-label="Delete entry">
                <Trash2 className="h-4 w-4 text-destructive" />
              </Button>
            }
          />
        </div>
      </div>

      <button
        type="button"
        aria-expanded={detailsOpen}
        aria-controls={detailsId}
        onClick={toggleDetails}
        className="mt-3 text-sm text-muted-foreground cursor-pointer hover:text-foreground flex items-center gap-1"
      >
        <ChevronRight
          className={cn('h-3 w-3 transition-transform duration-200', detailsOpen && 'rotate-90')}
        />
        View details
      </button>
      <div
        id={detailsId}
        className={cn(
          'grid transition-all duration-200 ease-in-out',
          detailsOpen ? 'grid-rows-[1fr] opacity-100 mt-2' : 'grid-rows-[0fr] opacity-0',
        )}
      >
        <div className="overflow-hidden">
          <div className="space-y-2 text-sm">
            <div className="grid grid-cols-[120px_1fr] gap-2">
              <span className="text-muted-foreground">Due Date:</span>
              <span>{formatDateOnly(entry.due_date)}</span>
            </div>
            {entry.scheduled_date && (
              <div className="grid grid-cols-[120px_1fr] gap-2">
                <span className="text-muted-foreground">Scheduled:</span>
                <span>
                  {formatDateTime(entry.scheduled_date)}{' '}
                  <span className="text-xs text-muted-foreground">({getTimezoneAbbr()})</span>
                </span>
              </div>
            )}
            {entry.source_type && entry.source_id && (
              <div className="grid grid-cols-[120px_1fr] gap-2">
                <span className="text-muted-foreground">Source:</span>
                <span>
                  {SOURCE_TYPE_CONFIG[entry.source_type]?.label ?? entry.source_type} (ID:{' '}
                  {entry.source_id})
                </span>
              </div>
            )}
            {entry.metadata && Object.keys(entry.metadata).length > 0 && (
              <div className="grid grid-cols-[120px_1fr] gap-2">
                <span className="text-muted-foreground">Metadata:</span>
                <pre className="text-xs bg-muted p-2 rounded overflow-x-auto">
                  {JSON.stringify(entry.metadata, null, 2)}
                </pre>
              </div>
            )}
          </div>
        </div>
      </div>
    </div>
  );
}

export default EventCard;
