import React, { useState, useEffect, useRef, useCallback } from 'react';
import { useRemoteControl } from '../hooks/useRemoteControl';
import { fetchChannels, fetchChannelAirings } from '../api';

const EPG_HOURS = 4;
const HOUR_WIDTH_PX = 360;
const PX_PER_MS = HOUR_WIDTH_PX / (60 * 60 * 1000);

function fmtTime(iso) {
  if (!iso) return '';
  return new Date(iso).toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' });
}

function fmtDuration(starts_at, ends_at) {
  if (!starts_at || !ends_at) return '';
  const mins = Math.round((new Date(ends_at) - new Date(starts_at)) / 60000);
  if (mins < 60) return `${mins}m`;
  const h = Math.floor(mins / 60), m = mins % 60;
  return m ? `${h}h ${m}m` : `${h}h`;
}

export default function Guide({ onClose, onSelectChannel }) {
  const [channels, setChannels] = useState([]);
  const [airings, setAirings] = useState({});
  const [selectedRow, setSelectedRow] = useState(0);
  const [selectedProgram, setSelectedProgram] = useState(0);
  const [now, setNow] = useState(Date.now());
  const scrollRef = useRef(null);
  const programRefs = useRef({}); // { `${rowIdx}-${progIdx}`: el }
  const rowsScrollRef = useRef(null);

  const anchorTime = useRef(new Date(Math.floor(Date.now() / 1800000) * 1800000).getTime());

  // Build filtered + sorted airing list for a channel
  const getAiringsForRow = useCallback((chanId) => {
    const list = airings[chanId] || [];
    return list
      .filter(a => new Date(a.ends_at).getTime() > anchorTime.current)
      .sort((a, b) => new Date(a.starts_at) - new Date(b.starts_at));
  }, [airings]);

  // Clamp selectedProgram when row changes
  useEffect(() => {
    const ch = channels[selectedRow];
    if (!ch) return;
    const rowAirings = getAiringsForRow(ch.id);
    setSelectedProgram(prev => Math.min(prev, Math.max(0, rowAirings.length - 1)));
  }, [selectedRow, channels, getAiringsForRow]);

  // Auto-scroll focused program into view (timeline scroll)
  useEffect(() => {
    const key = `${selectedRow}-${selectedProgram}`;
    const el = programRefs.current[key];
    if (el && scrollRef.current) {
      const containerRect = scrollRef.current.getBoundingClientRect();
      const elRect = el.getBoundingClientRect();
      const relLeft = elRect.left - containerRect.left + scrollRef.current.scrollLeft;
      const targetScroll = relLeft - containerRect.width / 4;
      scrollRef.current.scrollTo({ left: Math.max(0, targetScroll), behavior: 'smooth' });
    }
  }, [selectedRow, selectedProgram]);

  // Auto-scroll focused row into view (rows column scroll)
  useEffect(() => {
    if (rowsScrollRef.current) {
      const rowHeight = 80;
      const visibleHeight = rowsScrollRef.current.clientHeight;
      const rowTop = selectedRow * rowHeight;
      const rowBottom = rowTop + rowHeight;
      const currentScroll = rowsScrollRef.current.scrollTop;
      if (rowTop < currentScroll) {
        rowsScrollRef.current.scrollTop = rowTop;
      } else if (rowBottom > currentScroll + visibleHeight) {
        rowsScrollRef.current.scrollTop = rowBottom - visibleHeight;
      }
    }
  }, [selectedRow]);

  useRemoteControl({
    onUp: () => setSelectedRow(prev => Math.max(0, prev - 1)),
    onDown: () => setSelectedRow(prev => Math.min(channels.length - 1, prev + 1)),
    onLeft: () => setSelectedProgram(prev => Math.max(0, prev - 1)),
    onRight: () => {
      const ch = channels[selectedRow];
      if (!ch) return;
      const rowAirings = getAiringsForRow(ch.id);
      setSelectedProgram(prev => Math.min(rowAirings.length - 1, prev + 1));
    },
    onSelect: () => channels[selectedRow] && onSelectChannel(channels[selectedRow].id),
    onBack: onClose,
  });

  // Clock tick
  useEffect(() => {
    const timer = setInterval(() => setNow(Date.now()), 15000);
    return () => clearInterval(timer);
  }, []);

  // Fetch channels and airings
  useEffect(() => {
    fetchChannels()
      .then(data => {
        const sorted = [...data].sort((a, b) => {
          if (a.channel_number == null) return 1;
          if (b.channel_number == null) return -1;
          return a.channel_number - b.channel_number;
        });
        if (sorted.length === 0) {
          setChannels([{ id: 99, channel_number: 99, name: 'No Channels Found' }]);
          return;
        }
        setChannels(sorted);

        Promise.allSettled(
          data.map(ch =>
            fetchChannelAirings(ch.id, EPG_HOURS)
              .then(list => ({ channelId: ch.id, list }))
              .catch(() => ({ channelId: ch.id, list: [] }))
          )
        ).then(results => {
          const map = {};
          for (const r of results) {
            if (r.status === 'fulfilled') map[r.value.channelId] = r.value.list;
          }
          setAirings(map);
        });
      })
      .catch(err => {
        console.error('Guide fetch error:', err);
        setChannels([{ id: 99, channel_number: 99, name: 'Network Error' }]);
      });
  }, []);

  // Initial scroll to now
  useEffect(() => {
    if (scrollRef.current) {
      const msOffset = now - anchorTime.current;
      const pxOffset = msOffset * PX_PER_MS;
      scrollRef.current.scrollLeft = Math.max(0, pxOffset - HOUR_WIDTH_PX / 2);
    }
  }, [airings]); // only run once airings load

  const currentTimeStr = new Date(now).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
  const playheadPx = (now - anchorTime.current) * PX_PER_MS;
  const containerWidthPx = EPG_HOURS * HOUR_WIDTH_PX + HOUR_WIDTH_PX;

  const timeSlots = Array.from({ length: EPG_HOURS * 2 + 2 }).map((_, i) => {
    const ts = new Date(anchorTime.current + i * 30 * 60 * 1000);
    return {
      label: ts.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' }),
      left: i * (HOUR_WIDTH_PX / 2),
    };
  });

  // Focused program info for the detail panel
  const focusedChannel = channels[selectedRow];
  const focusedAirings = focusedChannel ? getAiringsForRow(focusedChannel.id) : [];
  const focusedAiring = focusedAirings[selectedProgram] || null;

  const nowStr = new Date(now).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
  const isLive = focusedAiring
    ? now >= new Date(focusedAiring.starts_at).getTime() && now < new Date(focusedAiring.ends_at).getTime()
    : false;

  // Progress % for live program
  const liveProgress = isLive && focusedAiring
    ? Math.min(100, Math.round(
        (now - new Date(focusedAiring.starts_at).getTime()) /
        (new Date(focusedAiring.ends_at).getTime() - new Date(focusedAiring.starts_at).getTime()) * 100
      ))
    : 0;

  return (
    <div className="guide-container open" style={{ paddingBottom: 0 }}>
      {/* Header */}
      <div className="guide-header">
        <h1>PYTV Guide</h1>
        <div className="guide-clock">{currentTimeStr}</div>
      </div>

      {/* EPG grid — takes available space between header and detail panel */}
      <div className="epg-wrapper" style={{ flex: 1, minHeight: 0 }}>

        {/* Left sticky channel column */}
        <div className="epg-channels-col" style={{ overflow: 'hidden', display: 'flex', flexDirection: 'column' }}>
          <div className="epg-corner" />
          <div ref={rowsScrollRef} className="epg-grid-rows" style={{ overflowY: 'hidden', flex: 1 }}>
            {channels.map((chan, idx) => (
              <div
                key={chan.id}
                className={`epg-row ${idx === selectedRow ? 'active' : ''}`}
                onClick={() => { setSelectedRow(idx); setSelectedProgram(0); }}
              >
                <div className="epg-ch-num">{chan.channel_number}</div>
                <div className="epg-ch-name">{chan.name}</div>
              </div>
            ))}
          </div>
        </div>

        {/* Scrollable timeline */}
        <div className="epg-timeline-scroll" ref={scrollRef}>
          <div
            className="epg-timeline-container"
            style={{ width: `${containerWidthPx}px`, backgroundSize: `${HOUR_WIDTH_PX / 2}px 100%` }}
          >
            {/* Time axis */}
            <div className="epg-time-axis">
              {timeSlots.map((slot, i) => (
                <div key={i} className="epg-time-slot" style={{ left: `${slot.left}px` }}>
                  {slot.label}
                </div>
              ))}
            </div>

            {/* Live playhead */}
            {playheadPx > 0 && playheadPx < containerWidthPx && (
              <div className="epg-playhead" style={{ left: `${playheadPx}px` }} />
            )}

            {/* Program rows */}
            <div className="epg-grid-rows">
              {channels.map((chan, rowIdx) => {
                const rowAirings = getAiringsForRow(chan.id);
                const isLoading = !airings[chan.id] && chan.id !== 99;
                const isActiveRow = rowIdx === selectedRow;

                return (
                  <div
                    key={chan.id}
                    className={`epg-row ${isActiveRow ? 'active' : ''}`}
                  >
                    {isLoading && <div className="epg-loading">Loading…</div>}
                    {!isLoading && rowAirings.length === 0 && (
                      <div className="epg-empty">No scheduled programs</div>
                    )}

                    {rowAirings.map((a, progIdx) => {
                      const sTs = new Date(a.starts_at).getTime();
                      const eTs = new Date(a.ends_at).getTime();
                      const startPx = Math.max(0, (sTs - anchorTime.current) * PX_PER_MS);
                      const rawEndPx = (eTs - anchorTime.current) * PX_PER_MS;
                      const endPx = Math.min(containerWidthPx, rawEndPx);
                      const widthPx = Math.max(2, endPx - startPx);

                      let stateClass = 'future';
                      if (now >= sTs && now < eTs) stateClass = 'current';
                      else if (now >= eTs) stateClass = 'past';

                      const isFocused = isActiveRow && progIdx === selectedProgram;

                      return (
                        <div
                          key={a.id}
                          ref={el => {
                            const key = `${rowIdx}-${progIdx}`;
                            if (el) programRefs.current[key] = el;
                          }}
                          className={`epg-program ${stateClass}${isFocused ? ' epg-program-focused' : ''}`}
                          style={{ left: `${startPx}px`, width: `${widthPx}px` }}
                          onClick={() => {
                            setSelectedRow(rowIdx);
                            setSelectedProgram(progIdx);
                            onSelectChannel(chan.id);
                          }}
                          onMouseEnter={() => {
                            setSelectedRow(rowIdx);
                            setSelectedProgram(progIdx);
                          }}
                        >
                          <div className="epg-program-title">{a.media_item_title}</div>
                          <div className="epg-program-time">{fmtTime(a.starts_at)} – {fmtTime(a.ends_at)}</div>
                        </div>
                      );
                    })}
                  </div>
                );
              })}
            </div>
          </div>
        </div>
      </div>

      {/* ── Detail panel ─────────────────────────────────────────────────── */}
      <div className="epg-detail-panel">
        {focusedAiring ? (
          <>
            <div className="epg-detail-left">
              {isLive && <span className="epg-live-badge">● LIVE</span>}
              <div className="epg-detail-title">{focusedAiring.media_item_title || '—'}</div>
              <div className="epg-detail-meta">
                <span>{fmtTime(focusedAiring.starts_at)} – {fmtTime(focusedAiring.ends_at)}</span>
                <span className="epg-detail-dot">·</span>
                <span>{fmtDuration(focusedAiring.starts_at, focusedAiring.ends_at)}</span>
                {focusedChannel && (
                  <>
                    <span className="epg-detail-dot">·</span>
                    <span>CH {focusedChannel.channel_number} · {focusedChannel.name}</span>
                  </>
                )}
              </div>
              {isLive && (
                <div className="epg-progress-bar">
                  <div className="epg-progress-fill" style={{ width: `${liveProgress}%` }} />
                </div>
              )}
            </div>
            <div className="epg-detail-right">
              <div className="epg-detail-hint">
                <kbd>↑↓</kbd> Channel &nbsp; <kbd>←→</kbd> Program &nbsp; <kbd>Enter</kbd> Watch &nbsp; <kbd>Esc</kbd> Close
              </div>
              {isLive && (
                <button className="btn-accent" style={{ fontSize: '0.85rem', padding: '0.4rem 1rem' }}
                  onClick={() => onSelectChannel(focusedChannel.id)}>
                  ▶ Watch Now
                </button>
              )}
            </div>
          </>
        ) : focusedChannel ? (
          <div className="epg-detail-left" style={{ opacity: 0.5 }}>
            <div className="epg-detail-title">{focusedChannel.name}</div>
            <div className="epg-detail-meta">No programs scheduled — <kbd>↑↓</kbd> to navigate channels</div>
          </div>
        ) : (
          <div className="epg-detail-left" style={{ opacity: 0.4 }}>
            <div className="epg-detail-meta"><kbd>↑↓</kbd> Channel &nbsp; <kbd>←→</kbd> Program &nbsp; <kbd>Enter</kbd> Watch</div>
          </div>
        )}
      </div>
    </div>
  );
}
