import { Box, Text } from "ink";
import type { UnifiedRepo } from "../types/index.ts";
import { palette } from "../ui/theme.ts";

interface UnifiedProjectItemProps {
  repo: UnifiedRepo;
  isSelected: boolean;
  isCursor: boolean;
}

// Nerd Font icons using Unicode escape sequences
// Reference: https://github.com/ryanoasis/nerd-fonts/wiki/Glyph-Sets-and-Code-Points
export const NF = {
  // Devicons (e700-e8ef)
  github: '\ue709',       // nf-dev-github_badge
  git_branch: '\ue725',   // nf-dev-git_branch
  python: '\ue73c',       // nf-dev-python
  rust: '\ue7a8',         // nf-dev-rust
  ruby: '\ue791',         // nf-dev-ruby
  java: '\ue738',         // nf-dev-java
  html5: '\ue736',        // nf-dev-html5
  css3: '\ue749',         // nf-dev-css3
  terminal: '\ue795',     // nf-dev-terminal
  php: '\ue73d',          // nf-dev-php
  swift: '\ue755',        // nf-dev-swift
  scala: '\ue737',        // nf-dev-scala
  haskell: '\ue777',      // nf-dev-haskell
  erlang: '\ue7b1',       // nf-dev-erlang
  clojure: '\ue768',      // nf-dev-clojure
  perl: '\ue769',         // nf-dev-perl
  docker: '\ue7b0',       // nf-dev-docker
  markdown: '\ue73e',     // nf-dev-markdown
  vim: '\ue7c5',          // nf-dev-vim
  react: '\ue7ba',        // nf-dev-react
  
  // Font Awesome (f000-f2ff)
  star: '\uf005',         // nf-fa-star
  star_empty: '\uf006',   // nf-fa-star_o
  lock: '\uf023',         // nf-fa-lock  
  unlock: '\uf09c',       // nf-fa-unlock_alt
  folder: '\uf07b',       // nf-fa-folder
  folder_open: '\uf07c',  // nf-fa-folder_open
  cloud: '\uf0c2',        // nf-fa-cloud
  check: '\uf00c',        // nf-fa-check
  times: '\uf00d',        // nf-fa-times
  circle: '\uf111',       // nf-fa-circle
  circle_o: '\uf10c',     // nf-fa-circle_o
  arrow_up: '\uf062',     // nf-fa-arrow_up
  arrow_down: '\uf063',   // nf-fa-arrow_down
  globe: '\uf0ac',        // nf-fa-globe
  file: '\uf15b',         // nf-fa-file
  code: '\uf121',         // nf-fa-code
  clock: '\uf017',        // nf-fa-clock_o
  database: '\uf1c0',     // nf-fa-database
  
  // Octicons (f400-f533)
  git_branch_oct: '\uf418', // nf-oct-git_branch
  repo: '\uf401',           // nf-oct-repo
  repo_forked: '\uf402',    // nf-oct-repo_forked
  git_commit: '\uf417',     // nf-oct-git_commit
  sync: '\uf46a',           // nf-oct-sync
  alert: '\uf421',          // nf-oct-alert (triangle warning)
  x: '\uf467',              // nf-oct-x (x mark)
  issue: '\uf41b',          // nf-oct-issue_opened
  
  // Seti-UI + Custom (e5fa-e6b7)
  typescript: '\ue628',   // nf-seti-typescript
  javascript: '\ue60c',   // nf-seti-javascript
  go: '\ue627',           // nf-seti-go2
  json: '\ue60b',         // nf-seti-json
  lua: '\ue620',          // nf-seti-lua
  vue: '\ue6a0',          // nf-seti-vue
  
  // Powerline symbols
  branch: '\ue0a0',       // nf-pl-branch
  
  // Custom/MDI
  source_branch: '\uf062c', // source branch
};

// Column widths - must match header widths exactly
// Note: Icons often display wider than their character count
export const COL = {
  sel: 4,         // "[ ] " selection with trailing space
  status: 10,     // status: "⚠  warn" or "✓  ok"
  name: 22,       // repo name
  branch: 14,     // branch name
  sync: 10,       // sync status
  lang: 3,        // language icon only
  stars: 5,       // star count
  forks: 5,       // fork count  
  updated: 8,     // last updated (shorter)
  size: 6,        // repo size
};

// Map language names to Nerd Font icons
const LANG_ICONS: Record<string, string> = {
  'typescript': NF.typescript,
  'javascript': NF.javascript,
  'python': NF.python,
  'rust': NF.rust,
  'go': NF.go,
  'ruby': NF.ruby,
  'java': NF.java,
  'php': NF.php,
  'swift': NF.swift,
  'scala': NF.scala,
  'html': NF.html5,
  'css': NF.css3,
  'vue': NF.vue,
  'haskell': NF.haskell,
  'erlang': NF.erlang,
  'clojure': NF.clojure,
  'lua': NF.lua,
  'perl': NF.perl,
  'shell': NF.terminal,
  'bash': NF.terminal,
  'dockerfile': NF.docker,
  'markdown': NF.markdown,
  'vim': NF.vim,
  'viml': NF.vim,
  'jsx': NF.react,
  'tsx': NF.react,
};

/**
 * Get Nerd Font icon for language
 */
function getLangIcon(language: string | null): string {
  if (!language) return ' ';
  return LANG_ICONS[language.toLowerCase()] || NF.code;
}

/**
 * Format size - compact
 */
function formatSize(sizeKB: number | undefined): string {
  if (!sizeKB) return '—'.padStart(COL.size);
  if (sizeKB < 1024) return `${sizeKB}K`.padStart(COL.size);
  if (sizeKB < 1024 * 1024) return `${Math.round(sizeKB / 1024)}M`.padStart(COL.size);
  return `${(sizeKB / 1024 / 1024).toFixed(0)}G`.padStart(COL.size);
}

/**
 * Format count (stars/forks) - compact
 */
function formatCount(count: number | undefined): string {
  if (count === undefined || count === 0) return '—';
  if (count >= 1000) return `${(count / 1000).toFixed(0)}k`;
  return String(count);
}

/**
 * Format relative date - uses lastModified for non-git/empty repos
 */
function formatDate(repo: UnifiedRepo): string {
  // Try git commit date first, then lastModified for non-git/empty repos, then GitHub date
  const date = repo.local?.status?.lastLocalCommit 
    || repo.local?.lastModified 
    || repo.github?.pushedAt;
  
  if (!date) return '—'.padStart(COL.updated);
  
  const dateObj = typeof date === 'string' ? new Date(date) : date;
  if (isNaN(dateObj.getTime())) return '—'.padStart(COL.updated);
  
  const days = Math.floor((Date.now() - dateObj.getTime()) / (1000 * 60 * 60 * 24));
  
  let text: string;
  if (days === 0) text = 'today';
  else if (days === 1) text = '1d';
  else if (days < 7) text = `${days}d`;
  else if (days < 30) text = `${Math.floor(days / 7)}w`;
  else if (days < 365) text = `${Math.floor(days / 30)}mo`;
  else text = `${Math.floor(days / 365)}y`;
  
  return text.padStart(COL.updated);
}

/**
 * Format sync status with icon - compact
 */
function formatSync(repo: UnifiedRepo): { text: string; color: string } {
  const status = repo.local?.status;
  if (!status) return { text: '—'.padEnd(COL.sync), color: palette.text.muted };
  if (!status.hasRemote) return { text: '—'.padEnd(COL.sync), color: palette.text.muted };  // Status column shows "local"
  
  const ahead = status.isAhead && status.unpushedCommits > 0;
  const behind = status.isBehind && status.unpulledCommits > 0;
  
  if (ahead && behind) {
    return { text: `↑${status.unpushedCommits}↓${status.unpulledCommits}`.padEnd(COL.sync), color: palette.badge.dirty.fg };
  }
  if (ahead) {
    return { text: `↑${status.unpushedCommits} push`.padEnd(COL.sync), color: palette.badge.push.fg };
  }
  if (behind) {
    return { text: `↓${status.unpulledCommits} pull`.padEnd(COL.sync), color: palette.badge.pull.fg };
  }
  return { text: `${NF.check} synced`.padEnd(COL.sync), color: palette.badge.ok.fg };
}

/**
 * Truncate string to max length
 */
function truncate(str: string, max: number): string {
  if (str.length <= max) return str;
  return str.slice(0, max - 1) + '…';
}

/**
 * Health status for a repo - determines what needs attention
 * Priority order (highest first):
 * 1. NO_GIT - folder has no git setup at all
 * 2. NO_COMMITS - git init but no commits
 * 3. NO_REMOTE - has commits but no remote configured
 * 4. DIRTY - has uncommitted changes
 * 5. UNSYNCED - ahead/behind remote
 * 6. OK - everything is good
 */
type RepoHealth = 'NO_GIT' | 'NO_COMMITS' | 'NO_REMOTE' | 'DIRTY' | 'UNSYNCED' | 'NOT_CLONED' | 'OK';

interface HealthInfo {
  status: RepoHealth;
  icon: string;
  label: string;
  color: string;
  bgColor?: string;
}

function getRepoHealth(repo: UnifiedRepo): HealthInfo {
  const status = repo.local?.status;
  const isNonGit = repo.local?.type === 'non-git';
  
  // Not cloned (GitHub only)
  if (repo.source === 'github') {
    return {
      status: 'NOT_CLONED',
      icon: NF.cloud,
      label: '',
      color: palette.text.muted,
    };
  }
  
  // No git at all (has package.json etc but no .git)
  if (isNonGit) {
    return {
      status: 'NO_GIT',
      icon: NF.alert,
      label: 'init',
      color: palette.badge.local.fg,
    };
  }
  
  // Git repo but no commits
  if (status && !status.hasCommits) {
    return {
      status: 'NO_COMMITS',
      icon: NF.alert,
      label: 'empty',
      color: palette.badge.local.fg,
    };
  }
  
  // Has commits but no remote
  if (status && !status.hasRemote) {
    return {
      status: 'NO_REMOTE',
      icon: NF.alert,
      label: 'local',
      color: palette.badge.local.fg,
    };
  }
  
  // Has dirty working tree
  if (status?.isDirty) {
    return {
      status: 'DIRTY',
      icon: NF.circle,
      label: '',
      color: palette.badge.dirty.fg,
    };
  }
  
  // Out of sync with remote
  if (status?.isOutOfSync) {
    return {
      status: 'UNSYNCED',
      icon: NF.sync,
      label: '',
      color: status.isAhead ? palette.badge.push.fg : palette.badge.pull.fg,
    };
  }
  
  // All good
  return {
    status: 'OK',
    icon: NF.check,
    label: '',
    color: palette.badge.ok.fg,
  };
}

/**
 * Get source indicator icon (local/github/both)
 */
function getSourceIcon(repo: UnifiedRepo): { icon: string; color: string } {
  const isPrivate = repo.github?.isPrivate ?? false;
  
  if (isPrivate) {
    return { icon: NF.lock, color: palette.text.warning };
  }
  
  if (repo.source === 'github') {
    return { icon: NF.cloud, color: palette.text.muted };
  } else if (repo.source === 'local') {
    return { icon: NF.folder, color: palette.text.info };
  } else {
    return { icon: NF.github, color: palette.text.success };
  }
}

export function UnifiedProjectItem({ repo, isSelected, isCursor }: UnifiedProjectItemProps) {
  const bg = isCursor ? palette.bg.accent : isSelected ? palette.bg.surface : undefined;
  const fg = isCursor || isSelected ? palette.text.primary : undefined;
  
  // Get health status (most important info)
  const health = getRepoHealth(repo);
  
  // Source icon (local/github/both)
  const src = getSourceIcon(repo);
  
  // Language icon  
  const langIcon = getLangIcon(repo.github?.language || null);
  
  // Branch
  const branch = repo.local?.status?.currentBranch;
  const branchText = branch ? truncate(branch, COL.branch - 2) : '—';
  
  // Sync status
  const sync = formatSync(repo);
  
  // Date (simple string now, no color)
  const dateText = formatDate(repo);
  
  // Selection checkbox (only for local repos)
  const checkbox = repo.source === 'github' ? '  '
    : isSelected ? '[x]' : '[ ]';
  const checkColor = isSelected ? palette.text.success : fg;

  return (
    <Box>
      {/* Cursor */}
      <Text color={fg} backgroundColor={bg}>
        {isCursor ? '>' : ' '}
      </Text>
      
      {/* Selection "[x] " or "[ ] " */}
      <Text color={checkColor} backgroundColor={bg}>
        {checkbox.padEnd(COL.sel)}
      </Text>
      
      {/* STATUS - icon + optional short label */}
      <Text color={isCursor ? fg : health.color} backgroundColor={bg} bold={isCursor || isSelected}>
        {`${health.label ? `${health.icon} ${health.label} ` : `${health.icon}   `}`.padEnd(COL.status)}
      </Text>
      
      {/* Source icon (local/github/both/private) */}
      <Text color={isCursor ? fg : src.color} backgroundColor={bg}>
        {src.icon}
      </Text>
      <Text backgroundColor={bg}>{' '}</Text>
      
      {/* Name */}
      <Text color={fg || palette.text.primary} backgroundColor={bg} bold={isCursor || isSelected}>
        {truncate(repo.name, COL.name - 2).padEnd(COL.name - 2)}
      </Text>
      
      {/* Gap */}
      <Text backgroundColor={bg}>{'  '}</Text>
      
      {/* Branch */}
      <Text color={isCursor ? fg : palette.text.info} backgroundColor={bg}>
        {branchText.padEnd(COL.branch)}
      </Text>
      
      {/* Gap */}
      <Text backgroundColor={bg}>{'  '}</Text>
      
      {/* Sync status */}
      <Text color={isCursor ? fg : sync.color} backgroundColor={bg}>
        {sync.text}
      </Text>
      
      {/* Gap */}
      <Text backgroundColor={bg}>{'  '}</Text>
      
      {/* Language icon */}
      <Text color={isCursor ? fg : palette.text.info} backgroundColor={bg}>
        {langIcon.padStart(COL.lang)}
      </Text>
      
      {/* Gap */}
      <Text backgroundColor={bg}>{'  '}</Text>
      
      {/* Stars */}
      <Text color={isCursor ? fg : 'yellow'} backgroundColor={bg}>
        {formatCount(repo.github?.stargazersCount).padStart(COL.stars)}
      </Text>
      
      {/* Gap */}
      <Text backgroundColor={bg}>{'  '}</Text>
      
      {/* Forks */}
      <Text color={isCursor ? fg : palette.text.muted} backgroundColor={bg}>
        {formatCount(repo.github?.forksCount).padStart(COL.forks)}
      </Text>
      
      {/* Gap */}
      <Text backgroundColor={bg}>{'  '}</Text>
      
       {/* Updated date */}
      <Text color={isCursor ? fg : palette.text.muted} backgroundColor={bg}>
        {dateText}
      </Text>
      
      {/* Gap */}
      <Text backgroundColor={bg}>{'  '}</Text>
      
      {/* Size */}
      <Text color={isCursor ? fg : palette.text.muted} backgroundColor={bg}>
        {formatSize(repo.github?.size)}
      </Text>
    </Box>
  );
}
