import { useState, useRef, useEffect } from 'react';
import { supabase } from '../supabaseClient';

interface TerminalEmulatorProps {
  onOpenWindow: (windowId: string) => void;
  onClose: () => void;
}

// Custom helper to format result rows as a clean ASCII text table
function formatAsciiTable(columns: string[], rows: any[]): string[] {
  if (columns.length === 0 || rows.length === 0) {
    return ['Empty result set.'];
  }
  
  // Calculate column widths
  const widths: Record<string, number> = {};
  columns.forEach(col => {
    widths[col] = col.length;
  });
  
  rows.forEach(row => {
    columns.forEach(col => {
      const valStr = row[col] !== null && row[col] !== undefined ? String(row[col]) : 'NULL';
      if (valStr.length > (widths[col] || 0)) {
        widths[col] = valStr.length;
      }
    });
  });

  // Build grid components
  const separator = '+' + columns.map(col => '-'.repeat(widths[col] + 2)).join('+') + '+';
  const header = '|' + columns.map(col => ` ${col.padEnd(widths[col])} `).join('|') + '|';
  
  const lines: string[] = [separator, header, separator];
  
  rows.forEach(row => {
    const rowLine = '|' + columns.map(col => {
      const valStr = row[col] !== null && row[col] !== undefined ? String(row[col]) : 'NULL';
      return ` ${valStr.padEnd(widths[col])} `;
    }).join('|') + '|';
    lines.push(rowLine);
  });
  
  lines.push(separator);
  return lines;
}

export default function TerminalEmulator({ onOpenWindow, onClose }: TerminalEmulatorProps) {
  const [history, setHistory] = useState<string[]>([
    'AlgoSpaced OS [Version 1.0.24]',
    '(c) Retro Arcade Systems. All rights reserved.',
    '',
    'Type "help" for a list of available commands.',
    ''
  ]);
  const [input, setInput] = useState('');
  const containerRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (containerRef.current) {
      containerRef.current.scrollTop = containerRef.current.scrollHeight;
    }
  }, [history]);

  // Tokenize inputs while respecting single/double quoted strings
  const tokenize = (cmd: string): { command: string; args: string[] } => {
    const trimmed = cmd.trim();
    const regex = /[^\s"']+|"([^"]*)"|'([^']*)'/g;
    const args: string[] = [];
    let match;
    while ((match = regex.exec(trimmed)) !== null) {
      args.push(match[1] || match[2] || match[0]);
    }
    return {
      command: args[0]?.toLowerCase() || '',
      args: args.slice(1)
    };
  };

  const handleCommand = async (cmd: string) => {
    const trimmed = cmd.trim();
    if (trimmed === '') {
      setHistory(prev => [...prev, '$']);
      return;
    }

    const { command, args } = tokenize(trimmed);
    let output: string[] = [`$ ${trimmed}`];

    switch (command) {
      case 'help':
        output.push(
          'Available commands:',
          '  help         - Display this documentation',
          '  streak       - Retrieve your active Leitner combo streak metrics',
          '  sync         - Run google drive file import sync',
          '  reviews      - Fetch Leetcode numbers due for daily review',
          '  python play  - Open Daily Python Challenge window',
          '  db init      - Initialize SQL session and open playground window',
          '  db status    - Check active SQL session objectives',
          '  db query [Q] - Execute query and format results inside CLI',
          '  open         - Open window (usage: open queue | journey | system)',
          '  clear        - Clear terminal buffer',
          '  exit         - Close the terminal shell'
        );
        break;
      case 'clear':
        setHistory([]);
        return;
      case 'exit':
        output.push('Closing terminal session...');
        setTimeout(() => {
          onClose();
        }, 500);
        break;
      case 'open': {
        const target = args[0]?.toLowerCase();
        if (target === 'queue' || target === 'daily' || target === 'reviews') {
          onOpenWindow('queue');
          output.push('Launching Daily Queue window...');
        } else if (target === 'journey' || target === 'path' || target === 'map') {
          onOpenWindow('journey');
          output.push('Launching Journey Path window...');
        } else if (target === 'system' || target === 'computer' || target === 'sys') {
          onOpenWindow('computer');
          output.push('Launching System Information window...');
        } else if (target === 'python' || target === 'challenge') {
          onOpenWindow('python');
          output.push('Launching Daily Python Challenge window...');
        } else if (target === 'db' || target === 'mysql' || target === 'sql') {
          onOpenWindow('mysql');
          output.push('Launching MySQL Playground window...');
        } else {
          output.push('Usage: open [queue | journey | system | python | db]');
        }
        break;
      }
      case 'streak':
        output.push('Connecting to streak.sys database...');
        try {
          const { data: { session } } = await supabase.auth.getSession();
          if (!session) {
            output.push('Error: Unauthenticated session');
            break;
          }
          const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/api/streak`, {
            headers: { 'Authorization': `Bearer ${session.access_token}` }
          });
          if (res.ok) {
            const data = await res.json();
            output.push(
              'Database Response:',
              `  Active Streak:  ${data.current_streak} days`,
              `  Max Combo:      ${data.longest_streak} days`,
              `  Last Activity:  ${data.last_active_date ? new Date(data.last_active_date).toLocaleDateString() : 'N/A'}`
            );
          } else {
            output.push('Error: Failed to query database endpoint');
          }
        } catch {
          output.push('Error: Connection timed out');
        }
        break;
      case 'sync':
        output.push('Initializing Google Drive synchronization sync.exe...');
        try {
          const { data: { session } } = await supabase.auth.getSession();
          if (!session) {
            output.push('Error: Unauthenticated session');
            break;
          }
          const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/api/sync`, {
            method: 'POST',
            headers: { 'Authorization': `Bearer ${session.access_token}` }
          });
          if (res.ok) {
            const data = await res.json();
            output.push(`Sync Result: ${data.message}`);
          } else {
            output.push('Error: Sync command failed at backend host');
          }
        } catch {
          output.push('Error: Cloud host unreachable');
        }
        break;
      case 'reviews':
        output.push('Querying leitner_cards partition...');
        try {
          const { data: { session } } = await supabase.auth.getSession();
          if (!session) {
            output.push('Error: Unauthenticated session');
            break;
          }
          const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/api/reviews/due`, {
            headers: { 'Authorization': `Bearer ${session.access_token}` }
          });
          if (res.ok) {
            const data = await res.json();
            if (data.length === 0) {
              output.push('Queue status: CLEAR! 0 cards due.');
            } else {
              output.push(
                `Queue status: ${data.length} card(s) due:`,
                ...data.map((r: any) => `  - LeetCode ${r.problems?.problem_number}: ${r.problems?.name} (Box ${r.box_level})`)
              );
            }
          } else {
            output.push('Error: Failed to fetch due items');
          }
        } catch {
          output.push('Error: Database connection lost');
        }
        break;

      case 'python': {
        const subCommand = args[0]?.toLowerCase();
        if (subCommand === 'play') {
          output.push('Launching Daily Python Challenge window...');
          onOpenWindow('python');
        } else {
          output.push('Usage: python play');
        }
        break;
      }

      case 'db': {
        const subCommand = args[0]?.toLowerCase();
        if (subCommand === 'init') {
          output.push('Initializing MySQL Playground and launching window...');
          onOpenWindow('mysql');
          try {
            const { data: { session } } = await supabase.auth.getSession();
            if (!session) {
              output.push('Error: Unauthenticated session');
              break;
            }
            const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/api/challenges/mysql/init`, {
              method: 'POST',
              headers: { 'Authorization': `Bearer ${session.access_token}` }
            });
            if (res.ok) {
              const data = await res.json();
              output.push(
                `Database Session Created: "${data.title}"`,
                `Objective: ${data.objective}`
              );
            } else {
              output.push('Error: Failed to initialize DB session on backend host.');
            }
          } catch {
            output.push('Error: Server connection lost.');
          }
        } else if (subCommand === 'status') {
          output.push('Fetching SQL playground status...');
          onOpenWindow('mysql');
          try {
            const { data: { session } } = await supabase.auth.getSession();
            if (!session) {
              output.push('Error: Unauthenticated session');
              break;
            }
            const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/api/challenges/mysql/status`, {
              headers: { 'Authorization': `Bearer ${session.access_token}` }
            });
            if (res.ok) {
              const data = await res.json();
              if (data.active) {
                output.push(
                  `Active SQL Challenge: "${data.title}"`,
                  `Objective: ${data.objective}`,
                  `Status: ${data.completed ? 'COMPLETED (Done)' : 'IN PROGRESS'}`
                );
              } else {
                output.push(data.message);
              }
            } else {
              output.push('Error: Failed to fetch DB status.');
            }
          } catch {
            output.push('Error: Server timed out.');
          }
        } else if (subCommand === 'query') {
          // Parse SQL query which resides in the remaining input
          const sqlIdx = trimmed.toLowerCase().indexOf('query');
          const sql = sqlIdx !== -1 ? trimmed.substring(sqlIdx + 5).trim().replace(/^["']|["']$/g, '') : '';
          
          if (!sql) {
            output.push('Usage: db query [SQL Statement] - Remember to wrap query in double quotes.');
            break;
          }
          
          output.push(`Running query: ${sql}`);
          onOpenWindow('mysql');
          
          try {
            const { data: { session } } = await supabase.auth.getSession();
            if (!session) {
              output.push('Error: Unauthenticated session');
              break;
            }
            const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/api/challenges/mysql/query`, {
              method: 'POST',
              headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${session.access_token}`
              },
              body: JSON.stringify({ query: sql })
            });
            if (res.ok) {
              const data = await res.json();
              if (data.success) {
                output.push(
                  `Query OK. Affected ${data.rows_affected} rows.`,
                  ...formatAsciiTable(data.columns, data.rows)
                );
                if (data.is_correct) {
                  output.push('OBJECTIVE ACHIEVED! Congratulations.');
                }
              } else {
                output.push(`SQL Error: ${data.error}`);
              }
            } else {
              output.push('Error: SQL execution failed.');
            }
          } catch {
            output.push('Error: Database server unreachable.');
          }
        } else {
          output.push('Usage: db init | db status | db query "SELECT..."');
        }
        break;
      }

      default:
        output.push(`Command not recognized: "${command}". Type "help" for a list of available actions.`);
    }

    setHistory(prev => [...prev, ...output, '']);
  };

  return (
    <div className="w-full h-full bg-[#1E293B] text-[#4ADE80] font-code-mono p-4 flex flex-col overflow-hidden text-xs md:text-sm select-text">
      <div ref={containerRef} className="flex-1 overflow-y-auto mb-2 custom-scrollbar space-y-1">
        {history.map((line, idx) => (
          <div key={idx} className="whitespace-pre-wrap leading-relaxed min-h-[1.2em]">
            {line}
          </div>
        ))}
      </div>
      <form
        onSubmit={(e) => {
          e.preventDefault();
          handleCommand(input);
          setInput('');
        }}
        className="flex items-center gap-1.5 border-t border-slate-700 pt-2 shrink-0 select-none"
      >
        <span className="font-bold text-[#ffcc00]">$</span>
        <input
          type="text"
          value={input}
          onChange={(e) => setInput(e.target.value)}
          className="flex-1 bg-transparent text-[#4ADE80] outline-none border-none p-0 focus:ring-0 font-code-mono text-xs md:text-sm"
          autoFocus
          placeholder="Type command..."
        />
      </form>
    </div>
  );
}
