
import React, { useState, useRef, useEffect, useMemo } from 'react';
import ReactDOM from 'react-dom/client';
import { PlusIcon } from './icons/PlusIcon';
import { ArrowLeftIcon } from './icons/ArrowLeftIcon';
import type { AgentReview, FlaggedItem, ResolvedItem, OverallStatus } from '../types';
import { FeedbackReport } from './FeedbackReport';
import { CreateCampaignModal } from './CreateCampaignModal';
import { CheckCircleIcon, ArrowPathIcon, ExclamationTriangleIcon } from './icons/StatusIcons';
import { ProofPreview } from './ProofPreview';
import { HistoryIcon } from './icons/HistoryIcon';
import { DropdownOptions } from '../App';
import { ChannelIcon } from './icons/ChannelIcon';
import { TagIcon } from './icons/TagIcon';
import { ChevronDownIcon } from './icons/ChevronDownIcon';
import { UploadIcon } from './icons/UploadIcon';
import { DocumentIcon } from './icons/DocumentIcon';
import { SpinnerIcon } from './icons/SpinnerIcon';
import { AGENT_NAMES } from '../constants';
import { ToggleSwitch } from './ToggleSwitch';
import { TrashIcon } from './icons/TrashIcon';
import { DownloadIcon } from './icons/DownloadIcon';
import { PDFIcon } from './icons/PDFIcon';
import { PDFReport } from './PDFReport';
import { ExportIcon } from './icons/ExportIcon';
import { XIcon } from './icons/XIcon';
import apiService from '../services/apiService';
import { usePdfPages } from '../hooks/usePdfPages';
import { useUser } from '../contexts/UserContext';

type SortKey = 'name' | 'proofs' | 'status' | 'agencyLead' | 'agency' | 'brandGuidelines' | 'lastModified';
type SortDirection = 'asc' | 'desc';

const formatDate = (isoDateString: string): string => {
  const date = new Date(isoDateString);
  return date.toLocaleDateString('en-US', {
    month: 'short',
    day: 'numeric',
    year: 'numeric'
  });
};

export const initialCampaigns = [
    {
        name: 'Barclays Q4 campaign',
        workfrontId: '#WF_12822',
        clientLead: 'Jane Doe',
        agency: 'OLIVER Agency',
        agencyLead: 'Steve O\'Donoghue',
        proofs: 3,
        status: 'In Progress',
        lastModified: '2024-07-22',
        brandGuidelines: 'Barclays',
        createdBy: null as string | null,
    },
    {
        name: 'Barclays Q3 Roundup',
        workfrontId: '#WF_12750',
        clientLead: 'Jane Doe',
        agency: 'OLIVER Agency',
        agencyLead: 'Steve O\'Donoghue',
        proofs: 1,
        status: 'Completed',
        lastModified: '2024-06-30',
        brandGuidelines: 'Barclays',
        createdBy: null as string | null,
    },
];

const IG_HERO_POST_1_IMAGE_V1 = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTA4MCIgaGVpZ2h0PSIxMDgwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxyZWN0IHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9IiMwMDFmNWEiLz48dGV4dCB4PSI1MCUiIHk9IjUwJSIgZm9udC1mYW1pbHk9InNhbnMtc2VyaWYiIGZvbnQtc2lçZz0iODAiIGZpbGw9IndoaXRlIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBkb21pbmFudC1iYXNlbGluZT0ibWlkZGxlIj5JRyBIZXJvIFBvc3QgMSB2MVc8L3RleHQ+PHRleHQgeD0iNTAlIiB5PSI2MCUiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjQwIiBmaWxsPSJ3aGl0ZSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZG9taW5hbnQtYmFzZWxpbmU9Im1pZGRsZSI+KEFzc2V0IFByZXZpZXcpPC90ZXh0Pjwvc3ZnPg==';
const IG_HERO_POST_1_IMAGE_V2 = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTA4MCIgaGVpZ2h0PSIxMDgwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxyZWN0IHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9IiMwMDcwYzAiLz48dGV4dCB4PSI1MCUiIHk9IjUwJSIgZm9udC1mYW1pbHk9InNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iODAiIGZpbGw9IndoaXRlIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBkb21pbmFudC1iYXNlbGluZT0ibWlkZGxlIj5JRyBIZXJvIFBvc3QgMSB2MjwvdGV4dD48dGV4dCB4PSI1MCUiIHk9IjYwJSIgZm9udC1mYW1pbHk9InNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iNDAiIGZpbGw9IndoaXRlIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBkb21pbmFudC1iYXNlbGluZT0ibWlkZGxlIj4oQ29ycmVjdGlvbnMgQXBwbGllZCk8L3RleHQ+PC9zdmc+';

const IG_HERO_POST_1_FEEDBACK_V1: AgentReview = {
  overallStatus: "Analysis Error",
  leadAgentSummary: "The proof could not be reliably processed by some agents due to low confidence in the analysis. This may happen if the proof is too abstract or irrelevant to typical marketing content. This version has been logged for manual human review. Please try uploading a revised version of the proof.",
  legalAgentReview: {
    ragStatus: "Error",
    feedback: "The agent could not analyse this proof with high confidence. This may be because the content is irrelevant, nonsensical, or too far outside of expected marketing materials.",
    issues: []
  },
  brandAgentReview: {
    ragStatus: "Error",
    feedback: "The agent could not analyse this proof with high confidence. This may be because the content is irrelevant, nonsensical, or too far outside of expected marketing materials.",
    issues: []
  },
  channelBestPracticesAgentReview: {
    ragStatus: "Green",
    feedback: "The content strategy is clear and effectively communicates the partnership message. The call-to-action is prominent.",
    issues: []
  },
  channelTechSpecsAgentReview: {
    ragStatus: "Amber",
    feedback: "While the image quality is high, the composition is not optimised for vertical formats like Instagram Stories. The high ratio of text in the image could also potentially reduce advertising reach on some platforms.",
    issues: ["Image composition is not mobile-first or suitable for vertical formats.", "High ratio of text in the image may negatively impact ad performance."]
  }
};

const IG_HERO_POST_1_FEEDBACK_V2: AgentReview = {
  overallStatus: "Passed",
  leadAgentSummary: "The proof has Passed review. All critical legal and brand issues from the previous version have been successfully addressed. The partnership claim is clear, and the design now fully aligns with brand guidelines. One minor suggestion is to consider a separate vertical version for Story placements, but the proof is approved for deployment.",
  legalAgentReview: {
    ragStatus: "Green",
    feedback: "All legal concerns have been addressed. The partnership claim is now clearly stated as 'Proud principal partner' and all necessary documentation for the use of the Lord's branding has been verified.",
    issues: []
  },
  brandAgentReview: {
    ragStatus: "Green",
    feedback: "The proof now fully aligns with brand guidelines. The 'Principal partner' lockup uses the correct brand font, and the non-standard blue border has been removed, resulting in a cleaner, on-brand look.",
    issues: []
  },
  channelBestPracticesAgentReview: {
    ragStatus: "Green",
    feedback: "The content strategy is effective with clear messaging and well-optimised visual hierarchy. No issues found.",
    issues: []
  },
  channelTechSpecsAgentReview: {
    ragStatus: "Amber",
    feedback: "The image composition has been improved and is suitable for standard feeds. However, for optimal performance on Instagram, creating a separate vertical version for Story placements is recommended.",
    issues: ["Consider creating a separate vertical version for Story placements."]
  }
};

export const initialCampaignProofs: { [key: string]: any[] } = {
    'Barclays Q4 campaign': [
        {
            proofName: 'IG Hero Post 1',
            channel: 'Social',
            subChannel: 'Meta',
            proofType: 'In-feed 4x5',
            status: 'completed',
            overallStatus: 'Passed',
            versions: [
                {
                    version: 2,
                    timestamp: '2024-07-25',
                    workfrontId: '#WF_12823-V2',
                    proofPreviewUrl: IG_HERO_POST_1_IMAGE_V2,
                    feedback: IG_HERO_POST_1_FEEDBACK_V2,
                    overallStatus: 'Passed',
                },
                {
                    version: 1,
                    timestamp: '2024-07-23',
                    workfrontId: '#WF_12823-V1',
                    proofPreviewUrl: IG_HERO_POST_1_IMAGE_V1,
                    feedback: IG_HERO_POST_1_FEEDBACK_V1,
                    overallStatus: 'Analysis Error',
                }
            ]
        },
        {
            proofName: 'Q4 FB Static 4x5',
            channel: 'Social',
            subChannel: 'Meta',
            proofType: 'In-feed 4x5',
            status: 'completed',
            overallStatus: 'Passed',
            versions: [
                {
                    version: 1,
                    timestamp: '2024-07-26',
                    workfrontId: '#WF_12824-V1',
                    proofPreviewUrl: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTA4MCIgaGVpZ2h0PSIxMzUwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxyZWN0IHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9IiMwMDcwYzAiLz48dGV4dCB4PSI1MCUiIHk9IjUwJSIgZm9udC1mYW1pbHk9InNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iODAiIGZpbGw9IndoaXRlIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBkb21pbmFudC1iYXNlbGluZT0ibWlkZGxlIj5GQiBTdGF0aWMgNHg1PC90ZXh0Pjwvc3ZnPg==',
                    feedback: {
                        overallStatus: "Passed",
                        leadAgentSummary: "Passed. Compliant with all guidelines.",
                        legalAgentReview: { ragStatus: "Green", feedback: "Disclaimers present and correct.", issues: [] },
                        brandAgentReview: { ragStatus: "Green", feedback: "On brand colors used.", issues: [] },
                        channelBestPracticesAgentReview: { ragStatus: "Green", feedback: "Content strategy is effective.", issues: [] },
                        channelTechSpecsAgentReview: { ragStatus: "Green", feedback: "Correct specs for FB.", issues: [] }
                    },
                    overallStatus: 'Passed',
                }
            ]
        },
        {
            proofName: 'Q4 IG Story Promo',
            channel: 'Social',
            subChannel: 'Meta',
            proofType: 'Stories Static 9x16',
            status: 'completed',
            overallStatus: 'Passed',
            versions: [
                {
                    version: 1,
                    timestamp: '2024-07-27',
                    workfrontId: '#WF_12825-V1',
                    proofPreviewUrl: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTA4MCIgaGVpZ2h0PSIxOTIwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxyZWN0IHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9IiMwMDFmNWEiLz48dGV4dCB4PSI1MCUiIHk9IjUwJSIgZm9udC1mYW1pbHk9InNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iODAiIGZpbGw9IndoaXRlIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBkb21pbmFudC1iYXNlbGluZT0ibWlkZGxlIj5JRyBTdG9yeTwvdGV4dD48L3N2Zz4=',
                    feedback: {
                        overallStatus: "Passed",
                        leadAgentSummary: "Approved for IG Stories.",
                        legalAgentReview: { ragStatus: "Green", feedback: "Compliant.", issues: [] },
                        brandAgentReview: { ragStatus: "Green", feedback: "Brand aligned.", issues: [] },
                        channelBestPracticesAgentReview: { ragStatus: "Green", feedback: "Engaging content strategy.", issues: [] },
                        channelTechSpecsAgentReview: { ragStatus: "Green", feedback: "Optimised for mobile.", issues: [] }
                    },
                    overallStatus: 'Passed',
                }
            ]
        }
    ],
    'Barclays Q3 Roundup': [
        {
            proofName: 'Q3 Results Infographic',
            channel: 'Display',
            subChannel: 'Banner',
            proofType: '300x600',
            status: 'completed',
            overallStatus: 'Passed',
            versions: [
                {
                  version: 1,
                  timestamp: '2024-06-28',
                  workfrontId: '#WF_12751-V1',
                  proofPreviewUrl: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTA4MCIgaGVpZ2h0PSIxMDgwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxyZWN0IHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9IiNmNGY2ZjgiLz48dGV4dCB4PSI1MCUiIHk9IjUwJSIgZm9udC1mYW1pbHk9InNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iODAiIGZpbGw9IiMwMDFmNWEiLz48dGV4dCB4PSI1MCUiIHk9IjUwJSIgZm9udC1mYW1pbHk9InNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iODAiIGZpbGw9IiMwMDFmNWEiIHRleH0LWFuY2hvcj0ibWlkZGxlIiBkb21pbmFudC1iYXNlbGluZT0ibWlkZGxlIj5RMyBSZXN1bHRzIEluZm9ncmFwaGljPC90ZXh0Pjwvc3ZnPg==',
                  feedback: {
                    overallStatus: "Passed",
                    leadAgentSummary: "The proof has Passed review with no issues found across all categories. It is well-designed, compliant, and ready for deployment.",
                    legalAgentReview: { ragStatus: "Green", feedback: "All claims are substantiated and disclaimers are correctly placed.", issues: [] },
                    brandAgentReview: { ragStatus: "Green", feedback: "The proof adheres perfectly to all brand guidelines.", issues: [] },
                    channelBestPracticesAgentReview: { ragStatus: "Green", feedback: "The content strategy is effective and well-optimised for engagement.", issues: [] },
                    channelTechSpecsAgentReview: { ragStatus: "Green", feedback: "The infographic format is highly suitable for the selected channel.", issues: [] },
                  },
                  overallStatus: 'Passed',
                }
            ]
        }
    ]
};

const StatusBadge: React.FC<{ status: string }> = ({ status }) => {
    let colorClasses = '';
    switch (status) {
        case 'In Progress':
            colorClasses = 'bg-oliver-gold text-oliver-black';
            break;
        case 'Completed':
            colorClasses = 'bg-oliver-green text-white';
            break;
        case 'Needs Review':
            colorClasses = 'bg-warning-light text-oliver-black';
            break;
        default:
            colorClasses = 'bg-oliver-grey text-oliver-black';
    }
    return (
        <span className={`px-2.5 py-0.5 text-xs font-semibold rounded-full ${colorClasses}`}>
            {status}
        </span>
    );
};

const OverallStatusBadge: React.FC<{ status: OverallStatus }> = ({ status }) => {
    let colorClasses = '';
    switch (status) {
        case 'Passed':
            colorClasses = 'bg-success text-white';
            break;
        case 'Failed':
            colorClasses = 'bg-error text-white';
            break;
        case 'Requires Manual Legal Review':
            colorClasses = 'bg-warning text-oliver-black';
            break;
        case 'Analysis Error':
            colorClasses = 'bg-grey-300 text-oliver-black';
            break;
    }

    return (
        <span className={`inline-flex items-center px-3 py-1 text-sm font-bold rounded-full ${colorClasses}`}>
            {status}
        </span>
    );
};


const CampaignList: React.FC<{
    onSelectCampaign: (name: string) => void;
    campaigns: typeof initialCampaigns;
    onOpenModal: () => void;
    onCampaignStatusChange: (campaignName: string, newStatus: 'In Progress' | 'Completed') => void;
    onDeleteCampaign: (campaign: typeof initialCampaigns[0]) => void;
    readOnly?: boolean;
    selectedAgencyId?: string | null;
}> = ({ onSelectCampaign, campaigns, onOpenModal, onCampaignStatusChange, onDeleteCampaign, readOnly = false, selectedAgencyId }) => {
    const { user, isSuperAdmin, isOversightAdmin } = useUser();
    const [showCompleted, setShowCompleted] = useState(true);
    const [showMyCampaignsOnly, setShowMyCampaignsOnly] = useState(false);
    const [selectedCampaigns, setSelectedCampaigns] = useState<Set<string>>(new Set());
    const [campaignToDelete, setCampaignToDelete] = useState<typeof initialCampaigns[0] | null>(null);
    const [showBulkDeleteModal, setShowBulkDeleteModal] = useState(false);
    const [isDeleting, setIsDeleting] = useState(false);
    const [isExportingCsv, setIsExportingCsv] = useState(false);

    const handleExportCsv = async () => {
        setIsExportingCsv(true);
        try {
            await apiService.downloadCampaignsCsv(selectedAgencyId || undefined);
        } catch (err) {
            console.error('CSV export failed:', err);
        } finally {
            setIsExportingCsv(false);
        }
    };
    const [sortKey, setSortKey] = useState<SortKey>('lastModified');
    const [sortDirection, setSortDirection] = useState<SortDirection>('desc');
    const [columnFilters, setColumnFilters] = useState<Record<SortKey, string>>({
        name: '',
        proofs: '',
        status: '',
        agencyLead: '',
        agency: '',
        brandGuidelines: '',
        lastModified: '',
    });

    const handleSort = (key: SortKey) => {
        if (sortKey === key) {
            setSortDirection(prev => prev === 'asc' ? 'desc' : 'asc');
        } else {
            setSortKey(key);
            setSortDirection('asc');
        }
    };

    const handleColumnFilterChange = (key: SortKey, value: string) => {
        setColumnFilters(prev => ({ ...prev, [key]: value }));
    };

    const filteredAndSortedCampaigns = useMemo(() => {
        let result = [...campaigns];

        // Show completed filter
        if (!showCompleted) {
            result = result.filter(c => c.status !== 'Completed');
        }

        // My campaigns only filter
        if (showMyCampaignsOnly && user?.id) {
            result = result.filter(c => c.createdBy === user.id);
        }

        // Per-column text filters
        const filterEntries = Object.entries(columnFilters) as [SortKey, string][];
        for (const [key, filterValue] of filterEntries) {
            if (!filterValue.trim()) continue;
            const lowerFilter = filterValue.toLowerCase();
            result = result.filter(c => {
                let cellValue: string;
                if (key === 'proofs') {
                    cellValue = String(c.proofs);
                } else if (key === 'lastModified') {
                    cellValue = formatDate(c.lastModified);
                } else {
                    cellValue = String(c[key] || '');
                }
                return cellValue.toLowerCase().includes(lowerFilter);
            });
        }

        // Sort
        result.sort((a, b) => {
            let comparison = 0;
            if (sortKey === 'proofs') {
                comparison = a.proofs - b.proofs;
            } else if (sortKey === 'lastModified') {
                comparison = new Date(a.lastModified).getTime() - new Date(b.lastModified).getTime();
            } else {
                const aVal = String(a[sortKey] || '').toLowerCase();
                const bVal = String(b[sortKey] || '').toLowerCase();
                comparison = aVal.localeCompare(bVal);
            }
            return sortDirection === 'asc' ? comparison : -comparison;
        });

        return result;
    }, [campaigns, showCompleted, showMyCampaignsOnly, user?.id, columnFilters, sortKey, sortDirection]);

    // Clear selection when campaigns list changes (e.g., after deletion)
    useEffect(() => {
        setSelectedCampaigns(prev => {
            const currentNames = new Set(filteredAndSortedCampaigns.map(c => c.name));
            const newSelection = new Set<string>();
            prev.forEach(name => {
                if (currentNames.has(name)) {
                    newSelection.add(name);
                }
            });
            return newSelection;
        });
    }, [filteredAndSortedCampaigns]);

    const getStatusSelectClasses = (status: string) => {
        let baseClasses = 'w-full text-center px-2.5 py-0.5 text-xs font-semibold rounded-full border border-transparent focus:outline-none focus:ring-2 focus:ring-oliver-azure appearance-none cursor-pointer';
        let colorClasses = '';
        switch (status) {
            case 'In Progress':
                colorClasses = 'bg-oliver-gold text-oliver-black';
                break;
            case 'Completed':
                colorClasses = 'bg-oliver-green text-white';
                break;
            default:
                colorClasses = 'bg-oliver-grey text-oliver-black';
        }
        return `${baseClasses} ${colorClasses}`;
    };

    const handleSelectAll = () => {
        if (selectedCampaigns.size === filteredAndSortedCampaigns.length) {
            setSelectedCampaigns(new Set());
        } else {
            setSelectedCampaigns(new Set(filteredAndSortedCampaigns.map(c => c.name)));
        }
    };

    const handleSelectCampaign = (campaignName: string, e: React.MouseEvent) => {
        e.stopPropagation();
        setSelectedCampaigns(prev => {
            const newSet = new Set(prev);
            if (newSet.has(campaignName)) {
                newSet.delete(campaignName);
            } else {
                newSet.add(campaignName);
            }
            return newSet;
        });
    };

    const handleSingleDelete = (campaign: typeof initialCampaigns[0], e: React.MouseEvent) => {
        e.stopPropagation();
        setCampaignToDelete(campaign);
    };

    const handleConfirmSingleDelete = async () => {
        if (campaignToDelete) {
            setIsDeleting(true);
            await onDeleteCampaign(campaignToDelete);
            setCampaignToDelete(null);
            setIsDeleting(false);
        }
    };

    const handleConfirmBulkDelete = async () => {
        setIsDeleting(true);
        const campaignsToDelete = filteredAndSortedCampaigns.filter(c => selectedCampaigns.has(c.name));
        for (const campaign of campaignsToDelete) {
            await onDeleteCampaign(campaign);
        }
        setSelectedCampaigns(new Set());
        setShowBulkDeleteModal(false);
        setIsDeleting(false);
    };

    const isAllSelected = filteredAndSortedCampaigns.length > 0 && selectedCampaigns.size === filteredAndSortedCampaigns.length;
    const isIndeterminate = selectedCampaigns.size > 0 && selectedCampaigns.size < filteredAndSortedCampaigns.length;

    return (
        <div className="p-4 sm:p-6 lg:p-8 h-full bg-white">
            <CampaignDeleteConfirmationModal
                isOpen={!!campaignToDelete}
                onClose={() => setCampaignToDelete(null)}
                onConfirm={handleConfirmSingleDelete}
                campaignName={campaignToDelete?.name || ''}
                proofCount={campaignToDelete?.proofs || 0}
                isBulk={false}
                selectedCount={1}
            />

            <CampaignDeleteConfirmationModal
                isOpen={showBulkDeleteModal}
                onClose={() => setShowBulkDeleteModal(false)}
                onConfirm={handleConfirmBulkDelete}
                campaignName=""
                proofCount={0}
                isBulk={true}
                selectedCount={selectedCampaigns.size}
            />

            <header className="mb-8">
                <div className="flex flex-col md:flex-row justify-between items-start md:items-center gap-4">
                    <div>
                        <h1 className="text-3xl lg:text-4xl font-semibold text-oliver-black">Campaigns</h1>
                        <p className="text-base lg:text-lg text-oliver-black mt-1">Manage your campaigns and proof collections.</p>
                    </div>
                     <div className="flex items-center gap-4">
                        <div className="flex items-center gap-2">
                            <label htmlFor="show-completed" className="text-sm font-medium text-oliver-black whitespace-nowrap">Show Completed</label>
                            <ToggleSwitch enabled={showCompleted} onChange={setShowCompleted} />
                        </div>
                        <div className="flex items-center gap-2">
                            <label htmlFor="my-campaigns" className="text-sm font-medium text-oliver-black whitespace-nowrap">My Campaigns Only</label>
                            <ToggleSwitch enabled={showMyCampaignsOnly} onChange={setShowMyCampaignsOnly} />
                        </div>
                        {(isSuperAdmin || isOversightAdmin) && (
                            <button
                                onClick={handleExportCsv}
                                disabled={isExportingCsv}
                                className="flex items-center gap-2 bg-white text-oliver-azure font-semibold py-2.5 px-6 rounded-full border border-oliver-azure hover:bg-oliver-grey transition-colors duration-300 disabled:opacity-50 disabled:cursor-not-allowed"
                            >
                                {isExportingCsv ? (
                                    <SpinnerIcon className="h-5 w-5 animate-spin" />
                                ) : (
                                    <ExportIcon className="h-5 w-5" />
                                )}
                                Export CSV
                            </button>
                        )}
                        {!readOnly && (
                            <button
                                onClick={onOpenModal}
                                className="flex items-center gap-2 bg-oliver-azure text-white font-semibold py-2.5 px-6 rounded-full hover:bg-oliver-azure/90 transition-colors duration-300"
                            >
                                <PlusIcon className="h-5 w-5" />
                                Create New Campaign
                            </button>
                        )}
                    </div>
                </div>
            </header>

            <section>
                {/* Bulk Actions Bar */}
                {!readOnly && selectedCampaigns.size > 0 && (
                    <div className="mb-4 bg-oliver-grey border border-oliver-azure rounded-[10px] p-3 flex items-center justify-between">
                        <div className="flex items-center gap-4">
                            <span className="text-sm font-medium text-oliver-azure">
                                {selectedCampaigns.size} campaign{selectedCampaigns.size !== 1 ? 's' : ''} selected
                            </span>
                            <button
                                onClick={() => setSelectedCampaigns(new Set())}
                                className="text-sm text-oliver-azure hover:text-oliver-black underline"
                            >
                                Clear selection
                            </button>
                        </div>
                        <button
                            onClick={() => setShowBulkDeleteModal(true)}
                            disabled={isDeleting}
                            className="flex items-center gap-2 bg-error text-white font-semibold py-1.5 px-4 rounded-full hover:bg-error/90 transition-colors duration-300 disabled:opacity-50 disabled:cursor-not-allowed"
                        >
                            <TrashIcon className="h-4 w-4" />
                            Delete Selected
                        </button>
                    </div>
                )}

                <div className="bg-white rounded-[10px] shadow-md overflow-hidden border border-grey-300">
                    <div className="overflow-x-auto">
                        <table className="min-w-full">
                            <thead className="bg-oliver-sky">
                                <tr>
                                    {!readOnly && (
                                    <th scope="col" className="px-4 py-3 text-left">
                                        <input
                                            type="checkbox"
                                            checked={isAllSelected}
                                            ref={(el) => {
                                                if (el) el.indeterminate = isIndeterminate;
                                            }}
                                            onChange={handleSelectAll}
                                            className="h-4 w-4 text-oliver-azure border-grey-300 rounded focus:ring-oliver-azure cursor-pointer"
                                            aria-label="Select all campaigns"
                                        />
                                    </th>
                                    )}
                                    {([
                                        ['name', 'Campaign Name'],
                                        ['proofs', 'Proofs'],
                                        ['status', 'Status'],
                                        ['agencyLead', 'Created By'],
                                        ['agency', 'Owning Agency'],
                                        ['brandGuidelines', 'Brand'],
                                        ['lastModified', 'Last Modified'],
                                    ] as [SortKey, string][]).map(([key, label]) => (
                                        <th
                                            key={key}
                                            scope="col"
                                            className="px-6 py-3 text-left text-xs font-bold text-oliver-black uppercase tracking-wider cursor-pointer select-none hover:text-oliver-azure"
                                            onClick={() => handleSort(key)}
                                        >
                                            <span className="inline-flex items-center gap-1">
                                                {label}
                                                <span className={`text-[10px] leading-none ${sortKey === key ? 'text-oliver-azure' : 'text-oliver-black/60'}`}>
                                                    {sortKey === key ? (sortDirection === 'asc' ? '\u25B2' : '\u25BC') : '\u25B4\u25BE'}
                                                </span>
                                            </span>
                                        </th>
                                    ))}
                                    {!readOnly && <th scope="col" className="relative px-4 py-3"><span className="sr-only">Actions</span></th>}
                                </tr>
                                <tr className="bg-oliver-grey">
                                    {!readOnly && <td className="px-4 py-1"></td>}
                                    {(['name', 'proofs', 'status', 'agencyLead', 'agency', 'brandGuidelines', 'lastModified'] as SortKey[]).map((key) => (
                                        <td key={key} className="px-6 py-1">
                                            <input
                                                type="text"
                                                value={columnFilters[key]}
                                                onChange={(e) => handleColumnFilterChange(key, e.target.value)}
                                                onClick={(e) => e.stopPropagation()}
                                                placeholder="Filter..."
                                                className="w-full text-xs py-1 px-2 border border-grey-300 rounded bg-white focus:outline-none focus:border-oliver-azure focus:ring-1 focus:ring-oliver-azure"
                                            />
                                        </td>
                                    ))}
                                    {!readOnly && <td className="px-4 py-1"></td>}
                                </tr>
                            </thead>
                            <tbody className="divide-y divide-grey-300">
                                {filteredAndSortedCampaigns.map((campaign, index) => {
                                    const isSelected = selectedCampaigns.has(campaign.name);
                                    return (
                                        <tr
                                            key={campaign.name}
                                            className={`hover:bg-oliver-grey cursor-pointer ${isSelected ? 'bg-oliver-grey' : index % 2 === 0 ? 'bg-white' : 'bg-oliver-grey'}`}
                                            onClick={() => onSelectCampaign(campaign.name)}
                                        >
                                            {!readOnly && (
                                            <td className="px-4 py-4 whitespace-nowrap">
                                                <input
                                                    type="checkbox"
                                                    checked={isSelected}
                                                    onChange={() => {}} // Handled by onClick
                                                    onClick={(e) => handleSelectCampaign(campaign.name, e)}
                                                    className="h-4 w-4 text-oliver-azure border-grey-300 rounded focus:ring-oliver-azure cursor-pointer"
                                                    aria-label={`Select ${campaign.name}`}
                                                />
                                            </td>
                                            )}
                                            <td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-oliver-black">{campaign.name}</td>
                                            <td className="px-6 py-4 whitespace-nowrap text-sm text-oliver-black">{campaign.proofs}</td>
                                            <td className="px-6 py-4 whitespace-nowrap text-sm w-40">
                                                <div className="relative">
                                                    <select
                                                        value={campaign.status}
                                                        onChange={(e) => onCampaignStatusChange(campaign.name, e.target.value as 'In Progress' | 'Completed')}
                                                        onClick={(e) => e.stopPropagation()}
                                                        className={getStatusSelectClasses(campaign.status)}
                                                        aria-label={`Change status for ${campaign.name}`}
                                                        disabled={readOnly}
                                                    >
                                                        <option value="In Progress">In Progress</option>
                                                        <option value="Completed">Completed</option>
                                                    </select>
                                                    <ChevronDownIcon className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2 h-full w-4 text-oliver-black" />
                                                </div>
                                            </td>
                                            <td className="px-6 py-4 whitespace-nowrap text-sm text-oliver-black">{campaign.agencyLead}</td>
                                            <td className="px-6 py-4 whitespace-nowrap text-sm text-oliver-black">{campaign.agency}</td>
                                            <td className="px-6 py-4 whitespace-nowrap text-sm text-oliver-black">{campaign.brandGuidelines}</td>
                                            <td className="px-6 py-4 whitespace-nowrap text-sm text-oliver-black">{formatDate(campaign.lastModified)}</td>
                                            {!readOnly && (
                                            <td className="px-4 py-4 whitespace-nowrap text-sm text-right">
                                                <button
                                                    onClick={(e) => handleSingleDelete(campaign, e)}
                                                    disabled={isDeleting}
                                                    className="p-2 text-oliver-black/60 rounded-full hover:bg-error-light hover:text-error transition-colors disabled:opacity-50"
                                                    title={`Delete ${campaign.name}`}
                                                    aria-label={`Delete ${campaign.name}`}
                                                >
                                                    <TrashIcon className="h-5 w-5" />
                                                </button>
                                            </td>
                                            )}
                                        </tr>
                                    );
                                })}
                            </tbody>
                        </table>
                    </div>
                </div>
            </section>
        </div>
    );
};

const UploadProofModal: React.FC<{
    isOpen: boolean;
    onClose: () => void;
    dropdownOptions: DropdownOptions;
    onSubmit: (file: File, proofName: string, channel: string, subChannel: string, proofType?: string) => void;
    isLoading: boolean;
    existingProofNames: string[];
}> = ({ isOpen, onClose, dropdownOptions, onSubmit, isLoading, existingProofNames }) => {
    const [file, setFile] = useState<File | null>(null);
    const [proofName, setProofName] = useState('');
    const [channel, setChannel] = useState('');
    const [subChannel, setSubChannel] = useState('');
    const [proofType, setProofType] = useState('');
    const fileInputRef = useRef<HTMLInputElement>(null);

    const availableChannels = Object.keys(dropdownOptions.channels);
    const availableSubChannels = channel ? Object.keys(dropdownOptions.channels[channel] || {}) : [];
    const availableProofTypes = (channel && subChannel) ? (dropdownOptions.channels[channel][subChannel] || []) : [];
    const showProofType = availableProofTypes.length > 0;

    // Debug logging for proof types
    useEffect(() => {
        if (channel && subChannel) {
            console.log('[DEBUG Frontend] Channel:', channel);
            console.log('[DEBUG Frontend] SubChannel:', subChannel);
            console.log('[DEBUG Frontend] dropdownOptions.channels[channel]:', dropdownOptions.channels[channel]);
            console.log('[DEBUG Frontend] dropdownOptions.channels[channel][subChannel]:', dropdownOptions.channels[channel]?.[subChannel]);
            console.log('[DEBUG Frontend] availableProofTypes:', availableProofTypes);
        }
    }, [channel, subChannel, dropdownOptions, availableProofTypes]);

    useEffect(() => {
        if (isOpen) {
            setFile(null);
            setProofName('');
            setChannel('');
            setSubChannel('');
            setProofType('');
            if (fileInputRef.current) {
                fileInputRef.current.value = '';
            }
        }
    }, [isOpen]);

    // Reset dependents when parent changes
    useEffect(() => {
        setSubChannel('');
        setProofType('');
    }, [channel]);

    useEffect(() => {
        if (!showProofType) {
            setProofType('');
        } else {
             setProofType('');
        }
    }, [subChannel, showProofType]);

    const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
        const selectedFile = event.target.files?.[0];
        if (selectedFile) {
            setFile(selectedFile);
        }
    };
    
    const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {
        e.preventDefault();
        e.stopPropagation();
        if (!isLoading && e.dataTransfer.files && e.dataTransfer.files.length > 0) {
            setFile(e.dataTransfer.files[0]);
            e.dataTransfer.clearData();
        }
    };
    
    const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {
        e.preventDefault();
        e.stopPropagation();
    };

    const handleSubmit = (e: React.FormEvent) => {
        e.preventDefault();
        if (file && proofName && channel && subChannel) {
             if (showProofType && !proofType) return;
            onSubmit(file, proofName, channel, subChannel, showProofType ? proofType : undefined);
        }
    };

    const isSubmitDisabled = !proofName || !file || !channel || !subChannel || (showProofType && !proofType) || isLoading;
    const isNewVersion = existingProofNames.includes(proofName.trim()) && proofName.trim() !== '';

    if (!isOpen) return null;

    return (
        <div className="fixed inset-0 z-50 overflow-y-auto" aria-labelledby="modal-title" role="dialog" aria-modal="true">
             <div className="flex min-h-screen items-end justify-center px-4 pt-4 pb-20 text-center sm:block sm:p-0">
                <div
                    className="fixed inset-0 bg-slate-900/75 backdrop-blur-sm transition-opacity"
                    aria-hidden="true"
                    onClick={onClose}
                ></div>
                <span className="hidden sm:inline-block sm:h-screen sm:align-middle" aria-hidden="true">&#8203;</span>

                <div className="relative inline-block transform overflow-hidden rounded-[10px] bg-white text-left align-bottom shadow-2xl transition-all sm:my-8 sm:w-full sm:max-w-2xl sm:align-middle border-2 border-oliver-azure">
                    {/* Header */}
                    <div className="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4 border-b border-grey-300 flex justify-between items-start">
                        <div>
                             <h3 className="text-2xl font-bold text-oliver-black" id="modal-title">Upload New Proof</h3>
                             <p className="text-sm text-oliver-black mt-1">Drag and drop your proof below to start AI analysis.</p>
                        </div>
                        <button
                            onClick={onClose}
                            className="rounded-full p-2 text-oliver-black/60 hover:bg-oliver-grey hover:text-oliver-black transition-colors"
                        >
                            <XIcon className="h-6 w-6" />
                        </button>
                    </div>

                    {/* Content */}
                    <form onSubmit={handleSubmit}>
                        <div className="px-4 pt-5 pb-4 sm:p-8">
                            <div className="space-y-6">
                                {/* Proof Name */}
                                <div>
                                    <label htmlFor="proof-name" className="block text-sm font-bold text-oliver-black mb-2">Proof Name</label>
                                    <div className="relative">
                                        <div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
                                            <DocumentIcon className="h-5 w-5 text-oliver-black/60" />
                                        </div>
                                        <input
                                            id="proof-name"
                                            type="text"
                                            value={proofName}
                                            onChange={(e) => setProofName(e.target.value)}
                                            placeholder="e.g., Q4 Hero Instagram Post"
                                            disabled={isLoading}
                                            className="w-full rounded-[10px] border-2 border-oliver-azure shadow-sm focus:border-oliver-azure focus:ring-oliver-azure p-3 pl-10 bg-white transition-all text-oliver-black"
                                            required
                                        />
                                    </div>
                                     {isNewVersion && (
                                        <p className="text-xs text-oliver-azure mt-2 p-2 bg-oliver-grey rounded-[10px] flex items-center gap-2">
                                            <span className="w-1.5 h-1.5 rounded-full bg-oliver-azure"></span>
                                            A proof with this name already exists. This will be uploaded as a new version.
                                        </p>
                                    )}
                                </div>

                                {/* Dropdowns Grid */}
                                <div className="grid grid-cols-1 gap-x-6 gap-y-6 sm:grid-cols-2">
                                    <div>
                                        <label htmlFor="proof-channel" className="block text-sm font-bold text-oliver-black mb-2">Channel</label>
                                        <div className="relative">
                                            <div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
                                                <ChannelIcon className="h-5 w-5 text-oliver-black/60" />
                                            </div>
                                            <select
                                                id="proof-channel"
                                                value={channel}
                                                onChange={(e) => setChannel(e.target.value)}
                                                disabled={isLoading}
                                                className="w-full rounded-[10px] border-2 border-oliver-azure shadow-sm focus:border-oliver-azure focus:ring-oliver-azure p-3 pl-10 bg-white transition-all text-oliver-black appearance-none"
                                                required
                                            >
                                                <option value="" disabled>Select Channel</option>
                                                {availableChannels.map(opt => <option key={opt} value={opt}>{opt}</option>)}
                                            </select>
                                            <div className="pointer-events-none absolute inset-y-0 right-0 flex items-center px-3 text-oliver-black/60">
                                                <ChevronDownIcon className="h-4 w-4" />
                                            </div>
                                        </div>
                                    </div>

                                    <div>
                                        <label htmlFor="proof-sub-channel" className="block text-sm font-bold text-oliver-black mb-2">Sub-Channel</label>
                                        <div className="relative">
                                            <div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
                                                <TagIcon className="h-5 w-5 text-oliver-black/60" />
                                            </div>
                                            <select
                                                id="proof-sub-channel"
                                                value={subChannel}
                                                onChange={(e) => setSubChannel(e.target.value)}
                                                disabled={isLoading || !channel}
                                                className="w-full rounded-[10px] border-2 border-oliver-azure shadow-sm focus:border-oliver-azure focus:ring-oliver-azure p-3 pl-10 bg-white transition-all text-oliver-black appearance-none disabled:bg-oliver-grey disabled:text-oliver-black/60"
                                                required
                                            >
                                                <option value="" disabled>Select Sub-Channel</option>
                                                {availableSubChannels.map(opt => <option key={opt} value={opt}>{opt}</option>)}
                                            </select>
                                            <div className="pointer-events-none absolute inset-y-0 right-0 flex items-center px-3 text-oliver-black/60">
                                                <ChevronDownIcon className="h-4 w-4" />
                                            </div>
                                        </div>
                                    </div>

                                    <div className="sm:col-span-2">
                                        <label htmlFor="proof-type" className="block text-sm font-bold text-oliver-black mb-2">Proof Type</label>
                                        <div className="relative">
                                            <select
                                                id="proof-type"
                                                value={proofType}
                                                onChange={(e) => setProofType(e.target.value)}
                                                disabled={isLoading || !subChannel || availableProofTypes.length === 0}
                                                className="w-full rounded-[10px] border-2 border-oliver-azure shadow-sm focus:border-oliver-azure focus:ring-oliver-azure p-3 bg-white transition-all text-oliver-black appearance-none disabled:bg-oliver-grey disabled:text-oliver-black/60"
                                                required={showProofType}
                                            >
                                                <option value="" disabled>
                                                    {!subChannel
                                                        ? "Select a Sub-Channel first"
                                                        : availableProofTypes.length === 0
                                                            ? "No proof types available"
                                                            : "Select Proof Type"
                                                    }
                                                </option>
                                                {availableProofTypes.map(opt => <option key={opt} value={opt}>{opt}</option>)}
                                            </select>
                                            <div className="pointer-events-none absolute inset-y-0 right-0 flex items-center px-3 text-oliver-black/60">
                                                <ChevronDownIcon className="h-4 w-4" />
                                            </div>
                                        </div>
                                    </div>
                                </div>

                                {/* Drag & Drop Zone */}
                                <div>
                                    <label className="block text-sm font-bold text-oliver-black mb-2">Proof File</label>
                                    <div
                                        onDragOver={handleDragOver}
                                        onDrop={handleDrop}
                                        className={`
                                            relative mt-1 flex justify-center px-6 pt-10 pb-10 border-2 border-dashed rounded-[10px] transition-all group cursor-pointer
                                            ${file ? 'border-success bg-success-light' : 'border-grey-300 hover:bg-success-light/30 hover:border-success/50'}
                                        `}
                                    >
                                        <input
                                            id="file-upload"
                                            name="file-upload"
                                            type="file"
                                            className="absolute inset-0 w-full h-full opacity-0 cursor-pointer"
                                            ref={fileInputRef}
                                            onChange={handleFileChange}
                                            disabled={isLoading}
                                            accept="image/png, image/jpeg, image/webp, image/gif, video/mp4, application/pdf"
                                        />
                                        <div className="text-center space-y-2 pointer-events-none">
                                            {!file ? (
                                                <>
                                                    <div className="mx-auto h-16 w-16 bg-oliver-grey text-oliver-black/60 rounded-full flex items-center justify-center group-hover:scale-110 group-hover:text-success group-hover:bg-success-light transition-all duration-300">
                                                        <UploadIcon className="h-8 w-8" />
                                                    </div>
                                                    <div className="text-sm text-oliver-black">
                                                        <span className="font-bold text-success">Click to upload</span> or drag and drop
                                                    </div>
                                                    <p className="text-xs text-oliver-black/60">SVG, PNG, JPG or GIF</p>
                                                </>
                                            ) : (
                                                <>
                                                    <div className="mx-auto h-16 w-16 bg-success-light text-success rounded-full flex items-center justify-center scale-110 shadow-sm">
                                                        <CheckCircleIcon className="h-8 w-8" />
                                                    </div>
                                                    <div className="text-sm font-bold text-oliver-black truncate max-w-xs mx-auto">
                                                        {file.name}
                                                    </div>
                                                    <p className="text-xs text-oliver-black">Ready for analysis</p>
                                                </>
                                            )}
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>

                        {/* Footer */}
                        <div className="bg-oliver-grey px-4 py-4 sm:px-6 border-t border-grey-300 flex flex-col-reverse sm:flex-row sm:justify-end gap-3">
                             <button
                                type="button"
                                onClick={onClose}
                                disabled={isLoading}
                                className="w-full sm:w-auto border-2 border-oliver-azure text-oliver-azure font-semibold py-2.5 px-6 rounded-full hover:bg-oliver-azure hover:text-white transition-colors duration-300 disabled:opacity-50"
                            >
                                Cancel
                            </button>
                            <button
                                type="submit"
                                disabled={isSubmitDisabled}
                                className="w-full sm:w-auto flex items-center justify-center bg-oliver-azure text-white font-bold py-2.5 px-6 rounded-full hover:bg-oliver-azure/90 shadow-lg shadow-oliver-azure/20 transition-all duration-300 disabled:bg-gray-300 disabled:text-oliver-black/60 disabled:shadow-none disabled:cursor-not-allowed"
                            >
                                {isLoading ? (
                                    <>
                                        <SpinnerIcon className="animate-spin -ml-1 mr-2 h-5 w-5 text-white" />
                                        Analysing...
                                    </>
                                ) : 'Start Analysis'}
                            </button>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    );
};

const LoadingCell: React.FC<{ progress: { completed: number; total: number } }> = ({ progress }) => {
    const percent = progress.total > 0 ? Math.round((progress.completed / progress.total) * 100) : 0;

    let statusText = 'Analysing...';
    if (progress.completed < AGENT_NAMES.length) {
        const agentName = AGENT_NAMES[progress.completed];
        statusText = `Analysing: ${agentName}...`;
    } else if (progress.completed === AGENT_NAMES.length) {
        statusText = 'Lead Agent Review...';
    } else {
        statusText = 'Finalizing...';
    }

    return (
        <div className="flex flex-col items-center justify-center h-full px-2 text-center w-full">
            <div className="w-full bg-grey-300 rounded-full h-1.5 mb-1.5">
                <div
                    className="bg-oliver-azure h-1.5 rounded-full"
                    style={{ width: `${percent}%`, transition: 'width 0.3s ease-in-out' }}
                ></div>
            </div>
            <span className="text-xs text-oliver-black truncate w-full">{statusText} ({percent}%)</span>
        </div>
    );
};

const DeleteConfirmationModal: React.FC<{
    isOpen: boolean;
    onClose: () => void;
    onConfirm: () => void;
    proofName: string;
}> = ({ isOpen, onClose, onConfirm, proofName }) => {
    if (!isOpen) return null;

    return (
        <div
            className="fixed inset-0 bg-black bg-opacity-60 flex items-center justify-center z-50 transition-opacity duration-300"
            onClick={onClose}
            aria-modal="true"
            role="dialog"
        >
            <div
                className="bg-white rounded-[10px] shadow-xl p-6 sm:p-8 w-full max-w-md transform transition-all border-2 border-oliver-azure"
                onClick={e => e.stopPropagation()}
            >
                <h3 className="text-xl font-bold text-oliver-black">Confirm Deletion</h3>
                <p className="text-oliver-black my-4">
                    Are you sure you want to permanently delete the proof "{proofName}"? This action cannot be undone.
                </p>
                <div className="mt-6 flex justify-end gap-3">
                    <button
                        type="button"
                        onClick={onClose}
                        className="border-2 border-oliver-azure text-oliver-azure font-semibold py-2 px-6 rounded-full hover:bg-oliver-azure hover:text-white transition-colors"
                    >
                        Cancel
                    </button>
                    <button
                        type="button"
                        onClick={onConfirm}
                        className="bg-error text-white font-semibold py-2 px-6 rounded-full hover:bg-error/90 transition-colors"
                    >
                        Delete Proof
                    </button>
                </div>
            </div>
        </div>
    );
};

const AnalysisErrorModal: React.FC<{
    isOpen: boolean;
    onClose: () => void;
    proofName: string;
    feedback: AgentReview | null;
}> = ({ isOpen, onClose, proofName, feedback }) => {
    if (!isOpen || !feedback) return null;

    const agentEntries: { label: string; review: { ragStatus: string; feedback: string } }[] = [
        { label: 'Risk & Control Agent', review: feedback.legalAgentReview },
        { label: 'Brand Agent', review: feedback.brandAgentReview },
        { label: 'Channel Best Practices Agent', review: feedback.channelBestPracticesAgentReview },
        { label: 'Channel Tech Specs Agent', review: feedback.channelTechSpecsAgentReview },
    ];

    const failedAgents = agentEntries.filter(a => a.review.ragStatus === 'Error');

    return (
        <div
            className="fixed inset-0 bg-black bg-opacity-60 flex items-center justify-center z-50 transition-opacity duration-300"
            onClick={onClose}
            aria-modal="true"
            role="dialog"
        >
            <div
                className="bg-white rounded-[10px] shadow-xl p-6 sm:p-8 w-full max-w-lg max-h-[80vh] overflow-y-auto transform transition-all border-2 border-oliver-azure"
                onClick={e => e.stopPropagation()}
            >
                <div className="flex items-start gap-3 mb-4">
                    <div className="flex-shrink-0 p-2 bg-red-100 rounded-full">
                        <ExclamationTriangleIcon className="h-6 w-6 text-red-600" />
                    </div>
                    <div>
                        <h3 className="text-xl font-bold text-oliver-black">Analysis Error</h3>
                        <p className="text-sm text-oliver-black/60 mt-0.5">{proofName}</p>
                    </div>
                </div>

                {feedback.leadAgentSummary && (
                    <div className="bg-red-50 border border-red-200 rounded-lg p-4 mb-4">
                        <h4 className="text-sm font-semibold text-red-800 mb-1">Summary</h4>
                        <p className="text-sm text-red-700">{feedback.leadAgentSummary}</p>
                    </div>
                )}

                {failedAgents.length > 0 && (
                    <div className="space-y-3">
                        <h4 className="text-sm font-semibold text-oliver-black/60">Agent Details</h4>
                        {failedAgents.map(agent => (
                            <div key={agent.label} className="bg-oliver-grey rounded-lg p-3">
                                <p className="text-sm font-medium text-oliver-black">{agent.label}</p>
                                <p className="text-sm text-oliver-black/60 mt-1">{agent.review.feedback}</p>
                            </div>
                        ))}
                    </div>
                )}

                <div className="mt-6 flex justify-end">
                    <button
                        type="button"
                        onClick={onClose}
                        className="border-2 border-oliver-azure text-oliver-azure font-semibold py-2 px-6 rounded-full hover:bg-oliver-azure hover:text-white transition-colors"
                    >
                        Close
                    </button>
                </div>
            </div>
        </div>
    );
};

const CampaignDeleteConfirmationModal: React.FC<{
    isOpen: boolean;
    onClose: () => void;
    onConfirm: () => void;
    campaignName: string;
    proofCount: number;
    isBulk: boolean;
    selectedCount: number;
}> = ({ isOpen, onClose, onConfirm, campaignName, proofCount, isBulk, selectedCount }) => {
    if (!isOpen) return null;

    return (
        <div
            className="fixed inset-0 bg-black bg-opacity-60 flex items-center justify-center z-50 transition-opacity duration-300"
            onClick={onClose}
            aria-modal="true"
            role="dialog"
        >
            <div
                className="bg-white rounded-[10px] shadow-xl p-6 sm:p-8 w-full max-w-md transform transition-all border-2 border-oliver-azure"
                onClick={e => e.stopPropagation()}
            >
                <h3 className="text-xl font-bold text-oliver-black">Confirm Deletion</h3>
                <p className="text-oliver-black my-4">
                    {isBulk ? (
                        <>Are you sure you want to permanently delete <strong>{selectedCount} selected campaign{selectedCount !== 1 ? 's' : ''}</strong>? All associated proofs will also be deleted. This action cannot be undone.</>
                    ) : (
                        <>Are you sure you want to permanently delete the campaign "<strong>{campaignName}</strong>"? {proofCount > 0 && <>This will also delete <strong>{proofCount} proof{proofCount !== 1 ? 's' : ''}</strong>.</>} This action cannot be undone.</>
                    )}
                </p>
                <div className="mt-6 flex justify-end gap-3">
                    <button
                        type="button"
                        onClick={onClose}
                        className="border-2 border-oliver-azure text-oliver-azure font-semibold py-2 px-6 rounded-full hover:bg-oliver-azure hover:text-white transition-colors"
                    >
                        Cancel
                    </button>
                    <button
                        type="button"
                        onClick={onConfirm}
                        className="bg-error text-white font-semibold py-2 px-6 rounded-full hover:bg-error/90 transition-colors"
                    >
                        {isBulk ? `Delete ${selectedCount} Campaign${selectedCount !== 1 ? 's' : ''}` : 'Delete Campaign'}
                    </button>
                </div>
            </div>
        </div>
    );
};

const CampaignDetail: React.FC<{
    campaignName: string;
    onBack: () => void;
    onSelectProof: (proof: any) => void;
    campaignProofs: { [key: string]: any[] };
    onProofUpload: (file: File, proofName: string, channel: string, subChannel: string, proofType?: string) => void;
    dropdownOptions: DropdownOptions;
    onRetryAnalysis: (campaignName: string, tempId: string) => void;
    onDeleteProof: (campaignName: string, proofName: string) => void;
    readOnly?: boolean;
}> = ({ campaignName, onBack, onSelectProof, campaignProofs, onProofUpload, dropdownOptions, onRetryAnalysis, onDeleteProof, readOnly = false }) => {
    const [isUploadFormVisible, setIsUploadFormVisible] = useState(false);
    const [proofToDelete, setProofToDelete] = useState<any | null>(null);
    const [proofForUpload, setProofForUpload] = useState<any | null>(null);
    const [isExporting, setIsExporting] = useState(false);
    const [errorProof, setErrorProof] = useState<any | null>(null);
    const fileInputRef = useRef<HTMLInputElement>(null);

    const proofs = campaignProofs[campaignName] || [];
    const isUploading = proofs.some(proof => proof.status === 'analyzing');
    const existingProofNames = proofs
        .filter(proof => proof.status === 'completed')
        .map(proof => proof.proofName);
    
    const handleConfirmDelete = () => {
        if (proofToDelete) {
            onDeleteProof(campaignName, proofToDelete.proofName);
            setProofToDelete(null);
        }
    };

    const handleNewVersionClick = (e: React.MouseEvent, proof: any) => {
        e.stopPropagation();
        setProofForUpload(proof);
        fileInputRef.current?.click();
    };

    const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
        const file = event.target.files?.[0];
        if (file && proofForUpload) {
            onProofUpload(
                file,
                proofForUpload.proofName,
                proofForUpload.channel,
                proofForUpload.subChannel,
                proofForUpload.proofType
            );
        }
        setProofForUpload(null);
        if (event.target) {
            event.target.value = '';
        }
    };
    
    const handleExportPDF = async (proofsToExport: any[], fileName: string) => {
        setIsExporting(true);

        const reportRootEl = document.createElement('div');
        reportRootEl.style.position = 'absolute';
        reportRootEl.style.left = '-9999px';
        reportRootEl.style.top = '0px';
        reportRootEl.style.zIndex = '-1';
        document.body.appendChild(reportRootEl);

        const reactRoot = ReactDOM.createRoot(reportRootEl);

        try {
            const proofsWithLatestVersion = proofsToExport.map(p => ({
                ...p,
                versions: [p.versions[0]], // Only render the latest version
            }));

            reactRoot.render(<PDFReport campaignName={campaignName} proofs={proofsWithLatestVersion} />);

            await new Promise(resolve => setTimeout(resolve, 1500)); // Wait for render and images

            const reportContent = reportRootEl.children[0] as HTMLElement;
            if (!reportContent) throw new Error("PDF report element not found");

            const safeTitle = fileName.replace(/[^a-zA-Z0-9 _-]/g, '_');
            const printWindow = window.open('', '_blank');
            if (!printWindow) throw new Error("Popup blocked. Please allow popups for this site and try again.");

            printWindow.document.write(`<!DOCTYPE html>
<html>
<head>
  <title>${safeTitle}</title>
  <meta charset="UTF-8">
  <style>
    @page { size: A4; margin: 0; }
    * { -webkit-print-color-adjust: exact !important; print-color-adjust: exact !important; box-sizing: border-box; }
    body { margin: 0; padding: 0; font-family: Arial, sans-serif; }
    ul { list-style-position: outside; padding-left: 20px; margin: 4px 0; }
    li { line-height: 1.5; margin-bottom: 6px; }
  </style>
</head>
<body>${reportContent.outerHTML}</body>
</html>`);
            printWindow.document.close();

            await new Promise<void>(resolve => {
                const timeout = setTimeout(resolve, 3000);
                printWindow.onload = () => { clearTimeout(timeout); resolve(); };
            });

            printWindow.print();
            setTimeout(() => { try { printWindow.close(); } catch (_) {} }, 1000);

        } catch (error) {
            console.error("Failed to generate PDF:", error);
            alert("Sorry, there was an error creating the PDF. Please try again.");
        } finally {
            reactRoot.unmount();
            document.body.removeChild(reportRootEl);
            setIsExporting(false);
        }
    };

    return (
        <div className="p-4 sm:p-6 lg:p-8 h-full bg-white">
            <DeleteConfirmationModal
                isOpen={!!proofToDelete}
                onClose={() => setProofToDelete(null)}
                onConfirm={handleConfirmDelete}
                proofName={proofToDelete?.proofName || ''}
            />

            <input
                type="file"
                ref={fileInputRef}
                onChange={handleFileChange}
                className="hidden"
                accept="image/png, image/jpeg, image/webp, image/gif, video/mp4, application/pdf"
                disabled={isUploading}
            />

            <header className="mb-8">
                <div className="flex items-center gap-4">
                    <button
                        onClick={onBack}
                        className="p-2 text-oliver-black/60 rounded-full hover:bg-grey-300 hover:text-oliver-black transition-colors duration-200"
                        title="Back to campaigns"
                        aria-label="Back to campaigns list"
                    >
                        <ArrowLeftIcon className="h-6 w-6" />
                    </button>
                    <div>
                        <h1 className="text-3xl lg:text-4xl font-semibold text-oliver-black">{campaignName}</h1>
                        <p className="text-base lg:text-lg text-oliver-black mt-1">Proof overview and compliance status.</p>
                    </div>
                </div>
            </header>
            
            <UploadProofModal
                isOpen={isUploadFormVisible}
                onClose={() => setIsUploadFormVisible(false)}
                dropdownOptions={dropdownOptions}
                onSubmit={(file, proofName, channel, subChannel, proofType) => {
                    onProofUpload(file, proofName, channel, subChannel, proofType);
                    setIsUploadFormVisible(false);
                }}
                isLoading={isUploading}
                existingProofNames={existingProofNames}
            />

            <AnalysisErrorModal
                isOpen={!!errorProof}
                onClose={() => setErrorProof(null)}
                proofName={errorProof?.proofName || ''}
                feedback={errorProof?.versions?.[0]?.feedback || null}
            />

            <section>
                <div className="mb-6 flex justify-end gap-3">
                    <button
                        onClick={() => handleExportPDF(proofs.filter(p => p.status === 'completed'), `${campaignName} - Campaign Report`)}
                        disabled={isExporting || proofs.filter(p => p.status === 'completed').length === 0}
                        className="flex items-center gap-2 bg-white text-oliver-azure font-semibold py-2 px-4 rounded-full border-2 border-oliver-azure hover:bg-oliver-azure hover:text-white transition-colors duration-300 disabled:bg-gray-300 disabled:text-oliver-black/60 disabled:border-grey-300 disabled:cursor-wait"
                    >
                        {isExporting ? <SpinnerIcon className="h-5 w-5 custom-spinner" /> : <ExportIcon className="h-5 w-5" />}
                        {isExporting ? 'Exporting...' : 'Export Campaign Report'}
                    </button>
                    {!readOnly && (
                        <button
                            onClick={() => setIsUploadFormVisible(true)}
                            className="flex items-center gap-2 bg-oliver-azure text-white font-semibold py-2 px-4 rounded-full hover:bg-oliver-azure/90 transition-colors duration-300"
                        >
                            <PlusIcon className="h-5 w-5" />
                            Upload New Proof
                        </button>
                    )}
                </div>
                
                <div className="bg-white rounded-[10px] shadow-md overflow-hidden border border-grey-300">
                    <div className="overflow-x-auto">
                        <table className="min-w-full divide-y divide-grey-300">
                            <thead className="bg-oliver-sky">
                                <tr>
                                    <th scope="col" className="px-6 py-3 text-left text-xs font-bold text-oliver-black uppercase tracking-wider">Proof Name</th>
                                    <th scope="col" className="px-6 py-3 text-left text-xs font-bold text-oliver-black uppercase tracking-wider">Workfront #</th>
                                    <th scope="col" className="px-6 py-3 text-left text-xs font-bold text-oliver-black uppercase tracking-wider">Channel</th>
                                    <th scope="col" className="px-6 py-3 text-left text-xs font-bold text-oliver-black uppercase tracking-wider">Sub-Channel</th>
                                    <th scope="col" className="px-6 py-3 text-left text-xs font-bold text-oliver-black uppercase tracking-wider">Proof Type</th>
                                    <th scope="col" className="px-6 py-3 text-left text-xs font-bold text-oliver-black uppercase tracking-wider">Overall Status</th>
                                    <th scope="col" className="relative px-6 py-3"><span className="sr-only">Actions</span></th>
                                </tr>
                            </thead>
                            <tbody className="bg-white divide-y divide-grey-300">
                                {proofs.map((proof, index) => {
                                    if (proof.status === 'analyzing') {
                                        return (
                                            <tr key={proof.tempId} className="bg-oliver-grey opacity-80">
                                                <td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-oliver-black">{proof.proofName}</td>
                                                <td className="px-6 py-4 whitespace-nowrap text-sm text-oliver-black/60 italic">Pending</td>
                                                <td className="px-6 py-4 whitespace-nowrap text-sm text-oliver-black">{proof.channel}</td>
                                                <td className="px-6 py-4 whitespace-nowrap text-sm text-oliver-black">{proof.subChannel}</td>
                                                <td className="px-6 py-4 whitespace-nowrap text-sm text-oliver-black">{proof.proofType || 'N/A'}</td>
                                                <td className="px-6 py-4" colSpan={2}>
                                                    {proof.analysisProgress ?
                                                        <LoadingCell progress={proof.analysisProgress} /> :
                                                        <div className="flex justify-center items-center h-full">
                                                            <SpinnerIcon className="h-5 w-5 text-oliver-azure custom-spinner" />
                                                            <span className="ml-2 text-sm text-oliver-black">Preparing...</span>
                                                        </div>
                                                    }
                                                </td>
                                            </tr>
                                        );
                                    }

                                    if (proof.status === 'error') {
                                        return (
                                            <tr key={proof.tempId} className="bg-error-light">
                                                <td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-oliver-black">{proof.proofName}</td>
                                                <td className="px-6 py-4 whitespace-nowrap text-sm text-oliver-black/60 italic">Failed</td>
                                                <td className="px-6 py-4 whitespace-nowrap text-sm text-oliver-black">{proof.channel}</td>
                                                <td className="px-6 py-4 whitespace-nowrap text-sm text-oliver-black">{proof.subChannel}</td>
                                                <td className="px-6 py-4 whitespace-nowrap text-sm text-oliver-black">{proof.proofType || 'N/A'}</td>
                                                <td className="px-6 py-4 whitespace-nowrap text-sm text-error font-semibold" colSpan={2}>
                                                    <div className="flex items-center justify-between">
                                                        <button
                                                            onClick={() => setErrorProof(proof)}
                                                            className="text-error hover:text-red-800 underline underline-offset-2 cursor-pointer transition-colors"
                                                        >
                                                            Analysis failed.
                                                        </button>
                                                        <button
                                                            onClick={() => onRetryAnalysis(campaignName, proof.tempId || proof._id)}
                                                            className="flex items-center gap-1.5 text-xs font-semibold text-oliver-azure hover:text-oliver-black whitespace-nowrap px-3 py-1.5 rounded-full bg-oliver-azure/10 hover:bg-oliver-azure/20 transition-colors"
                                                        >
                                                            <ArrowPathIcon className="h-4 w-4" />
                                                            Retry
                                                        </button>
                                                    </div>
                                                </td>
                                            </tr>
                                        );
                                    }

                                    const isVersioned = proof.versions && proof.versions.length > 0;
                                    const latestVersion = isVersioned ? proof.versions[0] : null;
                                    const isClickable = isVersioned;

                                    if (!latestVersion) return null; // Should not happen for completed proofs

                                    return (
                                        <tr
                                            key={latestVersion.workfrontId || index}
                                            className={`${index % 2 === 0 ? 'bg-white' : 'bg-oliver-grey'} ${isClickable ? "hover:bg-oliver-grey cursor-pointer" : ""}`}
                                            onClick={() => isClickable && onSelectProof(proof)}
                                        >
                                            <td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-oliver-black">
                                                {proof.proofName}
                                                {isVersioned && (
                                                    <span className="ml-2 bg-grey-300 text-oliver-black text-xs font-bold px-2 py-0.5 rounded-full">
                                                        V{latestVersion.version}
                                                    </span>
                                                )}
                                            </td>
                                            <td className="px-6 py-4 whitespace-nowrap text-sm text-oliver-black">{latestVersion.workfrontId}</td>
                                            <td className="px-6 py-4 whitespace-nowrap text-sm text-oliver-black">{proof.channel}</td>
                                            <td className="px-6 py-4 whitespace-nowrap text-sm text-oliver-black">{proof.subChannel}</td>
                                            <td className="px-6 py-4 whitespace-nowrap text-sm text-oliver-black">{proof.proofType || 'N/A'}</td>
                                            <td className="px-6 py-4 whitespace-nowrap text-sm">
                                                <OverallStatusBadge status={latestVersion.overallStatus} />
                                            </td>
                                            <td className="px-6 py-4 whitespace-nowrap text-sm text-right">
                                                <div className="flex items-center justify-end gap-1">
                                                    {!readOnly && (
                                                        <button
                                                            onClick={(e) => handleNewVersionClick(e, proof)}
                                                            className="p-2 text-oliver-black/60 rounded-full hover:bg-oliver-grey hover:text-oliver-azure transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
                                                            title={`Upload new version for ${proof.proofName}`}
                                                            disabled={isUploading || isExporting}
                                                        >
                                                            <UploadIcon className="h-5 w-5" />
                                                        </button>
                                                    )}
                                                    <button
                                                        onClick={(e) => {
                                                            e.stopPropagation();
                                                            handleExportPDF([proof], `${campaignName} - ${proof.proofName} Report`);
                                                        }}
                                                        disabled={isExporting}
                                                        className="p-2 text-oliver-black/60 rounded-full hover:bg-success-light hover:text-success transition-colors disabled:opacity-50 disabled:cursor-wait"
                                                        title={`Export PDF for ${proof.proofName}`}
                                                    >
                                                        <PDFIcon className="h-5 w-5" />
                                                    </button>
                                                    {!readOnly && (
                                                        <button
                                                            onClick={(e) => {
                                                                e.stopPropagation();
                                                                setProofToDelete(proof);
                                                            }}
                                                            disabled={isExporting}
                                                            className="p-2 text-oliver-black/60 rounded-full hover:bg-error-light hover:text-error transition-colors disabled:opacity-50"
                                                            title={`Delete ${proof.proofName}`}
                                                        >
                                                            <TrashIcon className="h-5 w-5" />
                                                        </button>
                                                    )}
                                                </div>
                                            </td>
                                        </tr>
                                    );
                                })}
                            </tbody>
                        </table>
                    </div>
                </div>
            </section>
        </div>
    );
};

const ProofDetailView: React.FC<{
    campaignName: string;
    proof: any;
    onBack: () => void;
    onNewVersionUpload: (file: File) => void;
    isUploadingNewVersion: boolean;
    onFlagSubmit: (flagData: Omit<FlaggedItem, 'id' | 'timestamp' | 'submitter' | 'submitAgency'>) => void;
    onResolveSubmit: (resolveData: Omit<ResolvedItem, 'id' | 'timestamp' | 'submitter' | 'submitAgency'>) => void;
    flaggedItems: FlaggedItem[];
    resolvedItems: ResolvedItem[];
    readOnly?: boolean;
}> = ({ campaignName, proof, onBack, onNewVersionUpload, isUploadingNewVersion, onFlagSubmit, onResolveSubmit, flaggedItems, resolvedItems, readOnly = false }) => {
    
    const getInitialVersionIndex = () => {
        if (proof.initialVersion && proof.versions) {
            const index = proof.versions.findIndex((v: any) => v.version === proof.initialVersion);
            return index > -1 ? index : 0;
        }
        return 0; // Default to the latest version (index 0)
    };
    
    const [selectedVersionIndex, setSelectedVersionIndex] = useState(getInitialVersionIndex);
    const [isExporting, setIsExporting] = useState(false);
    const fileInputRef = useRef<HTMLInputElement>(null);

    const handleUploadClick = () => {
        fileInputRef.current?.click();
    };

    const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
        const file = event.target.files?.[0];
        if (file) {
            onNewVersionUpload(file);
        }
    };
    
    useEffect(() => {
        // When proof versions change (e.g., new upload), reset to show the latest version.
        setSelectedVersionIndex(0);
    }, [proof.versions]);

    const versions = proof.versions || [];
    const selectedVersion = versions[selectedVersionIndex];

    // Load PDF pages on-demand for PDF files
    const { pdfPages } = usePdfPages(selectedVersion?.fileStorageKey);

    const handleFlagSubmitWrapper = (agentName: string, comments: string) => {
        onFlagSubmit({
            campaignName,
            proofName: proof.proofName,
            version: selectedVersion.version,
            agentFlagged: agentName,
            comments,
        });
    };
    
    const handleResolveSubmitWrapper = (agentName: string, issueText: string, reason: string) => {
        onResolveSubmit({
            campaignName,
            proofName: proof.proofName,
            version: selectedVersion.version,
            agent: agentName,
            issue: issueText,
            resolution: reason,
        });
    };

    const handleDownload = async () => {
        const fileName = `${proof.proofName}_V${selectedVersion.version}`;
        const storageKey = selectedVersion.fileStorageKey;

        try {
            // Prefer fetching the original file from backend storage
            if (storageKey) {
                const file = await apiService.getFile(storageKey);
                const blobUrl = URL.createObjectURL(file);
                const link = document.createElement('a');
                link.href = blobUrl;
                const ext = storageKey.split('.').pop() || 'png';
                link.download = `${fileName}.${ext}`;
                document.body.appendChild(link);
                link.click();
                document.body.removeChild(link);
                URL.revokeObjectURL(blobUrl);
                return;
            }

            // Fallback to preview URL if no storage key (legacy data)
            const url = selectedVersion.proofPreviewUrl;
            if (url.startsWith('data:')) {
                // Data URL - extract mime type and download directly
                const link = document.createElement('a');
                link.href = url;
                const mimeMatch = url.match(/data:([^;]+)/);
                const ext = mimeMatch ? mimeMatch[1].split('/')[1] : 'png';
                link.download = `${fileName}.${ext}`;
                document.body.appendChild(link);
                link.click();
                document.body.removeChild(link);
            } else {
                // Remote URL - fetch as blob to handle CORS and ensure download
                const response = await fetch(url);
                const blob = await response.blob();
                const blobUrl = URL.createObjectURL(blob);
                const link = document.createElement('a');
                link.href = blobUrl;
                const ext = url.split('.').pop()?.split('?')[0] || 'png';
                link.download = `${fileName}.${ext}`;
                document.body.appendChild(link);
                link.click();
                document.body.removeChild(link);
                URL.revokeObjectURL(blobUrl);
            }
        } catch (error) {
            console.error('Failed to download file:', error);
            alert('Sorry, there was an error downloading the file. Please try again.');
        }
    };

    const handleDownloadReport = async () => {
        setIsExporting(true);

        const reportRootEl = document.createElement('div');
        reportRootEl.style.position = 'absolute';
        reportRootEl.style.left = '-9999px';
        reportRootEl.style.top = '0px';
        reportRootEl.style.zIndex = '-1';
        document.body.appendChild(reportRootEl);

        const reactRoot = ReactDOM.createRoot(reportRootEl);

        try {
            const proofForReport = {
                ...proof,
                versions: [selectedVersion],
            };

            reactRoot.render(<PDFReport campaignName={campaignName} proofs={[proofForReport]} />);

            await new Promise(resolve => setTimeout(resolve, 1500));

            const reportContent = reportRootEl.children[0] as HTMLElement;
            if (!reportContent) throw new Error("PDF report element not found");

            const fileName = `${campaignName} - ${proof.proofName} V${selectedVersion.version} Report`;
            const safeTitle = fileName.replace(/[^a-zA-Z0-9 _-]/g, '_');
            const printWindow = window.open('', '_blank');
            if (!printWindow) throw new Error("Popup blocked. Please allow popups for this site and try again.");

            printWindow.document.write(`<!DOCTYPE html>
<html>
<head>
  <title>${safeTitle}</title>
  <meta charset="UTF-8">
  <style>
    @page { size: A4; margin: 0; }
    * { -webkit-print-color-adjust: exact !important; print-color-adjust: exact !important; box-sizing: border-box; }
    body { margin: 0; padding: 0; font-family: Arial, sans-serif; }
    ul { list-style-position: outside; padding-left: 20px; margin: 4px 0; }
    li { line-height: 1.5; margin-bottom: 6px; }
  </style>
</head>
<body>${reportContent.outerHTML}</body>
</html>`);
            printWindow.document.close();

            await new Promise<void>(resolve => {
                const timeout = setTimeout(resolve, 3000);
                printWindow.onload = () => { clearTimeout(timeout); resolve(); };
            });

            printWindow.print();
            setTimeout(() => { try { printWindow.close(); } catch (_) {} }, 1000);

        } catch (error) {
            console.error("Failed to generate PDF:", error);
            alert("Sorry, there was an error creating the PDF. Please try again.");
        } finally {
            reactRoot.unmount();
            document.body.removeChild(reportRootEl);
            setIsExporting(false);
        }
    };

    if (!selectedVersion) {
        return (
            <div className="p-8">
                <p>Error: This proof has no versions to display.</p>
                <button onClick={onBack}>Go Back</button>
            </div>
        );
    }

    return (
        <div className="p-4 sm:p-6 lg:p-8 bg-white">
            <header className="mb-8">
                <div className="flex items-center gap-4">
                    <button
                        onClick={onBack}
                        className="p-2 text-oliver-black/60 rounded-full hover:bg-grey-300 hover:text-oliver-black transition-colors duration-200"
                        title="Back to campaign details"
                        aria-label="Back to campaign details"
                    >
                        <ArrowLeftIcon className="h-6 w-6" />
                    </button>
                    <div className="min-w-0">
                        <h1 className="text-3xl lg:text-4xl font-semibold text-oliver-black truncate" title={proof.proofName}>{proof.proofName}</h1>
                        <div className="flex items-center gap-2 mt-2 text-sm text-oliver-black/60 font-medium">
                            <span>{proof.channel}</span>
                            <span className="text-grey-300">&bull;</span>
                            <span>{proof.subChannel}</span>
                            {proof.proofType && (
                                <>
                                    <span className="text-grey-300">&bull;</span>
                                    <span>{proof.proofType}</span>
                                </>
                            )}
                        </div>
                    </div>
                </div>
            </header>

             <div className="max-w-screen-2xl mx-auto grid grid-cols-1 lg:grid-cols-3 gap-x-12">
                <div className="lg:col-span-1">
                    <div className="sticky top-8 flex flex-col gap-y-6">
                        <div>
                             <h2 className="text-2xl font-semibold text-oliver-black mb-4">
                                Proof Preview
                            </h2>
                            <ProofPreview
                                previewUrl={selectedVersion.proofPreviewUrl}
                                fileName={`${proof.proofName} - V${selectedVersion.version}`}
                                pdfPages={pdfPages}
                            />
                        </div>

                        <div>
                            <div className="flex flex-wrap items-center justify-between mb-3 gap-2">
                                <h3 className="text-xl font-semibold text-oliver-black flex items-center gap-2">
                                    <HistoryIcon className="h-6 w-6 text-oliver-azure"/>
                                    Version History
                                </h3>
                                <div className="flex flex-wrap items-center gap-2">
                                    <button
                                        onClick={handleDownload}
                                        className="flex items-center gap-2 text-sm bg-oliver-azure text-white font-semibold py-1.5 px-3 rounded-full border border-transparent hover:bg-oliver-azure/90 hover:shadow-sm active:scale-95 active:bg-oliver-azure/80 transition-all duration-150 shrink-0 whitespace-nowrap"
                                        title={`Download Version ${selectedVersion.version}`}
                                    >
                                        <DownloadIcon className="h-4 w-4" />
                                        Download Proof
                                    </button>
                                    <button
                                        onClick={handleDownloadReport}
                                        disabled={isExporting}
                                        className="flex items-center gap-2 text-sm bg-white text-oliver-azure font-semibold py-1.5 px-3 rounded-full border-2 border-oliver-azure hover:bg-oliver-azure hover:text-white hover:shadow-sm active:scale-95 transition-all duration-150 disabled:bg-gray-300 disabled:text-oliver-black/60 disabled:border-grey-300 disabled:cursor-wait shrink-0 whitespace-nowrap"
                                        title={`Download Report for Version ${selectedVersion.version}`}
                                    >
                                        {isExporting ? (
                                            <>
                                                <SpinnerIcon className="h-4 w-4 custom-spinner" />
                                                Exporting...
                                            </>
                                        ) : (
                                            <>
                                                <DocumentIcon className="h-4 w-4" />
                                                Download Report
                                            </>
                                        )}
                                    </button>
                                    {!readOnly && (
                                        <button
                                            onClick={handleUploadClick}
                                            disabled={isUploadingNewVersion}
                                            className="flex items-center gap-2 text-sm bg-white text-oliver-azure font-semibold py-1.5 px-3 rounded-full border-2 border-oliver-azure hover:bg-oliver-azure hover:text-white hover:shadow-sm active:scale-95 transition-all duration-150 disabled:bg-gray-300 disabled:text-oliver-black/60 disabled:border-grey-300 disabled:cursor-wait shrink-0 whitespace-nowrap"
                                            title="Upload a new version of this proof"
                                        >
                                            {isUploadingNewVersion ? (
                                                <>
                                                    <SpinnerIcon className="h-4 w-4 custom-spinner" />
                                                    Uploading...
                                                </>
                                            ) : (
                                                <>
                                                    <UploadIcon className="h-4 w-4" />
                                                    New Version
                                                </>
                                            )}
                                        </button>
                                    )}
                                </div>
                                <input
                                    type="file"
                                    ref={fileInputRef}
                                    onChange={handleFileChange}
                                    className="hidden"
                                    accept="image/png, image/jpeg, image/webp, image/gif, video/mp4, application/pdf"
                                    disabled={isUploadingNewVersion}
                                />
                            </div>
                            <div className="space-y-2">
                                {versions.map((version: any, index: number) => {
                                    const isActive = index === selectedVersionIndex;
                                    return (
                                        <button
                                            key={version.version}
                                            onClick={() => setSelectedVersionIndex(index)}
                                            className={`w-full text-left p-3 rounded-[10px] border-2 transition-all ${
                                                isActive
                                                ? 'bg-oliver-grey border-oliver-azure shadow-sm'
                                                : 'bg-white border-grey-300 hover:border-oliver-azure/50 hover:bg-oliver-grey'
                                            }`}
                                        >
                                            <div className="flex justify-between items-center">
                                                <p className={`font-bold ${isActive ? 'text-oliver-black' : 'text-oliver-black'}`}>Version {version.version}</p>
                                                <p className="text-xs text-oliver-black/60">{version.timestamp}</p>
                                            </div>
                                            <p className="text-sm text-oliver-black mt-1">Workfront ID: {version.workfrontId}</p>
                                        </button>
                                    );
                                })}
                            </div>
                        </div>
                    </div>
                </div>
                <div className="mt-8 lg:mt-0 lg:col-span-2">
                    {selectedVersion.isIdenticalFile && (
                        <div className="mb-6 bg-warning-light border border-warning rounded-[10px] p-4 flex items-start gap-3">
                            <ExclamationTriangleIcon className="w-5 h-5 text-warning flex-shrink-0 mt-0.5" />
                            <div>
                                <p className="font-semibold text-oliver-black">Identical File Detected</p>
                                <p className="text-sm text-oliver-black mt-1">
                                    This file is exactly the same as the previous version.
                                    The analysis results shown are from the new analysis,
                                    but no changes were made to the creative.
                                </p>
                            </div>
                        </div>
                    )}
                    <FeedbackReport
                        feedback={selectedVersion.feedback}
                        onFlagSubmit={handleFlagSubmitWrapper}
                        onResolveSubmit={handleResolveSubmitWrapper}
                        flaggedItems={flaggedItems}
                        resolvedItems={resolvedItems}
                        proofName={proof.proofName}
                        version={selectedVersion.version}
                    />
                </div>
            </div>
        </div>
    )
};


interface CampaignsProps {
    selectedCampaign: string | null;
    selectedProof: any | null;
    onSelectCampaign: (campaignName: string) => void;
    onSelectProof: (proof: any) => void;
    onBackToCampaignsList: () => void;
    onBackToCampaignDetails: () => void;
    campaigns: typeof initialCampaigns;
    campaignProofs: typeof initialCampaignProofs;
    onAddNewCampaign: (campaignData: { name: string; workfrontId: string; clientLead: string; brandGuidelines: string; }) => void;
    onProofUpload: (campaignName: string, file: File, proofName: string, channel: string, subChannel: string, proofType?: string) => void;
    dropdownOptions: DropdownOptions;
    onRetryAnalysis: (campaignName: string, tempId: string) => void;
    onCampaignStatusChange: (campaignName: string, newStatus: 'In Progress' | 'Completed') => void;
    onDeleteProof: (campaignName: string, proofName: string) => void;
    onDeleteCampaign: (campaignName: string) => Promise<void>;
    onFlagSubmit: (flagData: Omit<FlaggedItem, 'id' | 'timestamp' | 'submitter' | 'submitAgency'>) => void;
    onResolveSubmit: (resolveData: Omit<ResolvedItem, 'id' | 'timestamp' | 'submitter' | 'submitAgency'>) => void;
    flaggedItems: FlaggedItem[];
    resolvedItems: ResolvedItem[];
    readOnly?: boolean;
    selectedAgencyId?: string | null;
}

export const Campaigns: React.FC<CampaignsProps> = ({
    selectedCampaign,
    selectedProof,
    onSelectCampaign,
    onSelectProof,
    onBackToCampaignsList,
    onBackToCampaignDetails,
    campaigns,
    campaignProofs,
    onAddNewCampaign,
    onProofUpload,
    dropdownOptions,
    onRetryAnalysis,
    onCampaignStatusChange,
    onDeleteProof,
    onDeleteCampaign,
    onFlagSubmit,
    onResolveSubmit,
    flaggedItems,
    resolvedItems,
    readOnly = false,
    selectedAgencyId,
 }) => {
    
    const [isModalOpen, setIsModalOpen] = useState(false);
    
    if (selectedCampaign && selectedProof) {
        const handleNewVersionUpload = (file: File) => {
            onProofUpload(
                selectedCampaign,
                file,
                selectedProof.proofName,
                selectedProof.channel,
                selectedProof.subChannel,
                selectedProof.proofType
            );
        };

        const isUploadingNewVersion = campaignProofs[selectedCampaign]?.some(
            proof => (proof.status === 'analyzing' || proof.status === 'loading') && proof.proofName === selectedProof.proofName
        );

        return <ProofDetailView
                    campaignName={selectedCampaign}
                    proof={selectedProof}
                    onBack={onBackToCampaignDetails}
                    onNewVersionUpload={handleNewVersionUpload}
                    isUploadingNewVersion={isUploadingNewVersion}
                    onFlagSubmit={onFlagSubmit}
                    onResolveSubmit={onResolveSubmit}
                    flaggedItems={flaggedItems}
                    resolvedItems={resolvedItems}
                    readOnly={readOnly}
                />;
    }

    if (selectedCampaign) {
        return <CampaignDetail 
                    campaignName={selectedCampaign} 
                    onBack={onBackToCampaignsList} 
                    onSelectProof={onSelectProof} 
                    campaignProofs={campaignProofs}
                    onProofUpload={(file, proofName, channel, subChannel, proofType) => onProofUpload(selectedCampaign, file, proofName, channel, subChannel, proofType)}
                    dropdownOptions={dropdownOptions}
                    onRetryAnalysis={onRetryAnalysis}
                    onDeleteProof={onDeleteProof}
                    readOnly={readOnly}
                />;
    }

    return (
        <>
            {!readOnly && (
                <CreateCampaignModal
                    isOpen={isModalOpen}
                    onClose={() => setIsModalOpen(false)}
                    onAddCampaign={onAddNewCampaign}
                    brandGuidelines={dropdownOptions.brandGuidelines}
                />
            )}
            <CampaignList
                onSelectCampaign={onSelectCampaign}
                campaigns={campaigns}
                onOpenModal={readOnly ? () => {} : () => setIsModalOpen(true)}
                onCampaignStatusChange={readOnly ? () => {} : onCampaignStatusChange}
                onDeleteCampaign={readOnly ? () => {} : (campaign) => onDeleteCampaign(campaign.name)}
                readOnly={readOnly}
                selectedAgencyId={selectedAgencyId}
            />
        </>
    );
};
