'use client';

import { useEffect, useMemo, useState } from 'react';
import Link from 'next/link';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { Skeleton } from '@/components/ui/skeleton';
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
import {
  ProviderToggle,
  type AnalyzerProvider,
} from '@/components/analyzer/provider-toggle';
import {
  Sparkles,
  Loader2,
  ExternalLink,
  CheckCircle2,
  Server,
  Layers,
  Database,
} from 'lucide-react';
import { useSession } from '@/lib/auth-client';
import { toast } from 'sonner';

interface FieldGap {
  field_name: string;
  why_missing_matters: string;
  suggested_value: string | null;
  evidence_ticket_numbers: string[];
  confidence: 'high' | 'medium' | 'low';
}

interface NotePromotion {
  quoted_note_text: string;
  target_field: string;
  suggested_value: string;
  confidence: 'high' | 'medium' | 'low';
}

interface AuditRow {
  id: string;
  generated_at: string;
  provider: 'anthropic' | 'openrouter';
  ticket_count: number;
  field_gaps: FieldGap[];
  notes_promotions: NotePromotion[];
  contradictions: { description: string; evidence: string }[];
  overall_score: number | null;
  estimated_cost_usd: number | null;
}

interface MatchedAsset {
  id: string;
  name: string | null;
  hostname?: string | null;
  type_name: string | null;
  score: number;
  matched_term: string;
  latestAudit: AuditRow | null;
}

interface SuggestionsResponse {
  ticketNumber: string;
  organizationId: string | null;
  organizationName: string | null;
  flexibleAssets: MatchedAsset[];
  configurations: MatchedAsset[];
}

const CONFIDENCE_TONE: Record<FieldGap['confidence'], string> = {
  high: 'border-red-500 bg-red-500/10',
  medium: 'border-amber-500 bg-amber-500/10',
  low: 'border-blue-500 bg-blue-500/10',
};

interface ItglueSuggestionsPanelProps {
  analysisId: string;
}

export function ItglueSuggestionsPanel({ analysisId }: ItglueSuggestionsPanelProps) {
  const { data: session } = useSession();
  const role = (session?.user as { role?: string } | undefined)?.role ?? 'user';
  const canWrite = role === 'admin' || role === 'super-admin';

  const [data, setData] = useState<SuggestionsResponse | null>(null);
  const [loading, setLoading] = useState(false);
  const [loadError, setLoadError] = useState<string | null>(null);
  const [provider, setProvider] = useState<AnalyzerProvider>('anthropic');
  const [auditing, setAuditing] = useState<string | null>(null);
  const [busyKey, setBusyKey] = useState<string | null>(null);

  async function loadSuggestions(): Promise<void> {
    setLoading(true);
    setLoadError(null);
    try {
      const res = await fetch(
        `/api/analyzer/analyses/${analysisId}/itglue-suggestions`
      );
      if (!res.ok) {
        const err = (await res.json().catch(() => ({}))) as { error?: string };
        throw new Error(err.error ?? `Request failed: ${res.status}`);
      }
      const d = (await res.json()) as SuggestionsResponse;
      setData(d);
    } catch (err) {
      setLoadError(err instanceof Error ? err.message : 'Unknown error');
    } finally {
      setLoading(false);
    }
  }

  async function runAudit(
    assetType: 'flexible_asset' | 'configuration',
    assetId: string
  ): Promise<void> {
    const key = `${assetType}:${assetId}`;
    setAuditing(key);
    try {
      const res = await fetch(
        `/api/analyzer/analyses/${analysisId}/itglue-suggestions`,
        {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ assetType, assetId, provider }),
        }
      );
      const d = await res.json();
      if (!res.ok) throw new Error(d.message || d.error || 'Audit failed');
      toast.success('Audit complete');
      // Refresh the suggestions to pick up the new audit row.
      await loadSuggestions();
    } catch (err) {
      toast.error(err instanceof Error ? err.message : 'Audit failed');
    } finally {
      setAuditing(null);
    }
  }

  async function applyGap(
    assetType: 'flexible_asset' | 'configuration',
    assetId: string,
    auditId: string,
    gap: FieldGap | NotePromotion,
    kind: 'field_gap' | 'note_promotion'
  ): Promise<void> {
    if (!canWrite) return;
    const fieldName =
      kind === 'field_gap' ? (gap as FieldGap).field_name : (gap as NotePromotion).target_field;
    const suggested =
      kind === 'field_gap'
        ? (gap as FieldGap).suggested_value
        : (gap as NotePromotion).suggested_value;
    if (suggested === null || suggested === undefined || suggested === '') {
      toast.error('No suggested value to apply');
      return;
    }
    const evidence =
      kind === 'field_gap'
        ? {
            ticket_numbers: (gap as FieldGap).evidence_ticket_numbers,
            gap_description: (gap as FieldGap).why_missing_matters,
          }
        : {
            ticket_numbers: [],
            gap_description: `Promoted from Notes: "${(gap as NotePromotion).quoted_note_text}"`,
          };
    const key = `${assetType}:${assetId}:${kind}:${fieldName}`;
    setBusyKey(key);
    try {
      const path =
        assetType === 'flexible_asset'
          ? `/api/analyzer/itglue/applications/${assetId}/apply`
          : `/api/analyzer/itglue/configurations/${assetId}/apply`;
      const res = await fetch(path, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          auditId,
          fieldName,
          suggestedValue: suggested,
          sourceEvidence: evidence,
        }),
      });
      const d = await res.json();
      if (!res.ok) throw new Error(d.message || d.error || 'Apply failed');
      toast.success(`Applied: ${fieldName}`);
      await loadSuggestions();
    } catch (err) {
      toast.error(err instanceof Error ? err.message : 'Apply failed');
    } finally {
      setBusyKey(null);
    }
  }

  const totalMatches = useMemo(() => {
    if (!data) return 0;
    return data.flexibleAssets.length + data.configurations.length;
  }, [data]);

  return (
    <Card>
      <CardHeader>
        <div className="flex items-start justify-between gap-3 flex-wrap">
          <div className="flex items-center gap-2">
            <Database className="w-5 h-5" />
            <CardTitle className="text-base">IT Glue documentation</CardTitle>
          </div>
          <div className="flex items-center gap-2 flex-wrap">
            <ProviderToggle value={provider} onChange={setProvider} size="sm" />
            <Button onClick={loadSuggestions} disabled={loading} size="sm">
              {loading ? (
                <>
                  <Loader2 className="w-3.5 h-3.5 mr-1.5 animate-spin" />
                  Checking…
                </>
              ) : data ? (
                <>
                  <Sparkles className="w-3.5 h-3.5 mr-1.5" />
                  Re-check
                </>
              ) : (
                <>
                  <Sparkles className="w-3.5 h-3.5 mr-1.5" />
                  Check IT Glue documentation
                </>
              )}
            </Button>
          </div>
        </div>
      </CardHeader>
      <CardContent className="space-y-4">
        {loadError && (
          <Alert variant="destructive">
            <AlertTitle>Couldn&rsquo;t load suggestions</AlertTitle>
            <AlertDescription>{loadError}</AlertDescription>
          </Alert>
        )}

        {!data && !loading && !loadError && (
          <p className="text-sm text-muted-foreground">
            Click <strong>Check IT Glue documentation</strong> to find IT Glue
            records this ticket touched and surface what should be documented.
          </p>
        )}

        {data && (
          <>
            <p className="text-sm text-muted-foreground">
              Matched <strong>{totalMatches}</strong> IT Glue record
              {totalMatches === 1 ? '' : 's'} for{' '}
              <strong>{data.organizationName ?? 'this client'}</strong>.
              {totalMatches === 0 &&
                ' (No matches — ticket fingerprint did not mention any IT Glue assets we could find.)'}
            </p>

            {data.flexibleAssets.length > 0 && (
              <section className="space-y-3">
                <h3 className="text-xs font-semibold uppercase tracking-wide text-muted-foreground flex items-center gap-1">
                  <Layers className="w-3.5 h-3.5" /> Applications ({data.flexibleAssets.length})
                </h3>
                {data.flexibleAssets.map((m) =>
                  renderAssetMatch(
                    m,
                    'flexible_asset',
                    auditing === `flexible_asset:${m.id}`,
                    busyKey,
                    canWrite,
                    () => runAudit('flexible_asset', m.id),
                    (g, k, auditId) => applyGap('flexible_asset', m.id, auditId, g, k)
                  )
                )}
              </section>
            )}

            {data.configurations.length > 0 && (
              <section className="space-y-3">
                <h3 className="text-xs font-semibold uppercase tracking-wide text-muted-foreground flex items-center gap-1">
                  <Server className="w-3.5 h-3.5" /> Configurations ({data.configurations.length})
                </h3>
                {data.configurations.map((m) =>
                  renderAssetMatch(
                    m,
                    'configuration',
                    auditing === `configuration:${m.id}`,
                    busyKey,
                    canWrite,
                    () => runAudit('configuration', m.id),
                    (g, k, auditId) => applyGap('configuration', m.id, auditId, g, k)
                  )
                )}
              </section>
            )}
          </>
        )}
      </CardContent>
    </Card>
  );
}

function renderAssetMatch(
  m: MatchedAsset,
  assetType: 'flexible_asset' | 'configuration',
  auditing: boolean,
  busyKey: string | null,
  canWrite: boolean,
  onRunAudit: () => void,
  onApply: (
    gap: FieldGap | NotePromotion,
    kind: 'field_gap' | 'note_promotion',
    auditId: string
  ) => void
) {
  const detailHref =
    assetType === 'flexible_asset'
      ? `/analyzer/itglue/applications/${m.id}`
      : `/analyzer/itglue/configurations/${m.id}`;
  const audit = m.latestAudit;
  return (
    <div key={`${assetType}:${m.id}`} className="rounded-md border p-3 space-y-3">
      <div className="flex items-start justify-between gap-3 flex-wrap">
        <div className="min-w-0 flex-1">
          <Link href={detailHref} className="font-medium hover:underline">
            {m.name ?? m.id}
          </Link>
          <p className="text-xs text-muted-foreground mt-0.5">
            {m.type_name ?? '—'}
            {m.hostname && ` · ${m.hostname}`}
            {' · '}match: <span className="font-mono">{m.matched_term}</span>
            {audit?.overall_score !== null && audit?.overall_score !== undefined && (
              <>
                {' · '}score{' '}
                <Badge
                  variant={
                    (audit.overall_score ?? 0) > 0.8
                      ? 'default'
                      : (audit.overall_score ?? 0) > 0.5
                        ? 'secondary'
                        : 'destructive'
                  }
                  className="text-[10px]"
                >
                  {Math.round((audit.overall_score ?? 0) * 100)}%
                </Badge>
              </>
            )}
          </p>
        </div>
        <div className="flex items-center gap-2 shrink-0">
          <Button asChild variant="outline" size="sm">
            <Link href={detailHref}>
              Open
              <ExternalLink className="w-3 h-3 ml-1" />
            </Link>
          </Button>
          <Button onClick={onRunAudit} disabled={auditing} size="sm">
            {auditing ? (
              <>
                <Loader2 className="w-3.5 h-3.5 mr-1.5 animate-spin" />
                Auditing…
              </>
            ) : (
              <>
                <Sparkles className="w-3.5 h-3.5 mr-1.5" />
                {audit ? 'Re-audit for this ticket' : 'Audit for this ticket'}
              </>
            )}
          </Button>
        </div>
      </div>

      {audit && (
        <div className="space-y-2">
          {audit.field_gaps.length === 0 && audit.notes_promotions.length === 0 && (
            <p className="text-xs text-muted-foreground">
              No new gaps surfaced from this ticket. Existing record looks
              sufficient for what was learned.
            </p>
          )}
          {audit.field_gaps.map((g) => {
            const k = `${assetType}:${m.id}:field_gap:${g.field_name}`;
            const busy = busyKey === k;
            return (
              <div
                key={k}
                className={`border-l-4 rounded p-2 ${CONFIDENCE_TONE[g.confidence]}`}
              >
                <div className="flex items-start justify-between gap-2 flex-wrap">
                  <div className="min-w-0 flex-1">
                    <p className="text-sm font-medium">{g.field_name}</p>
                    <p className="text-xs mt-0.5">{g.why_missing_matters}</p>
                    {g.suggested_value !== null && (
                      <p className="text-xs mt-1">
                        <span className="font-medium">Suggested: </span>
                        <span className="font-mono break-all">
                          {g.suggested_value}
                        </span>
                      </p>
                    )}
                  </div>
                  <div className="flex items-center gap-1 shrink-0">
                    <Badge variant="outline" className="text-[10px] uppercase">
                      {g.confidence}
                    </Badge>
                    <Button
                      size="sm"
                      disabled={
                        !canWrite ||
                        g.suggested_value === null ||
                        g.suggested_value === '' ||
                        busy
                      }
                      onClick={() => onApply(g, 'field_gap', audit.id)}
                      title={
                        !canWrite
                          ? 'Requires admin'
                          : g.suggested_value === null
                            ? 'No concrete suggestion'
                            : 'Apply to IT Glue'
                      }
                    >
                      {busy ? (
                        <Loader2 className="w-3 h-3 animate-spin" />
                      ) : (
                        <CheckCircle2 className="w-3 h-3 mr-1" />
                      )}
                      Apply
                    </Button>
                  </div>
                </div>
              </div>
            );
          })}
          {audit.notes_promotions.map((p, i) => {
            const k = `${assetType}:${m.id}:note_promotion:${p.target_field}:${i}`;
            const busy = busyKey === `${assetType}:${m.id}:note_promotion:${p.target_field}`;
            return (
              <div
                key={k}
                className="border-l-4 border-primary/40 bg-primary/5 rounded p-2"
              >
                <div className="flex items-start justify-between gap-2 flex-wrap">
                  <div className="min-w-0 flex-1">
                    <p className="text-xs font-mono italic text-muted-foreground break-words">
                      &ldquo;{p.quoted_note_text}&rdquo;
                    </p>
                    <p className="text-xs mt-1">
                      → <span className="font-medium">{p.target_field}</span>:{' '}
                      <span className="font-mono break-all">{p.suggested_value}</span>
                    </p>
                  </div>
                  <div className="flex items-center gap-1 shrink-0">
                    <Badge variant="outline" className="text-[10px] uppercase">
                      {p.confidence}
                    </Badge>
                    <Button
                      size="sm"
                      disabled={!canWrite || busy}
                      onClick={() => onApply(p, 'note_promotion', audit.id)}
                      title={!canWrite ? 'Requires admin' : 'Apply to IT Glue'}
                    >
                      {busy ? (
                        <Loader2 className="w-3 h-3 animate-spin" />
                      ) : (
                        <CheckCircle2 className="w-3 h-3 mr-1" />
                      )}
                      Apply
                    </Button>
                  </div>
                </div>
              </div>
            );
          })}
          {audit.contradictions.length > 0 && (
            <div className="text-xs text-muted-foreground space-y-1">
              {audit.contradictions.map((c, i) => (
                <p key={i}>
                  ⚠ {c.description}
                  <span className="ml-1">— {c.evidence}</span>
                </p>
              ))}
            </div>
          )}
        </div>
      )}
    </div>
  );
}

interface MatchedAssetExt extends MatchedAsset {
  hostname?: string | null;
}
void ({} as MatchedAssetExt);
