import { expect, test, type Page, type Route } from '@playwright/test';
import { gameProfile, gameTrpcRoute } from './gameTestPaths.js';

const response = (data: unknown) => ({ result: { data } });
const operations = (route: Route) =>
    decodeURIComponent(new URL(route.request().url()).pathname.split('/trpc/')[1] ?? '').split(',');
const general = {
    id: 1,
    name: '테스트장수',
    npcState: 0,
    officerLevel: 1,
    cityId: 1,
    cityName: null,
    troopId: 0,
    troopName: null,
    officerCity: 0,
    officerCityName: null,
    stats: { leadership: 70, strength: 60, intelligence: 50 },
    experienceLevel: 9,
    dedicationLevel: 1,
    injury: 0,
    gold: 1000,
    rice: 2000,
    personality: null,
    specialDomestic: null,
    specialWar: null,
    belong: 1,
    refreshScoreTotal: 10,
    permission: 'normal',
};
const install = async (page: Page, secretAllowed = true) => {
    await page.addInitScript((profile) => {
        localStorage.setItem('sammo-game-token', 'ga_general');
        localStorage.setItem('sammo-game-profile', profile);
    }, gameProfile);
    await page.route(gameTrpcRoute, async (route) => {
        const results = operations(route).map((operation) => {
            if (operation === 'auth.status') return response({ ok: true });
            if (operation === 'lobby.info') return response({ myGeneral: { id: 1, name: '테스트장수' } });
            if (operation === 'join.getConfig') return response({});
            if (operation === 'nation.getGeneralList')
                return response({
                    nation: { id: 1, name: '위', color: '#008000', level: 3 },
                    viewer: { generalId: 1, permission: 0 },
                    generals: [general],
                });
            if (operation === 'nation.getSecretGeneralList') {
                if (!secretAllowed)
                    return {
                        error: {
                            message: '권한이 부족합니다.',
                            code: -32000,
                            data: { code: 'FORBIDDEN', httpStatus: 403, path: operation },
                        },
                    };
                return response({
                    nation: { id: 1, name: '위', color: '#008000', level: 3 },
                    viewer: { generalId: 1, permission: 1 },
                    summary: {
                        gold: 1000,
                        rice: 2000,
                        crew: 300,
                        generalCount: 1,
                        averageGold: 1000,
                        averageRice: 2000,
                        readiness: {
                            90: { crew: 300, generals: 1 },
                            80: { crew: 300, generals: 1 },
                            60: { crew: 300, generals: 1 },
                        },
                    },
                    generals: [
                        {
                            id: 1,
                            name: '테스트장수',
                            npcState: 0,
                            injury: 0,
                            stats: { leadership: 70, strength: 60, intelligence: 50 },
                            leadershipBonus: 0,
                            experienceLevel: 9,
                            troopId: 0,
                            troopName: null,
                            gold: 1000,
                            rice: 2000,
                            cityId: 1,
                            cityName: '업',
                            defenceTrain: 90,
                            defenceTrainText: '☆',
                            crewTypeId: 1,
                            crew: 300,
                            train: 90,
                            atmos: 90,
                            killTurn: 7,
                            turnTime: '2026-01-01T01:02:00.000Z',
                            reservedCommands: ['징병', '훈련'],
                        },
                    ],
                });
            }
            return { error: { message: `unhandled ${operation}`, data: { code: 'BAD_REQUEST' } } };
        });
        await route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(results) });
    });
};

test('nation generals keeps the 1000px legacy grid and redacted member columns', async ({ page }) => {
    await install(page);
    await page.setViewportSize({ width: 1200, height: 900 });
    await page.goto('nation/generals');
    await expect(page.locator('#nation-general-list')).toContainText('테스트장수');
    await expect(page.locator('#nation-general-list')).toContainText('?');
    const computed = await page.locator('.general-page').evaluate((element) => {
        const rect = element.getBoundingClientRect();
        const style = getComputedStyle(element);
        return { x: rect.x, width: rect.width, fontSize: style.fontSize, fontFamily: style.fontFamily };
    });
    expect(computed).toMatchObject({ x: 100, width: 1000, fontSize: '16px' });
    expect(computed.fontFamily).toContain('Times New Roman');
    expect(await page.locator('#nation-general-list').evaluate((el) => getComputedStyle(el).borderCollapse)).toBe(
        'separate'
    );
    expect((await page.locator('#nation-general-list').boundingBox())?.width).toBe(1030);
    expect((await page.locator('#nation-general-list tbody tr').boundingBox())?.height).toBe(66);
});

test('both pages preserve the legacy 1000px overflow contract at 500px', async ({ page }) => {
    await install(page);
    await page.setViewportSize({ width: 500, height: 900 });
    for (const path of ['nation/generals', 'nation/secret']) {
        await page.goto(path);
        await expect(
            page.locator(path.endsWith('secret') ? '#secret-general-list' : '#nation-general-list')
        ).toBeVisible();
        expect(await page.locator('main').evaluate((el) => el.getBoundingClientRect().width)).toBe(1000);
        expect(await page.evaluate(() => document.documentElement.scrollWidth)).toBeGreaterThanOrEqual(1000);
    }
});

test('secret office renders summary, turns, and the forbidden error flow', async ({ page }) => {
    await install(page);
    await page.setViewportSize({ width: 1200, height: 900 });
    await page.goto('nation/secret');
    await expect(page.locator('.summary')).toContainText('전체 금');
    await expect(page.locator('#secret-general-list')).toContainText('1 : 징병');
    expect(await page.locator('.secret-page').evaluate((el) => el.getBoundingClientRect().width)).toBe(1000);

    await page.unroute(gameTrpcRoute);
    await install(page, false);
    await page.goto('nation/secret');
    await expect(page.getByRole('alert')).toContainText('권한이 부족합니다.');
    await expect(page.locator('#secret-general-list')).toHaveCount(0);
});
