import {
    Component,
    Input,
    ElementRef,
    ViewChild,
    OnChanges,
    SimpleChanges,
    ChangeDetectorRef,
    AfterViewInit
} from '@angular/core';
import * as pdfjsLib from 'pdfjs-dist/legacy/build/pdf';

pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.9.359/pdf.worker.min.js';

@Component({
    selector: 'app-pdf-viewer',
    templateUrl: './pdf-viewer.component.html',
    styleUrls: ['./pdf-viewer.component.css']
})
export class PdfViewerComponent implements OnChanges, AfterViewInit {
    @ViewChild('canvasContainer', { static: true }) canvasContainer!: ElementRef<HTMLDivElement>;
    @Input() pdfSrc!: string;
    @Input() syncScrollRef: PdfViewerComponent | null = null;
    @Input() isSyncScrollEnabled: boolean = false;
    pdf: any;
    canvasElements = new Map<number, HTMLCanvasElement>();
    private isProgrammaticScroll = false;
    highlightEnabled = true;
    isPdfLoading = false;
    pdfDoc: any = null;
    currentPage = 1;
    totalPages = 0;
    scale = 1.5;
    gotoPageNumber: number | null = null;
    isDarkMode = false;
    searchQuery: string = '';
    searchMatches: { page: number; text: string; y: number }[] = [];


    constructor(private cdr: ChangeDetectorRef) { }

    ngOnChanges(changes: SimpleChanges): void {
        if (changes['pdfSrc'] && this.pdfSrc) {
            this.loadPdf(this.pdfSrc);
        }
    }

    ngAfterViewInit(): void {
        this.canvasContainer.nativeElement.addEventListener('scroll', this.onScroll.bind(this));
    }

    get zoomPercentage(): number {
        return Math.round(this.scale * 100);
    }

    async loadPdf(url: string) {
        this.isPdfLoading = true;
        this.pdfDoc = await pdfjsLib.getDocument(url).promise;
        this.totalPages = this.pdfDoc.numPages;
        this.currentPage = 1;
        await this.renderAllPages();
        this.isPdfLoading = false;
        this.cdr.detectChanges();


    }

    async renderAllPages() {
        const container = this.canvasContainer.nativeElement;
        container.innerHTML = '';

        for (let i = 1; i <= this.totalPages; i++) {
            const page = await this.pdfDoc.getPage(i);
            const viewport = page.getViewport({ scale: this.scale });

            const canvas = document.createElement('canvas');
            const context = canvas.getContext('2d')!;
            canvas.height = viewport.height;
            canvas.width = viewport.width;
            canvas.setAttribute('data-page-number', i.toString());

            await page.render({ canvasContext: context, viewport }).promise;
            container.appendChild(canvas);
        }

        this.cdr.detectChanges();
    }

    prevPage(): void {
        if (this.currentPage > 1) {
            this.currentPage--;
            this.gotoPageNumber = this.currentPage; // ✅ sync
            this.scrollToPage(this.currentPage);
        }
    }

    nextPage(): void {
        if (this.currentPage < this.totalPages) {
            this.currentPage++;
            this.gotoPageNumber = this.currentPage; // ✅ sync
            this.scrollToPage(this.currentPage);
        }
    }



    async zoomIn() {
        this.scale += 0.25;
        await this.renderAllPages();
    }

    async zoomOut() {
        if (this.scale > 0.5) {
            this.scale -= 0.25;
            await this.renderAllPages();
        }
    }

    scrollToPage(page: number): void {
        const container = this.canvasContainer.nativeElement;
        const canvases = container.querySelectorAll('canvas');

        if (page >= 1 && page <= canvases.length) {
            const targetCanvas = canvases[page - 1];
            if (targetCanvas) {
                // scroll only inside canvas container, not whole page
                container.scrollTo({
                    top: targetCanvas.offsetTop,
                    behavior: 'smooth'
                });
            }
        }
    }



    onScroll(): void {
        const container = this.canvasContainer.nativeElement;
        const canvases = container.querySelectorAll('canvas');
        const containerTop = container.scrollTop;

        let closestPage = 1;
        let minDistance = Infinity;

        canvases.forEach((canvas, index) => {
            const offsetTop = (canvas as HTMLElement).offsetTop;
            const distance = Math.abs(offsetTop - containerTop);
            if (distance < minDistance) {
                minDistance = distance;
                closestPage = index + 1;
            }
        });

        if (this.currentPage !== closestPage) {
            this.currentPage = closestPage;
            this.gotoPageNumber = closestPage;
            this.cdr.detectChanges();
        }

        // 🔁 Sync scroll only if enabled and not triggered programmatically
        if (this.isSyncScrollEnabled && this.syncScrollRef && !this.isProgrammaticScroll) {
            const ratio = container.scrollTop / (container.scrollHeight - container.clientHeight);
            const target = this.syncScrollRef.canvasContainer.nativeElement;
            const syncedTop = ratio * (target.scrollHeight - target.clientHeight);
            this.syncScrollRef.setScrollPosition(syncedTop);
        }
    }
    setScrollPosition(position: number): void {
        this.isProgrammaticScroll = true;
        this.canvasContainer.nativeElement.scrollTop = position;

        requestAnimationFrame(() => {
            this.isProgrammaticScroll = false;
        });
    }

    goToPage(): void {
        debugger;
        if (
            this.gotoPageNumber &&
            this.gotoPageNumber >= 1 &&
            this.gotoPageNumber <= this.totalPages
        ) {
            this.currentPage = this.gotoPageNumber;
            this.scrollToPage(this.gotoPageNumber);
        }
    }
    downloadPdf() {
        if (!this.pdfSrc) return;

        // Function to extract filename from URL
        const extractFilename = (url: string): string => {
            try {
                const pathname = new URL(url, window.location.href).pathname;
                const name = pathname.substring(pathname.lastIndexOf('/') + 1);
                return name || 'document.pdf';
            } catch {
                return 'document.pdf';
            }
        };

        const filename = extractFilename(this.pdfSrc);

        // Handle blob or full URLs
        if (
            this.pdfSrc.startsWith('blob:') ||
            this.pdfSrc.startsWith('http') ||
            this.pdfSrc.startsWith('data:')
        ) {
            const a = document.createElement('a');
            a.href = this.pdfSrc;
            a.download = filename;
            a.click();
        } else {
            // Handle relative path (like 'assets/sample.pdf')
            fetch(this.pdfSrc)
                .then(response => response.blob())
                .then(blob => {
                    const blobUrl = URL.createObjectURL(blob);
                    const a = document.createElement('a');
                    a.href = blobUrl;
                    a.download = filename;
                    a.click();
                    URL.revokeObjectURL(blobUrl);
                })
                .catch(err => console.error('Download failed', err));
        }
    }

    setHighlighting(enabled: boolean): void {
        this.highlightEnabled = enabled;
        this.renderAllPages(); // re-render pages with or without highlights
    }

    updateView(): void {
        this.renderAllPages();
        this.scrollToPage(this.currentPage);
    }
    resetZoom(): void {
        this.scale = 1.5; // or your default zoom level
        this.renderAllPages();
    }
    fitToWidth(): void {
        const container = this.canvasContainer.nativeElement;
        const width = container.clientWidth;

        // Temporary page to calculate required scale
        this.pdfDoc.getPage(1).then((page: any) => {
            const viewport = page.getViewport({ scale: 1 });
            const scale = width / viewport.width;

            this.scale = parseFloat(scale.toFixed(2));
            this.renderAllPages();
        });
    }
    fitToPage(): void {
        const container = this.canvasContainer.nativeElement;
        const height = container.clientHeight;

        this.pdfDoc.getPage(1).then((page: any) => {
            const viewport = page.getViewport({ scale: 1 });
            const scale = height / viewport.height;

            this.scale = parseFloat(scale.toFixed(2));
            this.renderAllPages();
        });
    }
    oggleDarkMode(): void {
        this.isDarkMode = !this.isDarkMode;

        const container = this.canvasContainer.nativeElement;
        container.style.backgroundColor = this.isDarkMode ? '#1e1e1e' : '#ffffff';

        // Apply invert filter to canvases
        const canvases = container.querySelectorAll('canvas');
        canvases.forEach(canvas => {
            (canvas as HTMLElement).style.filter = this.isDarkMode ? 'invert(1)' : 'invert(0)';
        });
    }
    printPdf(): void {
        const printWindow = window.open(this.pdfSrc, '_blank');
       if (printWindow) {
  printWindow.addEventListener('load', () => {
    printWindow.print();
  });
}
    }
    toggleDarkMode(): void {
        this.isDarkMode = !this.isDarkMode;

        const container = this.canvasContainer.nativeElement;

        // Set background color of container
        container.style.backgroundColor = this.isDarkMode ? '#1e1e1e' : '#ffffff';

        // Apply invert filter to all canvases inside the viewer
        const canvases = container.querySelectorAll('canvas');
        canvases.forEach((canvas: Element) => {
            (canvas as HTMLElement).style.filter = this.isDarkMode ? 'invert(1) hue-rotate(180deg)' : 'invert(0)';
        });
    }
    async onSearch() {
        this.searchMatches = [];

        if (!this.searchQuery || !this.pdfDoc) return;

        for (let pageNum = 1; pageNum <= this.totalPages; pageNum++) {
            const page = await this.pdfDoc.getPage(pageNum);
            const textContent = await page.getTextContent();

            textContent.items.forEach((item: any) => {
                const str = item.str || '';
                if (str.toLowerCase().includes(this.searchQuery.toLowerCase())) {
                    this.searchMatches.push({ page: pageNum, text: str, y: item.transform[5] });
                }
            });
        }

        this.highlightMatches();
    }
    async highlightMatches() {
        if (!this.pdfDoc) return;

        const container = this.canvasContainer.nativeElement;
        const canvases = container.querySelectorAll('canvas');

        for (let match of this.searchMatches) {
            const page = await this.pdfDoc.getPage(match.page);
            const viewport = page.getViewport({ scale: this.scale });
            const textContent = await page.getTextContent();

            const canvas = canvases[match.page - 1] as HTMLCanvasElement;
            const ctx = canvas.getContext('2d');
            if (!ctx) continue;

            ctx.save();
            ctx.fillStyle = 'rgba(255, 255, 0, 0.4)';

            textContent.items.forEach((item: any) => {
                const str = item.str || '';
                if (str.toLowerCase().includes(this.searchQuery.toLowerCase())) {
                    const transform = pdfjsLib.Util.transform(
                        viewport.transform,
                        item.transform
                    );
                    const x = transform[4];
                    const y = transform[5];
                    const width = item.width * this.scale;
                    const height = 10; // adjust as needed
                    ctx.fillRect(x, canvas.height - y, width, height);
                }
            });

            ctx.restore();
        }
    }


}
