import { useState, useEffect } from "react";
import { Box, Text, useInput, useStdout } from "ink";
import type { UnifiedRepo, CommandConfig } from "../types/index.ts";
import { getMarkdownLineCount, MarkdownRenderer } from "./MarkdownRenderer.tsx";

export function getMaxReadmeScroll(
  content: string | null,
  width: number,
  viewportHeight: number,
): number {
  if (!content) return 0;
  return Math.max(0, getMarkdownLineCount(content, width) - Math.max(0, viewportHeight));
}

export interface RepoDetailModalProps {
  repo: UnifiedRepo;
  readmeContent: string | null;
  readmeLoading: boolean;
  readmeError: string | null;
  scrollOffset: number;
  commands?: CommandConfig[];
  onClose: () => void;
  onAction: (action: string) => void;
  onScroll: (offset: number) => void;
  onCommand?: (command: CommandConfig) => void;
}

/** GitHub's repository-size field is reported in kilobytes. */
export function formatGitHubSize(sizeKB: number): string {
  if (sizeKB < 1024) return `${sizeKB} KB`;
  if (sizeKB < 1024 * 1024) return `${(sizeKB / 1024).toFixed(1)} MB`;
  if (sizeKB < 1024 * 1024 * 1024) return `${(sizeKB / (1024 * 1024)).toFixed(1)} GB`;
  return `${(sizeKB / (1024 * 1024 * 1024)).toFixed(1)} TB`;
}

export function RepoDetailModal({
  repo,
  readmeContent,
  readmeLoading,
  readmeError,
  scrollOffset,
  commands = [],
  onClose,
  onAction,
  onScroll,
  onCommand,
}: RepoDetailModalProps) {
  const { stdout } = useStdout();
  const [dimensions, setDimensions] = useState({ width: 80, height: 24 });

  useEffect(() => {
    if (stdout) {
      const updateDimensions = () => {
        setDimensions({
          width: stdout.columns || 80,
          height: stdout.rows || 24,
        });
      };

      updateDimensions();
      stdout.on("resize", updateDimensions);
      return () => {
        stdout.off("resize", updateDimensions);
      };
    }
  }, [stdout]);

  const maxWidth = Math.max(1, Math.min(100, dimensions.width - 4));
  // The modal owns the terminal viewport; reserve only its two border rows.
  const maxHeight = Math.max(1, dimensions.height - 2);
  // Keep the fixed header/action/footer chrome inside the modal even on short
  // terminals; the README viewport is the part that yields space first.
  const readmeHeight = Math.max(1, maxHeight - 17);
  // Modal border/padding consumes eight columns before README text begins.
  const readmeWidth = Math.max(1, maxWidth - 8);

  useInput((input, key) => {
    if (key.escape) {
      onClose();
      return;
    }

    // Scroll always targets the README — actions use letter keys, so there
    // is no conflict and no need to "focus" a section first.
    if (input === "j" || key.downArrow) {
      if (readmeContent) {
        const max = getMaxReadmeScroll(readmeContent, readmeWidth, readmeHeight - 2);
        onScroll(Math.min(max, scrollOffset + 1));
      }
      return;
    }

    if (input === "k" || key.upArrow) {
      if (readmeContent) {
        onScroll(Math.max(0, scrollOffset - 1));
      }
      return;
    }

    if (key.pageDown || input === " ") {
      if (readmeContent) {
        const max = getMaxReadmeScroll(readmeContent, readmeWidth, readmeHeight - 2);
        onScroll(Math.min(max, scrollOffset + 10));
      }
      return;
    }

    if (key.pageUp) {
      if (readmeContent) {
        onScroll(Math.max(0, scrollOffset - 10));
      }
      return;
    }

    if (input === "g") {
      onScroll(0);
      return;
    }

    if (input === "G") {
      if (readmeContent) onScroll(getMaxReadmeScroll(readmeContent, readmeWidth, readmeHeight - 2));
      return;
    }

    if (key.return) {
      if (canClone) {
        onAction("clone");
      } else {
        onAction("primary");
      }
      return;
    }

    switch (input) {
      case "p":
        if (hasLocal) onAction("push");
        return;
      case "P":
        if (hasLocal) onAction("pull");
        return;
      case "f":
        if (hasLocal) onAction("fetch");
        return;
      case "o":
        onAction("browser");
        return;
      case "d":
        if (hasLocal) onAction("editor");
        return;
    }

    if (onCommand && commands.length > 0) {
      const command = commands.find((c) => c.key === input);
      if (command) onCommand(command);
    }
  });

  const githubInfo = repo.github;
  const localInfo = repo.local;
  const status = localInfo?.status;

  // Derive local path from multiple sources for robustness
  const localPath = repo.localPath || localInfo?.path;

  // Determine if we have local and remote presence
  const hasLocal = !!(localPath || repo.source === "local" || repo.source === "both");
  const hasRemote = !!(githubInfo?.htmlUrl || repo.source === "github" || repo.source === "both");

  // Action availability based on state
  const canClone = !hasLocal && hasRemote;
  const canPush = hasLocal && !!(status?.isAhead && status.unpushedCommits > 0);
  const canPull = hasLocal && !!(status?.hasRemote && status.unpulledCommits > 0);
  const canFetch = hasLocal && !!status?.hasRemote;
  const canOpenBrowser = hasRemote && !!githubInfo?.htmlUrl;
  const canOpenEditor = hasLocal && !!localPath;
  const footerWidth = Math.max(1, maxWidth - 4);
  const footerMetadata = [
    githubInfo?.topics && githubInfo.topics.length > 0 ? `Topics: ${githubInfo.topics.join(", ")}` : null,
    githubInfo?.license ? `License: ${githubInfo.license}` : null,
    githubInfo?.language ? `Language: ${githubInfo.language}` : null,
  ].filter((value): value is string => value !== null).join("  ");
  const footerMetadataDisplay = footerMetadata.length > footerWidth
    ? `${footerMetadata.slice(0, Math.max(0, footerWidth - 1))}…`
    : footerMetadata;


  return (
    <Box
      flexDirection="column"
      borderStyle="round"
      borderColor="cyan"
      paddingX={1}
      paddingY={0}
      width={maxWidth}
      height={maxHeight}
    >
      {/* Header */}
      <Box justifyContent="center">
        <Text bold color="cyan">
          {githubInfo?.fullName || repo.name}
        </Text>
      </Box>

      {/* Repository Info */}
      <Box flexDirection="column">
        <Box justifyContent="space-between" flexDirection="row" gap={2}>
          <Box flexDirection="column" gap={1}>
            {githubInfo && (
              <Box gap={1}>
                <Text color="cyan">☁ GitHub</Text>
                <Text color="magenta">{githubInfo.fullName}</Text>
              </Box>
            )}
            {localInfo && (
              <Box gap={1}>
                <Text color="green">💻 Local</Text>
                <Text color="blue">{localInfo.path}</Text>
              </Box>
            )}
          </Box>
          <Box flexDirection="column" gap={1} alignItems="flex-end">
            {githubInfo && (
              <Box gap={1}>
                {githubInfo.isPrivate && <Text color="yellow">🔒 Private</Text>}
                <Text color="yellow">★{githubInfo.stargazersCount || 0}</Text>
                <Text color="yellow">🍴{githubInfo.forksCount || 0}</Text>
              </Box>
            )}
          </Box>
        </Box>
      </Box>

      {/* Status Section */}
      {status && (
        <Box
          borderStyle="round"
          borderColor="gray"
          paddingX={1}
          paddingY={0}
          marginBottom={0}
          flexDirection="column"
          gap={0}
        >
          <Box gap={2} flexWrap="wrap">
            <Text color={status.isDirty ? "red" : "green"}>
              {status.isDirty ? "● Dirty" : "○ Clean"}
            </Text>
            <Text color="magenta">⎇ {status.currentBranch}</Text>
            <Text color="yellow">{status.modifiedCount} modified</Text>
            {localInfo?.type === "git-submodule" && (
              <Text color="yellow">(submodule)</Text>
            )}
            {githubInfo && (
              <Text color="gray">{formatGitHubSize(githubInfo.size)}</Text>
            )}
            {status.stagedCount > 0 && (
              <Text color="green">{status.stagedCount} staged</Text>
            )}
            {status.untrackedCount > 0 && (
              <Text color="gray">{status.untrackedCount} untracked</Text>
            )}
          </Box>
          <Box gap={2} flexWrap="wrap">
            <Text color={status.isAhead ? "yellow" : "gray"}>
              ↑ {status.unpushedCommits} to push
            </Text>
            <Text color={status.isBehind ? "yellow" : "gray"}>
              ↓ {status.unpulledCommits} to pull
            </Text>
          </Box>
        </Box>
      )}

      {/* Actions Section */}
      <Box
        borderStyle="round"
        borderColor="gray"
        paddingX={1}
        paddingY={0}
        marginBottom={0}
        flexDirection="column"
        gap={0}
      >
        <Box flexDirection="column" gap={0}>
          <Box gap={3}>
          <Box gap={1}>
            <Text color={canClone ? "yellow" : "gray"}>[Enter]</Text>
            <Text dimColor={!canClone}>Clone</Text>
            {canClone && <Text dimColor> (picker)</Text>}
          </Box>
          <Box gap={1}>
            <Text color={canPush ? "yellow" : "gray"}>[p]</Text>
            <Text dimColor={!canPush}>Push</Text>
          </Box>
          <Box gap={1}>
            <Text color={canPull ? "yellow" : "gray"}>[P]</Text>
            <Text dimColor={!canPull}>Pull</Text>
          </Box>
          <Box gap={1}>
            <Text color={canFetch ? "yellow" : "gray"}>[f]</Text>
            <Text dimColor={!canFetch}>Fetch</Text>
          </Box>
          </Box>
          <Box gap={3}>
          <Box gap={1}>
            <Text color={canOpenBrowser ? "yellow" : "gray"}>[o]</Text>
            <Text dimColor={!canOpenBrowser}>Open Browser</Text>
          </Box>
          <Box gap={1}>
            <Text color={canOpenEditor ? "yellow" : "gray"}>[d]</Text>
            <Text dimColor={!canOpenEditor}>Editor</Text>
          </Box>
          </Box>
        </Box>

        {!hasLocal && (
          <Box>
            <Text dimColor>Clone to enable push, pull, fetch, and editor.</Text>
          </Box>
        )}
        {commands.length > 0 && (
          <Box gap={1} flexWrap="wrap">
            {commands.slice(0, 5).map((cmd) => (
              <Box key={cmd.key} gap={0}>
                <Text color="magenta">[{cmd.key}]</Text>
                <Text>{cmd.name}</Text>
                <Text> </Text>
              </Box>
            ))}
            {commands.length > 5 && (
              <Text dimColor>+{commands.length - 5} more</Text>
            )}
          </Box>
        )}
      </Box>

      {/* README Section */}
      <Box
        flexDirection="column"
        flexGrow={1}
        borderStyle="round"
        borderColor="gray"
        paddingX={1}
        paddingY={0}
        minHeight={readmeHeight}
      >
        <Box>
          <Text bold color="cyan">
            README.md
          </Text>
        </Box>

        <Box flexDirection="column" flexGrow={1}>
          {readmeLoading && (
            <Text color="yellow">Loading README...</Text>
          )}

          {readmeError && (
            <Text color="red">Error: {readmeError}</Text>
          )}

          {readmeContent && !readmeLoading && !readmeError && (
            <MarkdownRenderer
              content={readmeContent}
              width={readmeWidth}
              maxHeight={readmeHeight - 2}
              scrollOffset={scrollOffset}
            />
          )}

          {!readmeContent && !readmeLoading && !readmeError && (
            <Text dimColor>No README available</Text>
          )}
        </Box>
      </Box>

      {/* Footer */}
      <Box flexDirection="column">
        {footerMetadataDisplay && <Text color="blue">{footerMetadataDisplay}</Text>}
        <Text dimColor>[Esc] Close  [j/k ↑↓] Scroll  [g/G] Top/Bottom</Text>
      </Box>
    </Box>
  );
}
