import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useParams } from 'react-router-dom';
import { fetchData } from '../../fetching/Fetch.js';
import { GOLD_PRICE_URL, SERVER_URL } from '../../constants.js';
import {
    hasNewServingCall,
    playQueueCallSound,
    servingSnapshot,
    unlockQueueCallSound,
} from '../../utils/queueCallSound.js';
import AdCarousel from './AdCarousel.jsx';
import './BranchDisplayPage.css';

function formatGoldPrice(value) {
    const amount = Number(value);
    if (!Number.isFinite(amount)) return value ?? '—';
    return amount.toLocaleString('en-MY', {
        minimumFractionDigits: 2,
        maximumFractionDigits: 2,
    });
}

export default function BranchDisplayPage() {
    const { tenantCode, branchId } = useParams();
    const [branchName, setBranchName] = useState('');
    const [stations, setStations] = useState([]);
    const [tickets, setTickets] = useState([]);
    const [goldPrices, setGoldPrices] = useState([]);
    const [goldUpdatedAt, setGoldUpdatedAt] = useState(null);
    const [goldError, setGoldError] = useState(null);
    const [error, setError] = useState(null);
    const [soundReady, setSoundReady] = useState(false);
    const goldTableWrapRef = useRef(null);
    const previousServingRef = useRef(null);

    const loadDisplay = useCallback(async () => {
        if (!tenantCode || !branchId) return;

        try {
            const [stationsRes, queueRes, branchesRes] = await Promise.all([
                fetchData(
                    `${SERVER_URL}/api/v1/stations/${encodeURIComponent(tenantCode)}/${branchId}`,
                    'GET'
                ),
                fetchData(
                    `${SERVER_URL}/api/v1/branches/${encodeURIComponent(tenantCode)}/${branchId}/queue?activeOnly=true&sort=createdAt,asc`,
                    'GET'
                ),
                fetchData(
                    `${SERVER_URL}/api/v1/branches/${encodeURIComponent(tenantCode)}`,
                    'GET'
                ),
            ]);

            if (!stationsRes.success || !queueRes.success) {
                setError('Could not load branch display.');
                return;
            }

            setError(null);
            setStations(Array.isArray(stationsRes.data) ? stationsRes.data : []);
            setTickets(Array.isArray(queueRes.data) ? queueRes.data : []);

            if (branchesRes.success && Array.isArray(branchesRes.data)) {
                const branch = branchesRes.data.find(
                    (item) => Number(item.id) === Number(branchId)
                );
                if (branch?.name) {
                    setBranchName(branch.name);
                }
            } else if (queueRes.data?.[0]?.branch?.name) {
                setBranchName(queueRes.data[0].branch.name);
            }
        } catch (err) {
            console.error(err);
            setError('Could not load branch display.');
        }
    }, [tenantCode, branchId]);

    const loadGoldPrices = useCallback(async () => {
        try {
            const response = await fetch(GOLD_PRICE_URL);
            if (!response.ok) {
                throw new Error(`Gold price request failed (${response.status})`);
            }
            const data = await response.json();
            const rows = Array.isArray(data) ? data : [];
            setGoldPrices(rows);
            setGoldUpdatedAt(rows[0]?.tarikhupdate ?? null);
            setGoldError(null);
        } catch (err) {
            console.error(err);
            setGoldError('Could not load gold prices.');
        }
    }, []);

    useEffect(() => {
        loadDisplay();
        const interval = setInterval(loadDisplay, 3000);
        return () => clearInterval(interval);
    }, [loadDisplay]);

    useEffect(() => {
        loadGoldPrices();
        const interval = setInterval(loadGoldPrices, 5 * 60 * 1000);
        return () => clearInterval(interval);
    }, [loadGoldPrices]);

    useEffect(() => {
        const wrap = goldTableWrapRef.current;
        if (!wrap || goldPrices.length === 0) return undefined;

        let rafId = 0;
        let pauseUntil = 0;
        let direction = 1;
        const speedPxPerSec = 28;
        const pauseMs = 1600;
        let lastTs = 0;

        const step = (now) => {
            if (!lastTs) lastTs = now;
            const dt = Math.min(now - lastTs, 50);
            lastTs = now;

            const maxScroll = wrap.scrollHeight - wrap.clientHeight;
            if (maxScroll <= 2) {
                rafId = requestAnimationFrame(step);
                return;
            }

            if (now < pauseUntil) {
                rafId = requestAnimationFrame(step);
                return;
            }

            wrap.scrollTop += (speedPxPerSec * dt * direction) / 1000;

            if (direction > 0 && wrap.scrollTop >= maxScroll - 1) {
                wrap.scrollTop = maxScroll;
                direction = -1;
                pauseUntil = now + pauseMs;
            } else if (direction < 0 && wrap.scrollTop <= 1) {
                wrap.scrollTop = 0;
                direction = 1;
                pauseUntil = now + pauseMs;
            }

            rafId = requestAnimationFrame(step);
        };

        const startId = requestAnimationFrame(() => {
            wrap.scrollTop = 0;
            lastTs = 0;
            rafId = requestAnimationFrame(step);
        });

        return () => {
            cancelAnimationFrame(startId);
            cancelAnimationFrame(rafId);
        };
    }, [goldPrices]);

    const servingByStationId = useMemo(() => {
        const map = new Map();
        for (const ticket of tickets) {
            if (ticket.station?.id != null) {
                map.set(Number(ticket.station.id), ticket);
            }
        }
        return map;
    }, [tickets]);

    useEffect(() => {
        const next = servingSnapshot(tickets);
        const previous = previousServingRef.current;

        if (hasNewServingCall(previous, next)) {
            playQueueCallSound();
        }

        previousServingRef.current = next;
    }, [tickets]);

    const waiting = useMemo(
        () => tickets.filter((ticket) => ticket.station == null),
        [tickets]
    );

    const sortedStations = useMemo(
        () => [...stations].sort((a, b) => String(a.name).localeCompare(String(b.name))),
        [stations]
    );

    return (
        <div
            className="branch-display"
            onClick={() => {
                if (!soundReady) {
                    unlockQueueCallSound();
                    setSoundReady(true);
                }
            }}
        >
            {!soundReady ? (
                <button
                    type="button"
                    className="branch-display__sound-enable"
                    onClick={(event) => {
                        event.stopPropagation();
                        unlockQueueCallSound();
                        setSoundReady(true);
                    }}
                >
                    Enable call sound
                </button>
            ) : null}

            <header className="branch-display__header">
                <div className="branch-display__brand">
                    <img
                        className="branch-display__logo"
                        src="/logo-arrahn.jpeg"
                        alt="ar-rahn"
                    />
                    <h1 className="branch-display__title">
                        Selamat Datang ke Cawangan {branchName}
                    </h1>
                </div>
                <p className="branch-display__eyebrow">Sistem Nombor Giliran</p>
            </header>

            {error ? <p className="branch-display__error">{error}</p> : null}

            <div className="branch-display__main">
                <div className="branch-display__queue-column">
                    <section className="branch-display__section">
                        <h2 className="branch-display__section-title">Sedang Diproses</h2>
                        {sortedStations.length === 0 ? (
                            <p className="branch-display__empty">Tiada Stesen di Branch ini.</p>
                        ) : (
                            <div className="branch-display__stations">
                                {sortedStations.map((station) => {
                                    const ticket = servingByStationId.get(Number(station.id));
                                    return (
                                        <article
                                            key={station.id}
                                            className="branch-display__station-card"
                                        >
                                            <p className="branch-display__station-name">
                                                {station.name}
                                            </p>
                                            <p
                                                className={
                                                    ticket
                                                        ? 'branch-display__ticket-number'
                                                        : 'branch-display__ticket-number branch-display__ticket-number--idle'
                                                }
                                            >
                                                {ticket ? ticket.number : '—'}
                                            </p>
                                            <p className="branch-display__station-service">
                                                {ticket?.service?.name ?? 'Waiting for next'}
                                            </p>
                                        </article>
                                    );
                                })}
                            </div>
                        )}
                    </section>

                    <section className="branch-display__section branch-display__section--waiting">
                        <div className="branch-display__waiting-header">
                            <h2 className="branch-display__section-title">Giliran</h2>
                            <p className="branch-display__waiting-count">
                                {waiting.length} dalam giliran
                            </p>
                        </div>
                        {waiting.length === 0 ? (
                            <p className="branch-display__empty">Tiada nombor dalam giliran.</p>
                        ) : (
                            <ul className="branch-display__waiting-list">
                                {waiting.map((ticket) => (
                                    <li key={ticket.id} className="branch-display__waiting-item">
                                        <span className="branch-display__waiting-number">
                                            {ticket.number}
                                        </span>
                                    </li>
                                ))}
                            </ul>
                        )}
                    </section>

                    <section className="branch-display__section branch-display__section--gold">
                        <div className="branch-display__waiting-header">
                            <h2 className="branch-display__section-title">Harga Emas</h2>
                            {goldUpdatedAt ? (
                                <p className="branch-display__waiting-count">
                                    Dikemas kini pada {goldUpdatedAt}
                                </p>
                            ) : null}
                        </div>
                        {goldError ? (
                            <p className="branch-display__error">{goldError}</p>
                        ) : null}
                        {!goldError && goldPrices.length === 0 ? (
                            <p className="branch-display__empty">Loading harga emas…</p>
                        ) : null}
                        {goldPrices.length > 0 ? (
                            <div
                                ref={goldTableWrapRef}
                                className="branch-display__gold-table-wrap"
                            >
                                <table className="branch-display__gold-table">
                                    <thead>
                                        <tr>
                                            <th>Karat</th>
                                            <th>Mutu</th>
                                            <th>RM/g</th>
                                        </tr>
                                    </thead>
                                    <tbody>
                                        {goldPrices.map((row) => (
                                            <tr
                                                key={
                                                    row.recno ??
                                                    `${row.karat}-${row.keterangan}`
                                                }
                                            >
                                                <td>{row.karat}</td>
                                                <td>{row.keterangan}</td>
                                                <td>{formatGoldPrice(row.harga)}</td>
                                            </tr>
                                        ))}
                                    </tbody>
                                </table>
                            </div>
                        ) : null}
                    </section>
                </div>

                <AdCarousel tenantCode={tenantCode} />
            </div>
        </div>
    );
}
