'use client';

import { useEffect, useMemo, useState } from 'react';
import { useRouter } from 'next/navigation';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import { Badge } from '@/components/ui/badge';
import { Switch } from '@/components/ui/switch';
import { Label } from '@/components/ui/label';
import { Skeleton } from '@/components/ui/skeleton';
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
import { toast } from 'sonner';
import { Sparkles, Loader2, Network } from 'lucide-react';
import type {
  AggregateReportStatus,
  DiscoveredLinks,
  TicketRef,
} from '@/lib/types/analyzer';

interface RelatedTicketsPanelProps {
  ticketNumber: string;
  /** LLM provider for the bundle run. Defaults to 'anthropic'. */
  provider?: 'anthropic' | 'openrouter';
}

type Phase =
  | 'idle'
  | 'starting'
  | 'pending_analyses'
  | 'pending'
  | 'running'
  | 'complete'
  | 'failed';

const REPORT_POLL_TIMEOUT_MS = 10 * 60 * 1000;

export function RelatedTicketsPanel({
  ticketNumber,
  provider = 'anthropic',
}: RelatedTicketsPanelProps) {
  const router = useRouter();
  const [links, setLinks] = useState<DiscoveredLinks | null>(null);
  const [loadError, setLoadError] = useState<string | null>(null);
  const [selected, setSelected] = useState<Set<string>>(new Set());
  const [includeSuggested, setIncludeSuggested] = useState(false);
  const [suggestionsLoading, setSuggestionsLoading] = useState(false);
  const [phase, setPhase] = useState<Phase>('idle');
  const [statusLabel, setStatusLabel] = useState<string>('');

  // Initial cheap fetch.
  useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const res = await fetch(
          `/api/analyzer/tickets/${encodeURIComponent(ticketNumber)}/links`
        );
        if (!res.ok) {
          const data = (await res.json().catch(() => ({}))) as { error?: string };
          throw new Error(data.error ?? `Request failed: ${res.status}`);
        }
        const data = (await res.json()) as DiscoveredLinks;
        if (cancelled) return;
        setLinks(data);
        // Pre-check all explicit refs.
        setSelected(new Set(data.explicit.map((r) => r.ticket_number)));
      } catch (err) {
        if (!cancelled)
          setLoadError(err instanceof Error ? err.message : 'Unknown error');
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [ticketNumber]);

  async function loadSuggestions(): Promise<void> {
    if (!links) return;
    setSuggestionsLoading(true);
    try {
      const res = await fetch(
        `/api/analyzer/tickets/${encodeURIComponent(ticketNumber)}/links`,
        {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ includeSuggested: true }),
        }
      );
      if (!res.ok) {
        const data = (await res.json().catch(() => ({}))) as { error?: string };
        throw new Error(data.error ?? `Request failed: ${res.status}`);
      }
      const data = (await res.json()) as DiscoveredLinks;
      setLinks(data);
    } catch (err) {
      toast.error(
        err instanceof Error
          ? `Suggestion failed: ${err.message}`
          : 'Suggestion failed'
      );
      setIncludeSuggested(false);
    } finally {
      setSuggestionsLoading(false);
    }
  }

  function toggleRef(ref: TicketRef): void {
    setSelected((prev) => {
      const next = new Set(prev);
      if (next.has(ref.ticket_number)) next.delete(ref.ticket_number);
      else next.add(ref.ticket_number);
      return next;
    });
  }

  async function pollReport(reportId: string): Promise<void> {
    const start = Date.now();
    while (Date.now() - start < REPORT_POLL_TIMEOUT_MS) {
      await new Promise((r) => setTimeout(r, 3000));
      const res = await fetch(`/api/analyzer/aggregate-reports/${reportId}`);
      if (!res.ok) throw new Error(`Report poll failed: ${res.status}`);
      const data = (await res.json()) as {
        report: { status: AggregateReportStatus; errorMessage: string | null };
      };
      const status = data.report.status;
      setPhase(status as Phase);
      setStatusLabel(
        status === 'pending_analyses'
          ? 'Analyzing linked tickets…'
          : status === 'pending' || status === 'running'
            ? 'Building bundle report…'
            : status === 'complete'
              ? 'Done'
              : status === 'failed'
                ? 'Failed'
                : ''
      );
      if (status === 'complete') {
        router.push(`/analyzer/reports/${reportId}`);
        return;
      }
      if (status === 'failed') {
        throw new Error(data.report.errorMessage ?? 'Bundle report failed');
      }
    }
    throw new Error('Bundle report timed out after 10 minutes');
  }

  async function submit(opts: { confirmedCost?: boolean } = {}): Promise<void> {
    if (selected.size === 0) {
      toast.error('Select at least one linked ticket');
      return;
    }
    setPhase('starting');
    setStatusLabel('Queueing analyses…');
    try {
      const res = await fetch(
        `/api/analyzer/tickets/${encodeURIComponent(ticketNumber)}/analyze-bundle`,
        {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            linkedTicketNumbers: Array.from(selected),
            includeItglueContext: true,
            confirmedCost: opts.confirmedCost ?? false,
            provider,
          }),
        }
      );
      if (res.status === 400) {
        const data = (await res.json().catch(() => ({}))) as {
          requiresConfirmation?: boolean;
          message?: string;
          estimatedCost?: number;
        };
        if (data.requiresConfirmation) {
          const ok = window.confirm(
            `${data.message ?? 'Confirmation required'}.\n\nEstimated cost: $${data.estimatedCost?.toFixed(2) ?? '?'}\n\nProceed?`
          );
          if (ok) {
            await submit({ confirmedCost: true });
            return;
          }
          setPhase('idle');
          setStatusLabel('');
          return;
        }
        throw new Error(data.message ?? 'Bundle request rejected');
      }
      if (!res.ok) {
        const data = (await res.json().catch(() => ({}))) as { error?: string };
        throw new Error(data.error ?? `Request failed: ${res.status}`);
      }
      const data = (await res.json()) as {
        aggregateReportId: string;
        status: AggregateReportStatus;
      };
      setPhase(data.status as Phase);
      setStatusLabel(
        data.status === 'pending_analyses'
          ? 'Analyzing linked tickets…'
          : 'Building bundle report…'
      );
      await pollReport(data.aggregateReportId);
    } catch (err) {
      toast.error(err instanceof Error ? err.message : 'Bundle failed');
      setPhase('idle');
      setStatusLabel('');
    }
  }

  const allRefs = useMemo<TicketRef[]>(
    () => (links ? [...links.explicit, ...links.suggested] : []),
    [links]
  );
  const isRunning = phase !== 'idle' && phase !== 'failed' && phase !== 'complete';
  const selectedCount = selected.size;
  const hasContent = links && (links.explicit.length > 0 || links.isProblemTicket);

  if (loadError) {
    return (
      <Alert variant="destructive">
        <AlertTitle>Couldn&rsquo;t check for related tickets</AlertTitle>
        <AlertDescription>{loadError}</AlertDescription>
      </Alert>
    );
  }

  if (links === null) {
    return (
      <Card>
        <CardHeader>
          <Skeleton className="h-5 w-48" />
        </CardHeader>
        <CardContent>
          <Skeleton className="h-12 w-full" />
        </CardContent>
      </Card>
    );
  }

  if (!hasContent) {
    // Nothing to show — render nothing, the regular AnalyzeButton on the
    // parent page is sufficient.
    return null;
  }

  return (
    <Card className={links.isProblemTicket ? 'border-primary' : ''}>
      <CardHeader>
        <div className="flex items-start justify-between gap-3 flex-wrap">
          <div className="flex items-center gap-2">
            <Network className="w-5 h-5" />
            <CardTitle className="text-base">
              Related tickets detected ({allRefs.length})
            </CardTitle>
            {links.isProblemTicket && (
              <Badge variant="secondary">Problem ticket</Badge>
            )}
          </div>
          <div className="flex items-center gap-2">
            <Switch
              id="include-suggested"
              checked={includeSuggested}
              disabled={isRunning || suggestionsLoading}
              onCheckedChange={(v) => {
                const next = Boolean(v);
                setIncludeSuggested(next);
                if (next && links.suggested.length === 0) {
                  void loadSuggestions();
                }
              }}
            />
            <Label htmlFor="include-suggested" className="text-xs">
              {suggestionsLoading ? (
                <span className="inline-flex items-center gap-1">
                  <Loader2 className="w-3 h-3 animate-spin" />
                  Asking AI…
                </span>
              ) : (
                'AI-suggest more'
              )}
            </Label>
          </div>
        </div>
      </CardHeader>
      <CardContent className="space-y-4">
        <p className="text-sm text-muted-foreground">
          {links.isProblemTicket
            ? 'This looks like a problem/master ticket. Bundling will analyze every linked ticket and produce a cross-ticket report.'
            : 'This ticket references other tickets. Bundle them to get a cross-ticket analysis.'}
        </p>

        <ul className="divide-y">
          {allRefs.map((ref) => (
            <li
              key={ref.ticket_number + ':' + ref.source}
              className="py-2 flex items-start gap-3"
            >
              <Checkbox
                id={'rt-' + ref.ticket_number}
                checked={selected.has(ref.ticket_number)}
                onCheckedChange={() => toggleRef(ref)}
                disabled={isRunning}
                className="mt-0.5"
              />
              <div className="min-w-0 flex-1">
                <div className="flex items-center gap-2 flex-wrap">
                  <span className="font-mono text-sm">{ref.ticket_number}</span>
                  {ref.confidence === 'high' && (
                    <Badge variant="default" className="text-[10px] py-0">
                      explicit
                    </Badge>
                  )}
                  {ref.source === 'llm_suggested' && (
                    <Badge variant="outline" className="text-[10px] py-0">
                      AI-suggested
                    </Badge>
                  )}
                  {ref.status_label && (
                    <Badge variant="secondary" className="text-[10px] py-0">
                      {ref.status_label}
                    </Badge>
                  )}
                </div>
                {ref.title && (
                  <p className="text-xs text-muted-foreground truncate mt-0.5">
                    {ref.title}
                  </p>
                )}
                {ref.reason && (
                  <p className="text-xs text-muted-foreground italic mt-0.5">
                    {ref.reason}
                  </p>
                )}
              </div>
            </li>
          ))}
        </ul>

        <div className="flex items-center gap-2 flex-wrap pt-2">
          <Button
            onClick={() => void submit()}
            disabled={isRunning || selectedCount === 0}
            variant={links.isProblemTicket ? 'default' : 'secondary'}
          >
            {isRunning ? (
              <>
                <Loader2 className="w-4 h-4 mr-2 animate-spin" />
                {statusLabel || 'Working…'}
              </>
            ) : (
              <>
                <Sparkles className="w-4 h-4 mr-2" />
                Analyze with {selectedCount} linked ticket
                {selectedCount === 1 ? '' : 's'}
              </>
            )}
          </Button>
          <span className="text-xs text-muted-foreground">
            ({selectedCount + 1} total — master + linked)
          </span>
        </div>
      </CardContent>
    </Card>
  );
}
