// 이 파일이 하는 일: SQL 채점 순수함수 gradeSql의 단위 테스트다(프론트 첫 테스트).
//
// 학습 포인트 — 왜 하필 gradeSql부터인가?
//   gradeSql은 학생의 SQL이 "통과/실패"인지를 결정하고, 서버는 그 판정을 그대로 믿고 저장한다.
//   즉 이 함수가 조용히 깨지면 학생의 진도가 잘못 기록된다 — 값어치가 큰데, 순수함수라
//   (입력만 주면 출력이 정해짐, DOM·네트워크 없음) 테스트하기도 가장 쉽다. 첫 테스트로 딱이다.
//   (runSql·runJs는 Web Worker·WASM에 의존해 jsdom에서 어려우니 이번 범위 밖 — 후속 티켓.)
//
// 실행: frontend/에서  npm test   (vitest run)
import { describe, it, expect } from 'vitest';
import { gradeSql } from './runSql';

// gradeSql(actual, expected)
//   actual   = { columns: [...], rows: [[...], ...] }   ← 학생 쿼리 실행 결과
//   expected = { expectedColumns, expectedRows, orderMatters }  ← 문제의 정답
const expected = (rows, orderMatters = false) => ({ expectedRows: rows, orderMatters });
const actual = (rows, columns = []) => ({ columns, rows });

describe('gradeSql', () => {
  it('행 개수가 다르면 오답(false)', () => {
    const res = gradeSql(actual([[1], [2]]), expected([[1], [2], [3]]));
    expect(res).toBe(false);
  });

  it('내용이 정확히 같으면 정답(true)', () => {
    const rows = [['김하늘', 3200], ['이준호', 4100]];
    expect(gradeSql(actual(rows), expected(rows, true))).toBe(true);
  });

  it('orderMatters=false: 순서가 달라도 값이 같으면 정답', () => {
    const res = gradeSql(
      actual([['이준호', 4100], ['김하늘', 3200]]),
      expected([['김하늘', 3200], ['이준호', 4100]], false),
    );
    expect(res).toBe(true);
  });

  it('orderMatters=true: 순서가 다르면 오답 (ORDER BY 문제)', () => {
    const res = gradeSql(
      actual([['이준호', 4100], ['김하늘', 3200]]),
      expected([['김하늘', 3200], ['이준호', 4100]], true),
    );
    expect(res).toBe(false);
  });

  it('orderMatters=true: 순서까지 같으면 정답', () => {
    const rows = [['서지민', 4500], ['이준호', 4100], ['한지우', 3800]];
    expect(gradeSql(actual(rows), expected(rows, true))).toBe(true);
  });

  it('컬럼명(별칭)은 채점에 영향 없음 — 값만 비교한다', () => {
    // 학생이 SELECT salary AS 연봉 처럼 별칭을 붙여 columns가 달라도, 값이 같으면 정답.
    const res = gradeSql(
      actual([['김하늘', 3200]], ['name', '연봉']),      // 학생 컬럼명
      expected([['김하늘', 3200]], false),                // 정답엔 컬럼명 비교 항목 없음
    );
    expect(res).toBe(true);
  });

  it('값이 하나라도 다르면 오답', () => {
    const res = gradeSql(
      actual([['김하늘', 3200]]),
      expected([['김하늘', 9999]], false),
    );
    expect(res).toBe(false);
  });

  it('빈 결과끼리는 정답(true)', () => {
    expect(gradeSql(actual([]), expected([], false))).toBe(true);
  });

  it('숫자와 문자열은 구분한다 (3200 ≠ "3200")', () => {
    const res = gradeSql(
      actual([[3200]]),
      expected([['3200']], false),
    );
    expect(res).toBe(false);
  });
});
