import { Bars3Icon, PlayIcon, StopIcon, XMarkIcon } from '@heroicons/react/16/solid';
import { useState } from 'react';
import cx from '@src/cx.mjs';
import { themes } from '@strudel/codemirror';
import { LANGS, useT, setLanguage } from '@src/i18n.mjs';
import { StrudelIcon } from '@src/repl/components/icons/StrudelIcon';
import { useSettings, setIsZen, setIsPanelOpened, setActiveFooter as setTab, settingsMap } from '../../../settings.mjs';
import '../../Repl.css';
import { useLogger } from '../useLogger';
import { ConsoleTab } from './ConsoleTab';
import ExportTab from './ExportTab';
import { FilesTab } from './FilesTab';
import { PatternsTab } from './PatternsTab';
import { ProjectsTab } from './ProjectsTab';
import { GuideTab } from './GuideTab';
import { KisumTab } from './KisumTab';
import { VisorTab } from './VisorTab';
import { Reference } from './Reference';
import { SettingsTab } from './SettingsTab';
import { SoundsTab } from './SoundsTab';
import { WelcomeTab } from './WelcomeTab';

const TAURI = typeof window !== 'undefined' && window.__TAURI__;

const { BASE_URL } = import.meta.env;
const baseNoTrailing = BASE_URL.endsWith('/') ? BASE_URL.slice(0, -1) : BASE_URL;

export function LogoButton({ context, isEmbedded }) {
  const { started } = context;
  const { isZen, isCSSAnimationDisabled, fontFamily } = useSettings();
  return (
    <div
      className={cx(
        'mt-[1px]',
        started && !isCSSAnimationDisabled && 'animate-spin',
        'cursor-pointer text-blue-500',
        isZen && 'fixed top-2 right-4',
      )}
      onClick={() => {
        if (!isEmbedded) {
          setIsZen(!isZen);
        }
      }}
    >
      <span className="block text-foreground rotate-90">
        <StrudelIcon className="w-5 h-5 fill-foreground" />
      </span>
    </div>
  );
}

export function MainPanel({ context, isEmbedded = false, className }) {
  const { isZen, isButtonRowHidden, fontFamily } = useSettings();
  let loc = window.location;
  let ver = 'unofficial';
  let hot = false;
  let b = loc.hostname.match(/^(.+)\.(strudel)/);
  if (/(strudel.cc$)/.test(loc.hostname)) {
    // if there's no text before 'strudel', it's warm, otherwise use the text before strudel
    ver = b ? b[1] : 'warm';
  } else {
    // match both versions of localhost
    if (/(localhost)|(127.0.0.1)/.test(loc.hostname)) ver = 'dev';
  }
  let pr = ver.match(/pr-([0-9]+)/);
  if (pr) {
    pr = pr[1];
    ver = `hot: ${pr}`;
    hot = true;
    pr = `https://codeberg.org/uzu/strudel/pulls/${pr}`;
  }

  return (
    <nav
      id="header"
      className={cx(
        'flex-none text-black z-[100] text-sm select-none min-h-12 max-h-12',
        !isZen && !isEmbedded && 'border-b border-muted bg-lineHighlight',
        isZen ? 'h-12 w-8 fixed top-0 left-0' : '',
        'flex items-center relative',
        className,
      )}
      style={{ fontFamily }}
    >
      <div className={cx('flex w-full justify-between items-center')}>
        <div className="px-3 py-1 flex space-x-2 select-none shrink-0">
          <h1
            onClick={() => {
              if (isEmbedded) window.open(window.location.href.replace('embed', ''));
            }}
            className={cx(
              isEmbedded ? 'text-l cursor-pointer' : 'text-xl',
              'text-foreground font-bold flex space-x-2 items-center',
            )}
          >
            <LogoButton context={context} isEmbedded={isEmbedded} />
            {!isZen && (
              <div className="space-x-2 flex items-baseline">
                <span className="hidden sm:block">strudel</span>
                {!hot ? (
                  <span className="text-sm font-medium hidden lg:block">({ver})</span>
                ) : (
                  <a className="hover:opacity-50" href={pr} target="_blank">
                    <span className="text-sm font-medium hidden lg:block">({ver})</span>
                  </a>
                )}
              </div>
            )}
          </h1>
        </div>
        {/* menú principal CENTRADO de verdad (absoluto respecto al header) */}
        {!isZen && !isButtonRowHidden && (
          <div className="absolute left-1/2 -translate-x-1/2 hidden md:flex">
            <MainMenu isEmbedded={isEmbedded} context={context} />
          </div>
        )}
        {!isZen && (
          <div className="flex items-center gap-1.5 pr-1 shrink-0">
            {/* menú inline en pantallas pequeñas (donde no cabe centrado) */}
            {!isButtonRowHidden && (
              <div className="flex md:hidden">
                <MainMenu isEmbedded={isEmbedded} context={context} />
              </div>
            )}
            <ThemeSelector />
            <LanguageSelector />
            <PanelToggle isEmbedded={isEmbedded} isZen={isZen} />
          </div>
        )}
      </div>
    </nav>
  );
}

// ── selector de TEMA (header, derecha) ──────────────────────────────
function ThemeSelector() {
  const { theme } = useSettings();
  const t = useT();
  return (
    <select
      title={t('theme')}
      value={theme}
      onChange={(e) => settingsMap.setKey('theme', e.target.value)}
      className={cx(
        'bg-lineHighlight text-foreground text-xs rounded-md border border-muted cursor-pointer',
        'px-1.5 py-1 max-w-[9rem] outline-none transition-colors',
        'hover:border-cyan-400/70 hover:text-cyan-300 focus:border-cyan-400',
      )}
    >
      {Object.keys(themes).map((name) => (
        <option key={name} value={name}>
          🎨 {name}
        </option>
      ))}
    </select>
  );
}

// ── selector de IDIOMA (header, a la derecha del tema) ──────────────
function LanguageSelector() {
  const { language } = useSettings();
  const t = useT();
  return (
    <select
      title={t('language')}
      value={language || 'es'}
      onChange={(e) => setLanguage(e.target.value)}
      className={cx(
        'bg-lineHighlight text-foreground text-xs rounded-md border border-muted cursor-pointer',
        'px-1.5 py-1 outline-none transition-colors',
        'hover:border-cyan-400/70 hover:text-cyan-300 focus:border-cyan-400',
      )}
    >
      {Object.entries(LANGS).map(([code, label]) => (
        <option key={code} value={code}>
          🌍 {label}
        </option>
      ))}
    </select>
  );
}

export function Footer({ context, isEmbedded = false }) {
  return (
    <div className="border-t border-muted bg-lineHighlight block lg:hidden">
      <MainMenu context={context} isEmbedded={isEmbedded} />
    </div>
  );
}

// estilo compartido de los botones del menú: grandes, redondeados y con
// hover neón (fondo cian suave + texto cian + halo)
const menuBtn = cx(
  'flex items-center gap-1.5 px-4 py-1.5 rounded-lg font-semibold tracking-wide',
  'transition-all duration-150 cursor-pointer',
  'hover:bg-cyan-400/15 hover:text-cyan-300 hover:shadow-[0_0_14px_rgba(34,211,238,0.35)] hover:scale-105',
);

function MainMenu({ context, isEmbedded = false, className }) {
  const { started, pending, isDirty, activeCode, handleTogglePlay, handleEvaluate, handleShare } = context;
  const { isCSSAnimationDisabled } = useSettings();
  const t = useT();
  // abre el panel lateral en la pestaña indicada (projects, kisum, visor, settings…)
  const openTab = (tab) => {
    setTab(tab);
    setIsPanelOpened(true);
  };
  return (
    <div
      className={cx('flex items-center gap-1 text-sm max-w-full shrink-0 overflow-hidden text-foreground', className)}
    >
      <button
        onClick={handleTogglePlay}
        title={started ? t('stop') : t('play')}
        className={cx(menuBtn, !started && !isCSSAnimationDisabled && 'animate-pulse')}
      >
        {started ? <StopIcon className="w-6 h-6" /> : <PlayIcon className="w-6 h-6" />}
        {!isEmbedded && <span>{pending ? '...' : started ? t('stop') : t('play')}</span>}
      </button>
      <button
        onClick={handleEvaluate}
        title={t('update')}
        className={cx(menuBtn, (!isDirty || !activeCode) && 'opacity-50')}
      >
        {!isEmbedded && <span>{t('update')}</span>}
      </button>
      {!isEmbedded && (
        <button title={t('share')} className={menuBtn} onClick={handleShare}>
          <span>{t('share')}</span>
        </button>
      )}
      {!isEmbedded && (
        <a title={t('learn')} href={`${baseNoTrailing}/workshop/getting-started/`} className={menuBtn}>
          <span>{t('learn')}</span>
        </a>
      )}
      {/* accesos directos a paneles (abren la pestaña correspondiente) */}
      {!isEmbedded && <span className="mx-1 h-6 w-px bg-muted/70 self-center" />}
      {!isEmbedded && (
        <button title="projects" className={menuBtn} onClick={() => openTab('projects')}>
          <span>projects</span>
        </button>
      )}
      {!isEmbedded && (
        <button title="KISUM: audio a código Strudel" className={menuBtn} onClick={() => openTab('kisum')}>
          <span>KISUM</span>
        </button>
      )}
      {!isEmbedded && (
        <button title="visor: pentagrama y ondas en vivo" className={menuBtn} onClick={() => openTab('visor')}>
          <span>visor</span>
        </button>
      )}
      {!isEmbedded && (
        <button title="ajustes" className={menuBtn} onClick={() => openTab('settings')}>
          <span>ajustes</span>
        </button>
      )}
    </div>
  );
}

function PanelCloseButton() {
  const { isPanelOpen } = useSettings();
  return (
    isPanelOpen && (
      <button
        onClick={() => setIsPanelOpened(false)}
        className={cx('px-2 py-0 text-foreground hover:opacity-50')}
        aria-label="Close Menu"
      >
        <XMarkIcon className="w-6 h-6" />
      </button>
    )
  );
}

const BHKEY = 'strudel-bottompanel-h'; // alto (px) del panel inferior (redimensionable)

export function BottomPanel({ context }) {
  const { isPanelOpen, activeFooter: tab } = useSettings();
  const t = useT();
  const [h, setH] = useState(() => {
    try {
      return Number(localStorage.getItem(BHKEY)) || 360;
    } catch {
      return 360;
    }
  });

  // arrastrar el borde superior: encoge/agranda el panel (y el editor al revés)
  const startDrag = (e) => {
    e.preventDefault();
    const startY = e.clientY;
    const startH = h;
    let last = startH;
    const move = (ev) => {
      const max = Math.round(window.innerHeight * 0.8);
      last = Math.max(160, Math.min(max, startH + (startY - ev.clientY)));
      setH(last);
    };
    const up = () => {
      document.removeEventListener('mousemove', move);
      document.removeEventListener('mouseup', up);
      try {
        localStorage.setItem(BHKEY, String(Math.round(last)));
      } catch {
        /* noop */
      }
    };
    document.addEventListener('mousemove', move);
    document.addEventListener('mouseup', up);
  };

  return (
    <PanelNav
      className={cx(!isPanelOpen && 'min-h-10 max-h-10', 'shrink-0 overflow-hidden flex flex-col relative')}
      style={isPanelOpen ? { height: h } : undefined}
    >
      {isPanelOpen && (
        <div
          onMouseDown={startDrag}
          title={t('resizeHint')}
          className="h-1.5 w-full shrink-0 cursor-row-resize bg-muted hover:bg-cyan-400/60"
        />
      )}
      <div className="flex justify-between min-h-10 max-h-10 grid-cols-2 items-center border-t border-muted">
        <PanelCloseButton />
        <Tabs setTab={setTab} tab={tab} className={cx(isPanelOpen && 'border-l border-muted')} />
      </div>
      {isPanelOpen && (
        <div className="w-full h-full overflow-auto border-t border-muted">
          <PanelContent context={context} tab={tab} />
        </div>
      )}
    </PanelNav>
  );
}

const RWKEY = 'strudel-rightpanel-w'; // ancho (px) del panel derecho (redimensionable)

export function RightPanel({ context }) {
  const settings = useSettings();
  const { activeFooter: tab, isPanelOpen } = settings;
  const t = useT();
  const [w, setW] = useState(() => {
    try {
      return Number(localStorage.getItem(RWKEY)) || 600;
    } catch {
      return 600;
    }
  });
  if (!isPanelOpen) {
    return;
  }

  // arrastrar el borde izquierdo: encoge el editor / agranda el panel (y al revés)
  const startDrag = (e) => {
    e.preventDefault();
    const startX = e.clientX;
    const startW = w;
    let last = startW;
    const move = (ev) => {
      const max = Math.round(window.innerWidth * 0.9);
      last = Math.max(260, Math.min(max, startW + (startX - ev.clientX)));
      setW(last);
    };
    const up = () => {
      document.removeEventListener('mousemove', move);
      document.removeEventListener('mouseup', up);
      try {
        localStorage.setItem(RWKEY, String(Math.round(last)));
      } catch {
        /* noop */
      }
    };
    document.addEventListener('mousemove', move);
    document.addEventListener('mouseup', up);
  };

  return (
    <div className="flex h-full shrink-0 overflow-hidden">
      {/* divisor arrastrable entre editor y panel */}
      <div
        onMouseDown={startDrag}
        title={t('resizeHint')}
        className="w-1.5 h-full shrink-0 cursor-col-resize bg-muted hover:bg-cyan-400/60"
      />
      <PanelNav
        settings={settings}
        className="border-l border-muted h-full overflow-hidden"
        style={{ width: w, maxWidth: '90vw' }}
      >
        <div className={cx('flex flex-col h-full')}>
          <div className="flex justify-between w-full overflow-hidden border-b border-muted min-h-10 max-h-10">
            <PanelCloseButton />
            <Tabs setTab={setTab} tab={tab} className="border-l border-muted" />
          </div>
          <div className="overflow-auto h-full">
            <PanelContent context={context} tab={tab} />
          </div>
        </div>
      </PanelNav>
    </div>
  );
}

const tabNames = {
  projects: 'projects',
  kisum: 'kisum',
  visor: 'visor',
  guía: 'guia',
  welcome: 'intro',
  patterns: 'patterns',
  sounds: 'sounds',
  reference: 'reference',
  export: 'export',
  console: 'console',
  settings: 'settings',
};
if (TAURI) {
  tabNames.files = 'files';
}

// clave de traducción de la etiqueta visible de cada pestaña (el valor
// interno no cambia — solo el texto que se muestra)
const tabLabelKeys = {
  projects: 'tabProjects',
  guia: 'tabGuide',
  intro: 'tabIntro',
  patterns: 'tabPatterns',
  sounds: 'tabSounds',
  reference: 'tabReference',
  export: 'tabExport',
  console: 'tabConsole',
  settings: 'tabSettings',
  files: 'tabFiles',
};

function PanelNav({ children, className, ...props }) {
  const settings = useSettings();
  return (
    <nav
      onClick={() => {
        if (!settings.isPanelOpen) {
          setIsPanelOpened(true);
        }
      }}
      aria-label="Menu Panel"
      className={cx('h-full bg-lineHighlight group overflow-x-auto', className)}
      {...props}
    >
      {children}
    </nav>
  );
}

function PanelContent({ context, tab }) {
  useLogger();
  switch (tab) {
    case tabNames.projects:
      return <ProjectsTab context={context} />;
    case tabNames.kisum:
      return <KisumTab context={context} />;
    case tabNames.visor:
      return <VisorTab context={context} />;
    case tabNames.guia:
      return <GuideTab />;
    case tabNames.patterns:
      return <PatternsTab context={context} />;
    case tabNames.console:
      return <ConsoleTab />;
    case tabNames.sounds:
      return <SoundsTab />;
    case tabNames.reference:
      return <Reference />;
    case tabNames.export:
      return <ExportTab handleExport={context.handleExport} />;
    case tabNames.settings:
      return <SettingsTab started={context.started} />;
    case tabNames.files:
      return <FilesTab />;
    default:
      return <WelcomeTab context={context} />;
  }
}

function PanelTab({ label, isSelected, onClick }) {
  return (
    <>
      <button
        onClick={onClick}
        className={cx(
          'h-10 px-2 text-sm border-t-2 border-t-transparent text-foreground cursor-pointer hover:opacity-50 flex items-center space-x-1 border-b-2',
          isSelected ? 'border-foreground' : 'border-transparent',
        )}
      >
        {label}
      </button>
    </>
  );
}
function Tabs({ className }) {
  const { isPanelOpen, activeFooter: tab } = useSettings();
  const t = useT();
  return (
    <div
      className={cx(
        'px-2 w-full flex select-none max-w-full h-10 max-h-10 min-h-10 overflow-auto items-center',
        className,
      )}
    >
      {Object.keys(tabNames).map((key) => {
        const val = tabNames[key];
        const label = tabLabelKeys[val] ? t(tabLabelKeys[val]) : key;
        return <PanelTab key={key} isSelected={tab === val && isPanelOpen} label={label} onClick={() => setTab(val)} />;
      })}
    </div>
  );
}

export function PanelToggle({ isEmbedded, isZen }) {
  const { panelPosition, isPanelOpen } = useSettings();
  return (
    !isEmbedded &&
    !isZen &&
    panelPosition === 'right' && (
      <button
        title="menu"
        className={cx('border-l border-muted px-2 py-0 text-foreground hover:opacity-50')}
        onClick={() => setIsPanelOpened(!isPanelOpen)}
      >
        <Bars3Icon className="w-6 h-6" />
      </button>
    )
  );
}
