'use client';

import { useState, useMemo } from 'react';
import { useQuery, useMutation } from '@tanstack/react-query';
import { useRouter } from 'next/navigation';
import { Loader2, X, ChevronDown, ChevronRight } from 'lucide-react';
import {
  fetchPushPendingPreview, confirmBulkPush,
  type PushPendingPreviewItem,
} from '@/lib/api';
import styles from './PushPendingModal.module.css';

const FIELD_LABELS: Record<string, string> = {
  title: 'Title', description: 'Description', privacyStatus: 'Visibility',
  tags: 'Tags', categoryId: 'Category', defaultLanguage: 'Language',
  defaultAudioLanguage: 'Audio Language', selfDeclaredMadeForKids: 'Made for Kids',
  embeddable: 'Embeddable', license: 'License', recordingDate: 'Recording Date',
};

function FieldChip({ field }: { field: string }) {
  return <span className={styles.fieldChip}>{FIELD_LABELS[field] ?? field}</span>;
}

function TagsDiff({ before, after }: { before: string[]; after: string[] }) {
  const beforeSet = new Set(before);
  const afterSet = new Set(after);
  const removed = before.filter((t) => !afterSet.has(t));
  const added = after.filter((t) => !beforeSet.has(t));
  const kept = after.filter((t) => beforeSet.has(t));
  return (
    <div className={styles.tagsDiff}>
      {kept.map((t) => <span key={t} className={styles.tagKept}>{t}</span>)}
      {removed.map((t) => <span key={t} className={styles.tagRemoved}>{t}</span>)}
      {added.map((t) => <span key={t} className={styles.tagAdded}>{t}</span>)}
    </div>
  );
}

function DiffRow({ field, item }: { field: string; item: PushPendingPreviewItem }) {
  const label = FIELD_LABELS[field] ?? field;
  const d = item.diff[field as keyof typeof item.diff];
  if (!d) return null;

  if (field === 'tags') {
    return (
      <tr>
        <td className={styles.diffField}>{label}</td>
        <td className={styles.diffBefore}>{(d.before as string[]).join(', ') || '—'}</td>
        <td className={styles.diffAfter}><TagsDiff before={d.before as string[]} after={d.after as string[]} /></td>
      </tr>
    );
  }
  if (field === 'description') {
    return (
      <tr>
        <td className={styles.diffField}>{label}</td>
        <td className={styles.diffBefore}><pre className={styles.descPre}>{d.before ?? '—'}</pre></td>
        <td className={styles.diffAfter}><pre className={styles.descPre}>{d.after ?? '—'}</pre></td>
      </tr>
    );
  }
  const fmt = (v: string | number | boolean | string[] | null | undefined) => {
    if (v === null || v === undefined) return '—';
    if (typeof v === 'boolean') return v ? 'Yes' : 'No';
    return String(v);
  };
  return (
    <tr>
      <td className={styles.diffField}>{label}</td>
      <td className={styles.diffBefore}>{fmt(d.before)}</td>
      <td className={styles.diffAfter}>{fmt(d.after)}</td>
    </tr>
  );
}

function VideoRow({
  item,
  selected,
  onToggle,
}: {
  item: PushPendingPreviewItem;
  selected: boolean;
  onToggle: () => void;
}) {
  const [expanded, setExpanded] = useState(false);
  const thumb = item.thumbnailUrl ?? `https://img.youtube.com/vi/${item.videoId}/mqdefault.jpg`;

  return (
    <>
      <tr className={`${styles.row} ${!selected ? styles.rowDeselected : ''}`}>
        <td className={styles.colCheck}>
          <input type="checkbox" checked={selected} onChange={onToggle} className={styles.checkbox} />
        </td>
        <td className={styles.colThumb}>
          {/* eslint-disable-next-line @next/next/no-img-element */}
          <img src={thumb} alt="" width={80} height={45} className={styles.thumb} />
        </td>
        <td className={styles.colMeta}>
          <span className={styles.rowTitle}>{item.title}</span>
          <div className={styles.chips}>
            {item.firstSync
              ? <span className={`${styles.fieldChip} ${styles.chipFirstSync}`}>First sync</span>
              : item.changedFields.map((f) => <FieldChip key={f} field={f} />)
            }
          </div>
        </td>
        <td className={styles.colExpand}>
          <button className={styles.expandBtn} onClick={() => setExpanded((e) => !e)}>
            {expanded ? <ChevronDown size={16} /> : <ChevronRight size={16} />}
          </button>
        </td>
      </tr>
      {expanded && (
        <tr className={styles.diffRow}>
          <td colSpan={4} className={styles.diffCell}>
            <table className={styles.diffTable}>
              <thead>
                <tr>
                  <th className={styles.diffField}>Field</th>
                  <th className={styles.diffBefore}>Before</th>
                  <th className={styles.diffAfter}>After</th>
                </tr>
              </thead>
              <tbody>
                {item.changedFields.map((f) => (
                  <DiffRow key={f} field={f} item={item} />
                ))}
              </tbody>
            </table>
          </td>
        </tr>
      )}
    </>
  );
}

export default function PushPendingModal({ onClose, sort, order }: { onClose: () => void; sort?: string; order?: string }) {
  const router = useRouter();

  const { data: items = [], isLoading } = useQuery({
    queryKey: ['pushPendingPreview', sort, order],
    queryFn: () => fetchPushPendingPreview(sort, order),
    staleTime: 30_000,
  });

  // null = untouched (treat as all selected); Set = explicit selection state
  const [selected, setSelected] = useState<Set<string> | null>(null);

  const effectiveSelected = useMemo(
    () => selected ?? new Set(items.map((i) => i.videoId)),
    [items, selected],
  );

  const allSelected = items.length > 0 && effectiveSelected.size === items.length;

  const toggleAll = () => {
    if (allSelected) setSelected(new Set());
    else setSelected(new Set(items.map((i) => i.videoId)));
  };

  const toggleOne = (id: string) => {
    const next = new Set(effectiveSelected);
    if (next.has(id)) next.delete(id);
    else next.add(id);
    setSelected(next);
  };

  const confirmMut = useMutation({
    mutationFn: () => confirmBulkPush([...effectiveSelected]),
    onSuccess: () => {
      setSelected(null);
      onClose();
      router.push('/bulk-jobs');
    },
  });

  const selectedCount = effectiveSelected.size;

  return (
    <div className={styles.overlay} onClick={(e) => e.target === e.currentTarget && onClose()}>
      <div className={styles.modal}>
        <div className={styles.modalHeader}>
          <h2 className={styles.modalTitle}>Push Pending Videos</h2>
          <button className={styles.closeBtn} onClick={onClose}><X size={18} /></button>
        </div>

        <div className={styles.tableContainer}>
          {isLoading && (
            <div className={styles.loadingState}>
              <Loader2 size={20} className={styles.spinner} />
              <span>Loading pending changes…</span>
            </div>
          )}
          {!isLoading && items.length === 0 && (
            <div className={styles.emptyState}>No pending videos found.</div>
          )}
          {!isLoading && items.length > 0 && (
            <table className={styles.videoTable}>
              <thead>
                <tr>
                  <th className={styles.colCheck}></th>
                  <th className={styles.colThumb}></th>
                  <th className={styles.colMeta}>Video</th>
                  <th className={styles.colExpand}></th>
                </tr>
              </thead>
              <tbody>
                {items.map((item) => (
                  <VideoRow
                    key={item.videoId}
                    item={item}
                    selected={effectiveSelected.has(item.videoId)}
                    onToggle={() => toggleOne(item.videoId)}
                  />
                ))}
              </tbody>
            </table>
          )}
        </div>

        {!isLoading && items.length > 0 && (
          <div className={styles.modalFooter}>
            <button className={styles.selectAll} onClick={toggleAll}>
              {allSelected ? 'Deselect all' : 'Select all'}
            </button>
            <span className={styles.footerNote}>
              Videos are pushed in order, respecting YouTube quota limits.
            </span>
            <div className={styles.footerActions}>
              <button className="btn btn-secondary" onClick={onClose}>Cancel</button>
              <button
                className="btn btn-primary"
                disabled={selectedCount === 0 || confirmMut.isPending}
                onClick={() => confirmMut.mutate()}
              >
                {confirmMut.isPending ? <Loader2 size={14} className={styles.spinner} /> : null}
                Push {selectedCount} video{selectedCount !== 1 ? 's' : ''}
              </button>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}
