import { describe, expect, it } from 'vitest';
import type { City, General, Nation } from '../../../src/domain/entities.js';
import type { ConstraintContext, RequirementKey, StateView } from '../../../src/constraints/types.js';
import { evaluateConstraints } from '../../../src/constraints/evaluate.js';
import { resolveGeneralAction } from '../../../src/actions/engine.js';
import type { TurnSchedule } from '../../../src/turn/calendar.js';
import { ActionDefinition as StopWarAcceptAction } from '../../../src/actions/instant/nation/che_종전수락.js';

class TestStateView implements StateView {
    private readonly store = new Map<string, unknown>();

    has(req: RequirementKey): boolean {
        return this.store.has(this.getKey(req));
    }

    get(req: RequirementKey): unknown | null {
        return this.store.get(this.getKey(req)) ?? null;
    }

    set(req: RequirementKey, value: unknown): void {
        this.store.set(this.getKey(req), value);
    }

    private getKey(req: RequirementKey): string {
        switch (req.kind) {
            case 'general':
                return `general:${req.id}`;
            case 'city':
                return `city:${req.id}`;
            case 'nation':
                return `nation:${req.id}`;
            case 'destGeneral':
                return `destGeneral:${req.id}`;
            case 'destNation':
                return `destNation:${req.id}`;
            case 'diplomacy':
                return `diplomacy:${req.srcNationId}:${req.destNationId}`;
            case 'arg':
                return `arg:${req.key}`;
            case 'env':
                return `env:${req.key}`;
            default:
                return 'unknown';
        }
    }
}

const buildGeneral = (id: number, nationId: number, cityId: number, name = 'TestGeneral'): General => ({
    id,
    name,
    nationId,
    cityId,
    troopId: 0,
    stats: {
        leadership: 70,
        strength: 70,
        intelligence: 70,
    },
    experience: 100,
    dedication: 100,
    officerLevel: 3,
    role: {
        personality: null,
        specialDomestic: null,
        specialWar: null,
        items: {
            horse: null,
            weapon: null,
            book: null,
            item: null,
        },
    },
    injury: 0,
    gold: 1000,
    rice: 2000,
    crew: 1500,
    crewTypeId: 100,
    train: 80,
    atmos: 80,
    age: 25,
    npcState: 0,
    triggerState: {
        flags: {},
        counters: {},
        modifiers: {},
        meta: {},
    },
    meta: { killturn: 24 },
});

const buildCity = (id: number, nationId: number): City => ({
    id,
    name: `City${id}`,
    nationId,
    level: 2,
    state: 0,
    population: 10000,
    populationMax: 10000,
    agriculture: 1000,
    agricultureMax: 1000,
    commerce: 1000,
    commerceMax: 1000,
    security: 1000,
    securityMax: 1000,
    supplyState: 1,
    frontState: 0,
    defence: 200,
    defenceMax: 400,
    wall: 200,
    wallMax: 400,
    meta: {},
});

const buildNation = (id: number, name = 'Nation'): Nation => ({
    id,
    name: `${name}${id}`,
    color: '#000000',
    capitalCityId: id,
    chiefGeneralId: id,
    gold: 5000,
    rice: 5000,
    power: 0,
    level: 1,
    typeCode: 'test',
    meta: {},
});

const schedule: TurnSchedule = {
    entries: [{ startMinute: 0, tickMinutes: 60 }],
};

describe('Nation Instant Actions', () => {
    it('che_종전수락: blocks when not at war/declare', () => {
        const general = buildGeneral(1, 1, 1);
        const nation = buildNation(1);
        const destNation = buildNation(2);
        const destGeneral = buildGeneral(2, 2, 2, 'Dest');
        const city = buildCity(1, 1);
        const view = new TestStateView();
        view.set({ kind: 'general', id: general.id }, general);
        view.set({ kind: 'city', id: city.id }, city);
        view.set({ kind: 'nation', id: nation.id }, nation);
        view.set({ kind: 'destNation', id: destNation.id }, destNation);
        view.set({ kind: 'destGeneral', id: destGeneral.id }, destGeneral);
        view.set(
            {
                kind: 'diplomacy',
                srcNationId: nation.id,
                destNationId: destNation.id,
            },
            { state: 2, term: 0 }
        );

        const definition = new StopWarAcceptAction();
        const args = { destNationId: destNation.id, destGeneralId: destGeneral.id };
        const ctx: ConstraintContext = {
            actorId: general.id,
            nationId: nation.id,
            cityId: city.id,
            destNationId: destNation.id,
            destGeneralId: destGeneral.id,
            args,
            env: {},
            mode: 'full',
        };

        const result = evaluateConstraints(definition.buildConstraints(ctx, args), ctx, view);
        expect(result.kind).toBe('deny');
    });

    it('che_종전수락: patches diplomacy to neutral', () => {
        const general = buildGeneral(1, 1, 1);
        const nation = buildNation(1);
        const city = buildCity(1, 1);
        const destNation = buildNation(2);

        const definition = new StopWarAcceptAction();
        const resolution = resolveGeneralAction(
            definition,
            {
                general,
                city,
                nation,
                destNation,
                destGeneral: buildGeneral(2, 2, 2, 'Dest'),
                currentYear: 200,
                currentMonth: 1,
                rng: {} as any,
                addLog: () => {},
            } as any,
            { now: new Date(), schedule },
            { destNationId: destNation.id, destGeneralId: 2 }
        );

        const patches = resolution.effects.filter((effect) => effect.type === 'diplomacy:patch');
        expect(patches).toHaveLength(2);
        for (const patch of patches) {
            expect(patch.patch.state).toBe(2);
            expect(patch.patch.term).toBe(0);
        }
    });
});
