import {
    parseTaskStore,
    renderTaskStore,
    addTask,
    updateTask,
    completeTask,
    summarizeActiveTasks,
    TaskStore,
} from '../src/features/tasks/taskStore';
import { _parseTaskAttrs } from '../src/agent';

describe('parseTaskStore', () => {
    test('returns empty store on empty markdown', () => {
        const s = parseTaskStore('');
        expect(s).toEqual({ active: [], done: [] });
    });

    test('parses round-tripped output', () => {
        const original: TaskStore = {
            active: [
                { id: 't_001', title: '광고주 자료', owner: '@me', due: '2026-05-24T18:00', status: 'in_progress', notes: '자료 대기' },
                { id: 't_002', title: '디자인 리뷰', owner: '@planner', due: '', status: 'open', notes: '' },
            ],
            done: [
                { id: 't_000', title: '셋업', owner: '@me', due: '', status: 'done', notes: '', completedAt: '2026-05-20T10:00' },
            ],
        };
        const md = renderTaskStore(original);
        const parsed = parseTaskStore(md);
        expect(parsed.active).toHaveLength(2);
        expect(parsed.active[0].id).toBe('t_001');
        expect(parsed.active[0].status).toBe('in_progress');
        expect(parsed.done).toHaveLength(1);
        expect(parsed.done[0].id).toBe('t_000');
        expect(parsed.done[0].completedAt).toBe('2026-05-20T10:00');
    });

    test('normalizes status variants', () => {
        const md = `# Tasks
## Active
| ID | Title | Owner | Due | Status | Notes |
|---|---|---|---|---|---|
| t_001 | a | @me |  | In Progress |  |
| t_002 | b | @me |  | INPROGRESS |  |
| t_003 | c | @me |  | blocked |  |
| t_004 | d | @me |  | unknown_status |  |`;
        const s = parseTaskStore(md);
        expect(s.active.map((t) => t.status)).toEqual(['in_progress', 'in_progress', 'blocked', 'open']);
    });

    test('ignores malformed rows', () => {
        const md = `# Tasks
## Active
| ID | Title | Owner | Due | Status | Notes |
|---|---|---|---|---|---|
| t_001 | ok | @me |  | open |  |
| no_t_prefix | bad |
| just text not a row
| t_003 | ok2 | @me |  | open |  |`;
        const s = parseTaskStore(md);
        expect(s.active.map((t) => t.id)).toEqual(['t_001', 't_003']);
    });
});

describe('addTask', () => {
    test('assigns incremental t_NNN ids based on max across active + done', () => {
        const store: TaskStore = {
            active: [{ id: 't_003', title: 'a', owner: '', due: '', status: 'open', notes: '' }],
            done: [{ id: 't_010', title: 'b', owner: '', due: '', status: 'done', notes: '', completedAt: '' }],
        };
        const t = addTask(store, { title: '신규' });
        expect(t.id).toBe('t_011');
    });

    test('starts at t_001 for empty store', () => {
        const store: TaskStore = { active: [], done: [] };
        const t = addTask(store, { title: '첫 task' });
        expect(t.id).toBe('t_001');
    });

    test('trims input fields and defaults status to open', () => {
        const store: TaskStore = { active: [], done: [] };
        const t = addTask(store, { title: '  광고주  ', owner: '  @me  ', notes: '' });
        expect(t.title).toBe('광고주');
        expect(t.owner).toBe('@me');
        expect(t.status).toBe('open');
        expect(t.notes).toBe('');
    });
});

describe('updateTask', () => {
    test('patches only provided fields, preserves id', () => {
        const store: TaskStore = {
            active: [{ id: 't_001', title: 'a', owner: '@me', due: '', status: 'open', notes: '' }],
            done: [],
        };
        const r = updateTask(store, 't_001', { status: 'in_progress', notes: '시작' });
        expect(r?.title).toBe('a');
        expect(r?.status).toBe('in_progress');
        expect(r?.notes).toBe('시작');
    });

    test('returns null for unknown id', () => {
        const store: TaskStore = { active: [], done: [] };
        expect(updateTask(store, 't_999', { notes: 'x' })).toBeNull();
    });
});

describe('completeTask', () => {
    test('moves active task to done with completedAt', () => {
        const store: TaskStore = {
            active: [{ id: 't_001', title: 'a', owner: '', due: '', status: 'open', notes: '' }],
            done: [],
        };
        const r = completeTask(store, 't_001', '2026-05-21T15:00');
        expect(r?.status).toBe('done');
        expect(store.active).toHaveLength(0);
        expect(store.done).toHaveLength(1);
        expect(store.done[0].completedAt).toBe('2026-05-21T15:00');
    });

    test('returns null when already done or unknown', () => {
        const store: TaskStore = { active: [], done: [] };
        expect(completeTask(store, 't_001')).toBeNull();
    });
});

describe('summarizeActiveTasks', () => {
    test('returns empty string when no active', () => {
        expect(summarizeActiveTasks({ active: [], done: [] })).toBe('');
    });

    test('sorts due-set tasks before unset, asc by due', () => {
        const store: TaskStore = {
            active: [
                { id: 't_001', title: '늦은', owner: '', due: '2026-06-01T10:00', status: 'open', notes: '' },
                { id: 't_002', title: '미정', owner: '', due: '', status: 'open', notes: '' },
                { id: 't_003', title: '빠른', owner: '', due: '2026-05-21T10:00', status: 'open', notes: '' },
            ],
            done: [],
        };
        const summary = summarizeActiveTasks(store);
        const lines = summary.split('\n');
        // 빠른 → 늦은 → 미정 순
        expect(lines[0]).toContain('빠른');
        expect(lines[1]).toContain('늦은');
        expect(lines[2]).toContain('미정');
    });

    test('truncates beyond max', () => {
        const active = Array.from({ length: 20 }, (_, i) => ({
            id: `t_${String(i).padStart(3, '0')}`,
            title: `task ${i}`,
            owner: '', due: '', status: 'open' as const, notes: '',
        }));
        const summary = summarizeActiveTasks({ active, done: [] }, 5);
        expect(summary).toContain('task 0');
        expect(summary).toContain('task 4');
        expect(summary).not.toContain('task 5');
        expect(summary).toContain('15 more');
    });
});

describe('_parseTaskAttrs', () => {
    test('parses standard task attrs', () => {
        const a = _parseTaskAttrs('id="t_001" title="광고주 자료" owner="@me" due="2026-05-24T18:00"');
        expect(a.id).toBe('t_001');
        expect(a.title).toBe('광고주 자료');
        expect(a.owner).toBe('@me');
        expect(a.due).toBe('2026-05-24T18:00');
    });

    test('normalizes status variants', () => {
        expect(_parseTaskAttrs('status="In Progress"').status).toBe('in_progress');
        expect(_parseTaskAttrs('status="INPROGRESS"').status).toBe('in_progress');
        expect(_parseTaskAttrs('status="blocked"').status).toBe('blocked');
        expect(_parseTaskAttrs('status="done"').status).toBe('done');
        expect(_parseTaskAttrs('status="garbage"').status).toBe('open');
    });

    test('returns empty object when nothing parseable', () => {
        expect(_parseTaskAttrs('')).toEqual({});
        expect(_parseTaskAttrs('garbage')).toEqual({});
    });
});
