import { JosaUtil } from '@sammo-ts/common/util/JosaUtil';

import type { CommandOption, CommandTable } from './types';

type CommandScope = 'general' | 'nation';
type CommandArgs = Record<string, unknown>;

const CITY_TO_COMMANDS = new Set(['che_이동', 'che_강행', 'che_출병', 'che_천도']);
const CITY_AT_COMMANDS = new Set([
    'che_첩보',
    'che_화계',
    'che_선동',
    'che_탈취',
    'che_파괴',
    'che_백성동원',
    'che_허보',
]);
const CITY_OBJECT_COMMANDS = new Set(['che_수몰', 'che_초토화']);
const NATION_AT_COMMANDS = new Set(['che_선전포고', 'che_급습', 'che_이호경식']);
const NATION_PROPOSAL_COMMANDS = new Set(['che_불가침파기제의', 'che_종전제의']);

const ITEM_TYPE_NAMES: Record<string, string> = {
    horse: '명마',
    weapon: '무기',
    book: '서적',
    item: '도구',
};

const asArgs = (value: unknown): CommandArgs =>
    value && typeof value === 'object' && !Array.isArray(value) ? (value as CommandArgs) : {};

const firstValue = (args: CommandArgs, keys: readonly string[]): unknown => {
    for (const key of keys) {
        if (args[key] !== undefined) return args[key];
    }
    return undefined;
};

const optionLabel = (options: readonly CommandOption[], value: unknown): string | null => {
    const option = options.find((entry) => entry.value === value || String(entry.value) === String(value));
    if (!option) return null;
    // 도시·장수 option에는 선택 보조용 소속 정보가 괄호로 붙지만 Ref brief에는 이름만 들어간다.
    return option.label.replace(/\s+\([^)]*\)$/u, '');
};

const commandNameMap = (table: CommandTable | null, scope: CommandScope): Map<string, string> => {
    const result = new Map<string, string>([['휴식', '휴식']]);
    for (const group of table?.[scope] ?? []) {
        for (const command of group.values) result.set(command.key, command.name);
    }
    return result;
};

const defaultCommandName = (action: string): string => action.replace(/^(?:che_|cr_|event_)/u, '');

const numberText = (value: unknown, grouped = false): string => {
    if (typeof value !== 'number' || !Number.isFinite(value)) return String(value ?? '');
    return grouped ? value.toLocaleString('en-US') : String(value);
};

const wrap = (value: string): string => `【${value}】`;
const withParticle = (value: string, particle: '을' | '으로'): string => `${value}${JosaUtil.pick(value, particle)}`;
const wrappedWithParticle = (value: string, particle: '을' | '으로'): string =>
    `${wrap(value)}${JosaUtil.pick(value, particle)}`;

export const formatReservedCommandBrief = (
    scope: CommandScope,
    action: string,
    rawArgs: unknown,
    table: CommandTable | null
): string => {
    const args = asArgs(rawArgs);
    const input = table?.inputOptions;
    const commandNames = commandNameMap(table, scope);
    const commandName = commandNames.get(action) ?? defaultCommandName(action);
    const cityName = optionLabel(input?.cities ?? [], firstValue(args, ['destCityId', 'destCityID']));
    const nationName = optionLabel(input?.nations ?? [], firstValue(args, ['destNationId', 'destNationID']));
    const generalName = optionLabel(
        input?.generalTargets?.[action] ?? input?.generals ?? [],
        firstValue(args, ['destGeneralId', 'destGeneralID'])
    );

    if (CITY_TO_COMMANDS.has(action) && cityName) {
        return `${wrappedWithParticle(cityName, '으로')} ${commandName}`;
    }
    if (action === 'cr_인구이동' && cityName) {
        return `${wrappedWithParticle(cityName, '으로')} ${numberText(args.amount, true)}명 ${commandName}`;
    }
    if (CITY_AT_COMMANDS.has(action) && cityName) {
        const suffix =
            scope === 'nation' ? commandName : action === 'che_첩보' ? `${commandName} 실행` : `${commandName}실행`;
        return `${wrap(cityName)}에 ${suffix}`;
    }
    if (CITY_OBJECT_COMMANDS.has(action) && cityName) {
        return `${wrappedWithParticle(cityName, '을')} ${commandName}`;
    }
    if (action === 'che_임관' && nationName) {
        return `${wrappedWithParticle(nationName, '으로')} ${commandName}`;
    }
    if (NATION_AT_COMMANDS.has(action) && nationName) {
        return `${wrap(nationName)}에 ${commandName}`;
    }
    if (NATION_PROPOSAL_COMMANDS.has(action) && nationName) {
        return `${wrap(nationName)}에게 ${commandName}`;
    }
    if (action === 'che_불가침제의' && nationName) {
        return `${wrap(nationName)}에게 ${numberText(args.year)}년 ${numberText(args.month)}월까지 ${commandName}`;
    }
    if (action === 'che_등용' && generalName) {
        return `${wrappedWithParticle(generalName, '을')} ${commandName}`;
    }
    if (action === 'che_장수대상임관' && generalName) {
        return `${wrappedWithParticle(generalName, '을')} 따라 임관`;
    }
    if (action === 'che_선양' && generalName) {
        return `${wrap(generalName)}에게 ${commandName}`;
    }
    if (action === 'che_랜덤임관') {
        return '무작위 국가로 임관';
    }
    if ((action === 'che_건국' || action === 'cr_건국') && typeof args.nationName === 'string') {
        return `${wrappedWithParticle(args.nationName, '을')} 건국`;
    }
    if (action === 'che_무작위건국' && typeof args.nationName === 'string') {
        return `${wrappedWithParticle(args.nationName, '을')} 무작위 도시에 건국`;
    }
    if (action === 'che_군량매매') {
        return `군량 ${numberText(args.amount)}을 ${args.buyRice ? '구입' : '판매'}`;
    }
    if (action === 'che_헌납') {
        return `${args.isGold ? '금' : '쌀'} ${numberText(args.amount)}을 ${commandName}`;
    }
    if (action === 'che_증여' && generalName) {
        return `${wrap(generalName)}에게 ${args.isGold ? '금' : '쌀'} ${numberText(args.amount)}을 ${commandName}`;
    }
    if (action === 'che_징병' || action === 'che_모병') {
        const crewType = optionLabel(input?.crewTypes ?? [], args.crewType);
        if (crewType) return `${wrap(crewType)} ${numberText(args.amount)}명 ${commandName}`;
    }
    if (action === 'che_숙련전환') {
        const srcArmType = optionLabel(input?.armTypes ?? [], args.srcArmType);
        const destArmType = optionLabel(input?.armTypes ?? [], args.destArmType);
        if (srcArmType && destArmType) return `${wrap(srcArmType)}숙련을 ${wrap(destArmType)}숙련으로 전환`;
    }
    if (action === 'che_장비매매') {
        const itemType = typeof args.itemType === 'string' ? args.itemType : '';
        if (args.itemCode === 'None') {
            const itemTypeName = ITEM_TYPE_NAMES[itemType];
            if (itemTypeName) return `${withParticle(itemTypeName, '을')} 판매`;
        }
        const itemName = optionLabel(input?.items[itemType] ?? [], args.itemCode);
        if (itemName) {
            const itemRawName = itemName.replace(/\([^)]*\)$/u, '');
            return `${wrap(itemName)}${JosaUtil.pick(itemRawName, '을')} 구입`;
        }
    }
    if (action === 'che_발령' && generalName && cityName) {
        return `${wrap(generalName)}${wrappedWithParticle(cityName, '으로')} ${commandName}`;
    }
    if (action === 'che_부대탈퇴지시' && generalName) {
        return `${wrap(generalName)}${commandName}`;
    }
    if ((action === 'che_포상' || action === 'che_몰수') && generalName) {
        return `${wrap(generalName)} ${args.isGold ? '금' : '쌀'} ${numberText(args.amount, true)} ${commandName}`;
    }
    if (action === 'che_물자원조' && nationName && Array.isArray(args.amountList)) {
        return `${wrap(nationName)}에게 국고 ${numberText(args.amountList[0], true)} 병량 ${numberText(
            args.amountList[1],
            true
        )} ${commandName}`;
    }
    if (action === 'che_증축' || action === 'che_감축') {
        return `수도를 ${commandName}`;
    }
    if (action === 'che_국기변경') {
        return '【국기】를 변경';
    }
    if (action === 'che_국호변경' && typeof args.nationName === 'string') {
        return `국호를 ${wrappedWithParticle(args.nationName, '으로')} 변경`;
    }
    if (action === 'che_피장파장' && nationName) {
        const targetAction = typeof args.commandType === 'string' ? args.commandType : '';
        const targetName = commandNames.get(targetAction) ?? defaultCommandName(targetAction);
        return `${wrap(nationName)}에 ${wrap(targetName)} ${commandName}`;
    }

    return commandName;
};
