import { useEffect, useRef } from 'react'
import {
  Button,
  Textarea,
  Body1,
  Caption1,
  makeStyles,
  mergeClasses,
  tokens,
  shorthands
} from '@fluentui/react-components'
import { PlayRegular, DismissRegular, DeleteRegular } from '@fluentui/react-icons'
import { useSettings } from '../store/settings'
import { ScreenHeader, useScreenStyles } from '../components/ui/Screen'
import { EmptyState } from '../components/ui/EmptyState'
import { SPACE } from '../components/ui/tokens'
import { useTerminalRun, type LineKind } from './useTerminalRun'

const useStyles = makeStyles({
  // Fills the `fill` shell (L161); the log <pre> below is the screen's scroller.
  root: { display: 'flex', flexDirection: 'column', gap: SPACE.section, flexGrow: 1, minHeight: 0 },
  gate: {
    display: 'flex',
    flexDirection: 'column',
    alignItems: 'flex-start',
    gap: '8px',
    // List-row padding tier (UI3): cozy on both axes (was 12/14).
    padding: SPACE.cozy,
    backgroundColor: tokens.colorStatusWarningBackground1,
    color: tokens.colorStatusWarningForeground1,
    ...shorthands.borderRadius(tokens.borderRadiusLarge)
  },
  inputRow: { display: 'flex', gap: '8px', alignItems: 'flex-end' },
  inputCol: { flexGrow: 1, display: 'flex', flexDirection: 'column', gap: '4px' },
  prefix: { color: tokens.colorNeutralForeground3, fontFamily: tokens.fontFamilyMonospace },
  buttons: { display: 'flex', gap: '8px' },
  log: {
    flexGrow: 1,
    minHeight: '160px',
    overflowY: 'auto',
    margin: 0,
    // List-row padding tier (UI3): cozy on both axes (was 12/14).
    padding: SPACE.cozy,
    backgroundColor: tokens.colorNeutralBackground1,
    color: tokens.colorNeutralForeground1,
    ...shorthands.borderRadius(tokens.borderRadiusLarge),
    border: `1px solid ${tokens.colorNeutralStroke2}`,
    fontFamily: tokens.fontFamilyMonospace,
    fontSize: tokens.fontSizeBase200,
    lineHeight: tokens.lineHeightBase300,
    whiteSpace: 'pre-wrap',
    wordBreak: 'break-word'
  },
  // Center the "no output yet" placeholder in the log box, so it reads as an
  // empty state rather than a stray line of text at the top (L117).
  logEmpty: { display: 'flex', alignItems: 'center', justifyContent: 'center' },
  cmd: { color: tokens.colorBrandForeground1, fontWeight: tokens.fontWeightSemibold },
  stderr: { color: tokens.colorPaletteRedForeground1 },
  sys: { color: tokens.colorNeutralForeground3 }
})

/**
 * Built-in yt-dlp terminal (Phase N): type raw yt-dlp args, run the bundled
 * binary, and watch its output stream. Gated on the enableCustomCommands consent
 * flag (enforced again in main -- see src/main/terminal.ts).
 */
export function TerminalView(): React.JSX.Element {
  const styles = useStyles()
  const screen = useScreenStyles()
  const enableCustomCommands = useSettings((s) => s.enableCustomCommands)
  const updateSettings = useSettings((s) => s.update)

  // View-model hook owns the run/stream/stop orchestration + IPC (L93/CC13).
  const { args, setArgs, lines, running, run, stop, clearLines } = useTerminalRun()
  const logRef = useRef<HTMLPreElement>(null)

  // Keep the log pinned to the latest output.
  useEffect(() => {
    if (logRef.current) logRef.current.scrollTop = logRef.current.scrollHeight
  }, [lines])

  const lineClass = (kind: LineKind): string | undefined =>
    kind === 'cmd'
      ? styles.cmd
      : kind === 'stderr'
        ? styles.stderr
        : kind === 'sys'
          ? styles.sys
          : undefined

  return (
    <div className={screen.fill}>
      <div className={mergeClasses(styles.root, screen.width)}>
        <ScreenHeader
          title="Terminal"
          description={
            <>
              Run the bundled yt-dlp with your own arguments. The URL goes in the args too, e.g.{' '}
              <code>-F https://youtu.be/…</code>. ffmpeg is wired up automatically.
            </>
          }
        />

        {!enableCustomCommands && (
          <div className={styles.gate}>
            <Body1>
              The terminal runs the bundled yt-dlp with your own arguments — part of custom
              commands, which can pass arbitrary yt-dlp flags. Turn it on to use the terminal.
            </Body1>
            <Button
              appearance="primary"
              size="small"
              onClick={() => updateSettings({ enableCustomCommands: true })}
            >
              Enable custom commands
            </Button>
          </div>
        )}

        <div className={styles.inputRow}>
          <div className={styles.inputCol}>
            <Caption1 className={styles.prefix}>yt-dlp</Caption1>
            <Textarea
              textarea={{ 'aria-label': 'yt-dlp arguments' }}
              value={args}
              onChange={(_, d) => setArgs(d.value)}
              onKeyDown={(e) => {
                if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {
                  e.preventDefault()
                  run()
                }
              }}
              placeholder="--version    (Ctrl+Enter to run)"
              resize="vertical"
              disabled={!enableCustomCommands}
            />
          </div>
          <div className={styles.buttons}>
            {running ? (
              <Button appearance="subtle" icon={<DismissRegular />} onClick={stop}>
                Stop
              </Button>
            ) : (
              <Button
                appearance="primary"
                icon={<PlayRegular />}
                onClick={run}
                disabled={!enableCustomCommands || !args.trim()}
              >
                Run
              </Button>
            )}
            <Button
              appearance="subtle"
              icon={<DeleteRegular />}
              onClick={clearLines}
              disabled={lines.length === 0}
              aria-label="Clear output"
            />
          </div>
        </div>

        <pre
          className={mergeClasses(styles.log, lines.length === 0 && styles.logEmpty)}
          ref={logRef}
        >
          {lines.length === 0 ? (
            <EmptyState
              compact
              message="No output yet."
              hint="Run yt-dlp above to see its output."
            />
          ) : (
            lines.map((l) => (
              <div key={l.id} className={lineClass(l.kind)}>
                {l.text}
              </div>
            ))
          )}
        </pre>
      </div>
    </div>
  )
}
