/**
 * MergeReviewDrawer — Full merge request review interface.
 * Shows: diff summary, conflict cards per conflict class, resolution controls.
 * Supports approve / reject / request-changes decisions.
 */
import { useState, useEffect } from 'react';
import { createPortal } from 'react-dom';
import { motion, AnimatePresence } from 'framer-motion';
import { X, GitMerge, Plus, Edit2, ArrowUpDown, Trash2, AlertTriangle, CheckCircle2, ChevronDown } from 'lucide-react';
import { Button } from '@/components/ui/button';
import type { MergeRequest, ConflictRecord } from '../../types/canvas';

interface MergeReviewDrawerProps {
  mergeRequest: MergeRequest | null;
  isOpen: boolean;
  onClose: () => void;
  onReview: (decision: 'approve' | 'reject' | 'changes_requested', comment?: string) => Promise<void>;
}

const CONFLICT_CLASS_CONFIG: Record<string, {
  icon: typeof AlertTriangle;
  label: string;
  color: string;
  bg: string;
  description: string;
  severity: 'none' | 'low' | 'medium' | 'high';
}> = {
  safe_append: {
    icon: Plus, label: 'Safe Append', color: '#34d399', bg: 'rgba(52,211,153,0.1)',
    description: 'New component added in source, not present in target. Will be appended.',
    severity: 'none',
  },
  safe_reorder: {
    icon: ArrowUpDown, label: 'Safe Reorder', color: '#60a5fa', bg: 'rgba(96,165,250,0.1)',
    description: 'Component order differs between branches. Will be merged using longest-common-subsequence.',
    severity: 'none',
  },
  component_content_conflict: {
    icon: Edit2, label: 'Content Conflict', color: '#fbbf24', bg: 'rgba(251,191,36,0.1)',
    description: 'Both branches edited the same component content. Manual resolution required.',
    severity: 'high',
  },
  query_descriptor_conflict: {
    icon: AlertTriangle, label: 'Query Conflict', color: '#f87171', bg: 'rgba(248,113,113,0.1)',
    description: 'Data source or filter parameters conflict. Requires reviewer decision.',
    severity: 'high',
  },
  layout_slot_conflict: {
    icon: ArrowUpDown, label: 'Layout Conflict', color: '#fbbf24', bg: 'rgba(251,191,36,0.1)',
    description: 'Same layout slot claimed by different components.',
    severity: 'medium',
  },
  access_policy_conflict: {
    icon: AlertTriangle, label: 'Policy Conflict', color: '#f87171', bg: 'rgba(248,113,113,0.1)',
    description: 'Access control policies diverge. Stricter policy will prevail.',
    severity: 'high',
  },
  delete_edit_conflict: {
    icon: Trash2, label: 'Delete-Edit Conflict', color: '#f87171', bg: 'rgba(248,113,113,0.1)',
    description: 'Component deleted in one branch, edited in another.',
    severity: 'high',
  },
};

function ConflictCard({ conflict, resolution, onResolve }: {
  conflict: ConflictRecord;
  resolution?: string;
  onResolve: (id: string, decision: string) => void;
}) {
  const [expanded, setExpanded] = useState(false);
  const cfg = CONFLICT_CLASS_CONFIG[conflict.conflictClass] ?? CONFLICT_CLASS_CONFIG.component_content_conflict;
  const Icon = cfg.icon;
  const isResolved = !!resolution;

  return (
    <div
      className="rounded-xl overflow-hidden"
      style={{ background: cfg.bg, border: `1px solid ${cfg.color}30` }}
    >
      <button
        className="w-full flex items-center gap-3 p-3.5 text-left"
        onClick={() => setExpanded((p) => !p)}
      >
        <Icon className="w-4 h-4 flex-shrink-0" style={{ color: cfg.color }} />
        <div className="min-w-0 flex-1">
          <div className="flex items-center gap-2">
            <span className="text-xs font-semibold" style={{ color: cfg.color }}>{cfg.label}</span>
            {isResolved && (
              <CheckCircle2 className="w-3 h-3 text-green-400" />
            )}
          </div>
          <p className="text-[10px] text-zinc-500 truncate font-mono">
            {conflict.componentId}{conflict.field ? ` → ${conflict.field}` : ''}
          </p>
        </div>
        <ChevronDown
          className="w-3.5 h-3.5 text-zinc-600 flex-shrink-0 transition-transform"
          style={{ transform: expanded ? 'rotate(180deg)' : 'none' }}
        />
      </button>

      <AnimatePresence>
        {expanded && (
          <motion.div
            initial={{ height: 0 }}
            animate={{ height: 'auto' }}
            exit={{ height: 0 }}
            className="overflow-hidden border-t"
            style={{ borderColor: `${cfg.color}25` }}
          >
            <div className="p-3.5 space-y-3">
              <p className="text-xs text-zinc-300">{cfg.description}</p>
              {conflict.description && (
                <p className="text-xs text-zinc-400 italic">"{conflict.description}"</p>
              )}
              {/* Show values if present */}
              {(conflict.sourceValue !== undefined || conflict.targetValue !== undefined) && (
                <div className="grid grid-cols-2 gap-2">
                  {conflict.sourceValue !== undefined && (
                    <div className="p-2 rounded-lg" style={{ background: 'rgba(255,255,255,0.04)' }}>
                      <p className="text-[10px] text-zinc-500 mb-1">Source</p>
                      <p className="text-xs text-zinc-300 font-mono break-all">
                        {JSON.stringify(conflict.sourceValue).slice(0, 80)}
                      </p>
                    </div>
                  )}
                  {conflict.targetValue !== undefined && (
                    <div className="p-2 rounded-lg" style={{ background: 'rgba(255,255,255,0.04)' }}>
                      <p className="text-[10px] text-zinc-500 mb-1">Target</p>
                      <p className="text-xs text-zinc-300 font-mono break-all">
                        {JSON.stringify(conflict.targetValue).slice(0, 80)}
                      </p>
                    </div>
                  )}
                </div>
              )}

              {/* Resolution buttons */}
              {cfg.severity !== 'none' && !isResolved && (
                <div className="flex gap-2">
                  <button
                    className="text-[10px] px-2.5 py-1.5 rounded-lg transition-all flex-1"
                    style={{ background: 'rgba(59,130,246,0.15)', color: '#60a5fa', border: '1px solid rgba(59,130,246,0.3)' }}
                    onClick={() => onResolve(conflict.conflictId, 'source_wins')}
                  >
                    Use Source
                  </button>
                  <button
                    className="text-[10px] px-2.5 py-1.5 rounded-lg transition-all flex-1"
                    style={{ background: 'rgba(255,255,255,0.06)', color: '#a1a1aa', border: '1px solid rgba(255,255,255,0.1)' }}
                    onClick={() => onResolve(conflict.conflictId, 'target_wins')}
                  >
                    Keep Target
                  </button>
                </div>
              )}

              {isResolved && (
                <div className="flex items-center gap-2">
                  <CheckCircle2 className="w-3.5 h-3.5 text-green-400" />
                  <span className="text-xs text-green-300">Resolved: {resolution}</span>
                </div>
              )}
            </div>
          </motion.div>
        )}
      </AnimatePresence>
    </div>
  );
}

export function MergeReviewDrawer({ mergeRequest, isOpen, onClose, onReview }: MergeReviewDrawerProps) {
  const [mounted, setMounted] = useState(false);
  useEffect(() => setMounted(true), []);

  const [comment, setComment] = useState('');
  const [submitting, setSubmitting] = useState(false);
  const [resolutions, setResolutions] = useState<Record<string, string>>({});
  const [success, setSuccess] = useState<string | null>(null);

  const conflicts: ConflictRecord[] = mergeRequest?.conflicts ?? [];
  const diff = mergeRequest?.diffSummary;
  const highSeverityConflicts = conflicts.filter(
    (c) => (CONFLICT_CLASS_CONFIG[c.conflictClass]?.severity ?? 'none') === 'high'
  );
  const unresolvedHigh = highSeverityConflicts.filter((c) => !resolutions[c.conflictId]);
  const canApprove = unresolvedHigh.length === 0;

  const handleReview = async (decision: 'approve' | 'reject' | 'changes_requested') => {
    setSubmitting(true);
    try {
      await onReview(decision, comment);
      setSuccess(decision);
      setTimeout(() => {
        setSuccess(null);
        onClose();
      }, 2000);
    } finally {
      setSubmitting(false);
    }
  };

  const content = (
    <AnimatePresence>
      {isOpen && (
        <>
          <motion.div
            key="mr-backdrop"
            className="fixed inset-0 z-40"
            style={{ background: 'rgba(0,0,0,0.65)', backdropFilter: 'blur(4px)' }}
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            onClick={onClose}
          />
          <motion.div
            key="mr-drawer"
            className="fixed z-50 right-0 top-0 h-full"
            style={{ width: 480 }}
            initial={{ x: 480 }}
            animate={{ x: 0 }}
            exit={{ x: 480 }}
            transition={{ type: 'spring', stiffness: 300, damping: 30 }}
          >
            <div
              className="h-full flex flex-col"
              style={{
                background: 'rgba(10, 11, 18, 0.99)',
                borderLeft: '1px solid rgba(255,255,255,0.1)',
              }}
            >
              {/* Header */}
              <div
                className="flex items-center justify-between px-5 py-4 flex-shrink-0"
                style={{ borderBottom: '1px solid rgba(255,255,255,0.08)' }}
              >
                <div className="flex items-center gap-3">
                  <div className="w-8 h-8 rounded-xl bg-violet-500/15 border border-violet-500/25 flex items-center justify-center">
                    <GitMerge className="w-4 h-4 text-violet-400" />
                  </div>
                  <div>
                    <h2 className="text-sm font-semibold text-zinc-100">
                      {mergeRequest?.title ?? 'Merge Request'}
                    </h2>
                    <p className="text-xs text-zinc-500">
                      {mergeRequest?.sourceBranchId ?? 'fork'} → {mergeRequest?.targetBranchId ?? 'main'}
                    </p>
                  </div>
                </div>
                <button onClick={onClose} className="text-zinc-600 hover:text-zinc-300 transition-colors">
                  <X className="w-4 h-4" />
                </button>
              </div>

              {success ? (
                <div className="flex-1 flex flex-col items-center justify-center gap-4">
                  <CheckCircle2 className="w-12 h-12 text-green-400" />
                  <p className="text-base font-medium text-zinc-100 capitalize">
                    {success === 'approve' ? 'Merge approved!' : success === 'reject' ? 'Review rejected' : 'Changes requested'}
                  </p>
                </div>
              ) : (
                <>
                  <div className="flex-1 overflow-y-auto custom-scrollbar px-5 py-4 space-y-5">
                    {/* Diff summary */}
                    {diff && (
                      <div>
                        <h3 className="text-xs font-semibold text-zinc-400 uppercase tracking-wide mb-3">Changes</h3>
                        <div className="grid grid-cols-4 gap-2">
                          {[
                            { label: 'Added', val: diff.componentsAdded, color: '#34d399', icon: Plus },
                            { label: 'Edited', val: diff.componentsEdited, color: '#60a5fa', icon: Edit2 },
                            { label: 'Reordered', val: diff.componentsReordered, color: '#a78bfa', icon: ArrowUpDown },
                            { label: 'Deleted', val: diff.componentsDeleted, color: '#f87171', icon: Trash2 },
                          ].map(({ label, val, color, icon: Icon }) => (
                            <div
                              key={label}
                              className="p-2.5 rounded-xl text-center"
                              style={{ background: `${color}10`, border: `1px solid ${color}25` }}
                            >
                              <Icon className="w-3.5 h-3.5 mx-auto mb-1" style={{ color }} />
                              <p className="text-base font-bold" style={{ color }}>{val}</p>
                              <p className="text-[10px] text-zinc-600 uppercase tracking-wider">{label}</p>
                            </div>
                          ))}
                        </div>
                      </div>
                    )}

                    {/* Conflicts */}
                    {conflicts.length > 0 && (
                      <div>
                        <div className="flex items-center justify-between mb-3">
                          <h3 className="text-xs font-semibold text-zinc-400 uppercase tracking-wide">
                            Conflicts ({conflicts.length})
                          </h3>
                          {unresolvedHigh.length > 0 && (
                            <span className="text-[10px] text-amber-400">
                              {unresolvedHigh.length} require resolution
                            </span>
                          )}
                        </div>
                        <div className="space-y-2">
                          {conflicts.map((c) => (
                            <ConflictCard
                              key={c.conflictId}
                              conflict={c}
                              resolution={resolutions[c.conflictId]}
                              onResolve={(id, decision) =>
                                setResolutions((p) => ({ ...p, [id]: decision }))
                              }
                            />
                          ))}
                        </div>
                      </div>
                    )}

                    {conflicts.length === 0 && (
                      <div
                        className="flex items-center gap-3 p-4 rounded-xl"
                        style={{ background: 'rgba(52,211,153,0.07)', border: '1px solid rgba(52,211,153,0.2)' }}
                      >
                        <CheckCircle2 className="w-5 h-5 text-green-400 flex-shrink-0" />
                        <p className="text-sm text-green-300">No conflicts — clean merge</p>
                      </div>
                    )}

                    {/* Reviewer comment */}
                    <div>
                      <label className="text-xs font-medium text-zinc-400 mb-1.5 block">Reviewer comment</label>
                      <textarea
                        value={comment}
                        onChange={(e) => setComment(e.target.value)}
                        placeholder="Optional note for the author…"
                        rows={3}
                        className="w-full px-3 py-2.5 text-sm rounded-xl resize-none focus:outline-none"
                        style={{
                          background: 'rgba(255,255,255,0.04)',
                          border: '1px solid rgba(255,255,255,0.1)',
                          color: '#e4e4e7',
                        }}
                      />
                    </div>
                  </div>

                  {/* Decision buttons */}
                  <div
                    className="flex gap-2 px-5 py-4 flex-shrink-0"
                    style={{ borderTop: '1px solid rgba(255,255,255,0.07)' }}
                  >
                    <Button
                      variant="outline"
                      onClick={() => void handleReview('reject')}
                      disabled={submitting}
                      className="flex-1 border-red-500/30 bg-red-500/10 text-red-400 hover:bg-red-500/20"
                    >
                      Reject
                    </Button>
                    <Button
                      variant="outline"
                      onClick={() => void handleReview('changes_requested')}
                      disabled={submitting}
                      className="flex-1 border-amber-500/30 bg-amber-500/10 text-amber-400 hover:bg-amber-500/20"
                    >
                      Request Changes
                    </Button>
                    <Button
                      onClick={() => void handleReview('approve')}
                      disabled={!canApprove || submitting}
                      className="flex-1 bg-green-700 hover:bg-green-600 text-white disabled:opacity-40"
                    >
                      {canApprove ? 'Approve & Merge' : `Resolve ${unresolvedHigh.length} conflicts`}
                    </Button>
                  </div>
                </>
              )}
            </div>
          </motion.div>
        </>
      )}
    </AnimatePresence>
  );

  if (!mounted) return null;
  return createPortal(content, document.body);
}
