import type { Card, Rank, Suit } from './types';
import { buildDeck, makeCard } from './cards';
import {
  bestSplit,
  compareGroup,
  compareSplit,
  evalGroup,
  groupPoint,
  specialHand,
} from './handEval';

let pass = 0;
let fail = 0;
function check(label: string, cond: boolean) {
  if (cond) {
    pass++;
  } else {
    fail++;
    console.error('  ✗ FAIL:', label);
  }
}

function c(suit: Suit, rank: Rank): Card {
  return makeCard(suit, rank, true);
}
function g(a: Card, b: Card): [Card, Card] {
  return [a, b];
}

// 1) 牌库 32 张
const deck = buildDeck();
check('牌库共 32 张', deck.length === 32);
check(
  '红桃3 仅 1 张',
  deck.filter((x) => x.suit === 'heart' && x.rank === '3').length === 1,
);
check('大王 仅 1 张', deck.filter((x) => x.suit === 'joker').length === 1);
check('红Q 共 2 张', deck.filter((x) => x.rank === 'Q').length === 2);
check('8 共 4 张', deck.filter((x) => x.rank === '8').length === 4);

// 2) 牌型识别
check('丁皇 = 红3+大王', evalGroup(g(c('heart', '3'), c('joker', 'JOKER'))).name === '丁皇');
check('天牌 = 对红Q', evalGroup(g(c('heart', 'Q'), c('diamond', 'Q'))).name === '天牌');
check('地牌 = 对红2', evalGroup(g(c('heart', '2'), c('diamond', '2'))).name === '地牌');
check('人牌 = 对红8', evalGroup(g(c('heart', '8'), c('diamond', '8'))).name === '人牌');
check('和牌 = 对红4', evalGroup(g(c('heart', '4'), c('diamond', '4'))).name === '和牌');
check('梅十 = 对黑10', evalGroup(g(c('spade', '10'), c('club', '10'))).name === '梅十');
check('板凳 = 对黑4', evalGroup(g(c('spade', '4'), c('club', '4'))).name === '板凳');
check('长三 = 对黑6', evalGroup(g(c('spade', '6'), c('club', '6'))).name === '长三');
check('虎头 = 对黑J', evalGroup(g(c('spade', 'J'), c('club', 'J'))).name === '虎头');
check('苕十 = 对红10', evalGroup(g(c('heart', '10'), c('diamond', '10'))).name === '苕十');
check('猫猫 = 对红6', evalGroup(g(c('heart', '6'), c('diamond', '6'))).name === '猫猫');
check('膏药 = 对红7', evalGroup(g(c('heart', '7'), c('diamond', '7'))).name === '膏药');
check('对子 = 对黑8', evalGroup(g(c('spade', '8'), c('club', '8'))).name === '对子');
check('奶狗 = 红Q+黑9', evalGroup(g(c('heart', 'Q'), c('spade', '9'))).name === '奶狗');
check('天杠 = 红Q+8', evalGroup(g(c('heart', 'Q'), c('club', '8'))).name === '天杠');
check('地杠 = 红2+8', evalGroup(g(c('heart', '2'), c('club', '8'))).name === '地杠');
check('天关九 = 红Q+7', evalGroup(g(c('heart', 'Q'), c('spade', '7'))).name === '天关九');
check('地关九 = 红2+7', evalGroup(g(c('heart', '2'), c('spade', '7'))).name === '地关九');
check('灯笼九 = 红8+黑J', evalGroup(g(c('heart', '8'), c('spade', 'J'))).name === '灯笼九');
check('乌龙九 = 黑8+黑J', evalGroup(g(c('spade', '8'), c('club', 'J'))).name === '乌龙九');

// 3) 点数
check('地牌+黑5 = 7点', groupPoint(g(c('heart', '2'), c('spade', '5'))) === 7);
check('斧头+黑9 = 0点', groupPoint(g(c('spade', 'J'), c('club', '9'))) === 0);
check('梅十+红十 = 0点', groupPoint(g(c('spade', '10'), c('heart', '10'))) === 0);
check('8点散牌', evalGroup(g(c('spade', '5'), c('heart', '3'))).name === '8点'); // 5+3=8

// 4) 比较
check('丁皇 > 天牌', compareGroup(evalGroup(g(c('heart', '3'), c('joker', 'JOKER'))), evalGroup(g(c('heart', 'Q'), c('diamond', 'Q')))) > 0);
check('天牌 > 地牌', compareGroup(evalGroup(g(c('heart', 'Q'), c('diamond', 'Q'))), evalGroup(g(c('heart', '2'), c('diamond', '2')))) > 0);
check('对子 > 奶狗', compareGroup(evalGroup(g(c('spade', '8'), c('club', '8'))), evalGroup(g(c('heart', 'Q'), c('spade', '9')))) > 0);
check('奶狗 > 天杠', compareGroup(evalGroup(g(c('heart', 'Q'), c('spade', '9'))), evalGroup(g(c('heart', 'Q'), c('club', '8')))) > 0);
check('天杠 > 地杠', compareGroup(evalGroup(g(c('heart', 'Q'), c('club', '8'))), evalGroup(g(c('heart', '2'), c('club', '8')))) > 0);
check('天关九 > 散牌8点', compareGroup(evalGroup(g(c('heart', 'Q'), c('spade', '7'))), evalGroup(g(c('spade', '5'), c('heart', '3')))) > 0);
check('8点 > 7点', compareGroup(evalGroup(g(c('spade', '5'), c('heart', '3'))), evalGroup(g(c('heart', '2'), c('spade', '5')))) > 0);
check('梅十=板凳(同档相等)', compareGroup(evalGroup(g(c('spade', '10'), c('club', '10'))), evalGroup(g(c('spade', '4'), c('club', '4')))) === 0);
check('虎头=苕十(同档相等)', compareGroup(evalGroup(g(c('spade', 'J'), c('club', 'J'))), evalGroup(g(c('heart', '10'), c('diamond', '10')))) === 0);

// 5) 特殊牌型
check('三花十', specialHand([c('heart', '10'), c('spade', '10'), c('spade', 'J'), c('club', '7')]) === '三花十');
check('三花六', specialHand([c('heart', '6'), c('spade', '6'), c('joker', 'JOKER'), c('club', '7')]) === '三花六');
check('非特殊', specialHand([c('heart', 'Q'), c('diamond', 'Q'), c('spade', '8'), c('club', '7')]) === null);

// 6) 分墩 + 比牌
// A: 对红Q(天牌) + 红8红8(人牌) ；B: 红4红4(和牌) + 黑8黑8(杂对)
const A = bestSplit([c('heart', 'Q'), c('diamond', 'Q'), c('heart', '8'), c('diamond', '8')]);
check('A 头墩=天牌', A.headEval.name === '天牌');
check('A 尾墩=人牌', A.tailEval.name === '人牌');
const B = bestSplit([c('heart', '4'), c('diamond', '4'), c('spade', '8'), c('club', '8')]);
check('A 胜 B（头尾都大）', compareSplit(A, B) > 0);

// 打和：一大一小
// C: 头天牌, 尾杂对8 ；D: 头和牌, 尾人牌 -> C头大D尾大 => 打和
const C = bestSplit([c('heart', 'Q'), c('diamond', 'Q'), c('spade', '8'), c('club', '8')]);
const D = bestSplit([c('heart', '4'), c('diamond', '4'), c('heart', '8'), c('diamond', '8')]);
check('C 头墩=天牌', C.headEval.name === '天牌');
check('D 头墩=人牌(大者为头)', D.headEval.name === '人牌');
check('D 尾墩=和牌', D.tailEval.name === '和牌');
check('C vs D 打和（一大一小）', compareSplit(C, D) === 0);

console.log(`\n通过 ${pass} / ${pass + fail}`);
if (fail > 0) process.exit(1);
