import {
    _buildEventBody,
    _addMinutesIso,
    _addDaysDate,
} from '../src/features/calendar/calendarApi';
import { _parseCalEventAttrs } from '../src/agent';

describe('_addMinutesIso', () => {
    test('adds minutes to local ISO without timezone, preserves no-tz format', () => {
        const out = _addMinutesIso('2026-05-21T14:00', 60);
        expect(out).toBe('2026-05-21T15:00:00');
    });

    test('handles ISO with seconds', () => {
        const out = _addMinutesIso('2026-05-21T14:30:00', 30);
        expect(out).toBe('2026-05-21T15:00:00');
    });

    test('handles UTC marker Z', () => {
        const out = _addMinutesIso('2026-05-21T14:00:00Z', 60);
        expect(out).toBe('2026-05-21T15:00:00.000Z');
    });

    test('returns null on malformed input', () => {
        expect(_addMinutesIso('not-a-date', 30)).toBeNull();
        expect(_addMinutesIso('', 30)).toBeNull();
    });

    test('handles day-rollover correctly', () => {
        const out = _addMinutesIso('2026-05-21T23:30', 60);
        expect(out).toBe('2026-05-22T00:30:00');
    });
});

describe('_addDaysDate', () => {
    test('adds days to YYYY-MM-DD', () => {
        expect(_addDaysDate('2026-05-21', 1)).toBe('2026-05-22');
        expect(_addDaysDate('2026-12-31', 1)).toBe('2027-01-01');
    });
});

describe('_buildEventBody', () => {
    test('rejects empty title or start', () => {
        const r1 = _buildEventBody({ title: '', start: '2026-05-21T14:00' }, 60);
        expect(r1.ok).toBe(false);
        const r2 = _buildEventBody({ title: 'x', start: '' }, 60);
        expect(r2.ok).toBe(false);
    });

    test('builds basic timed event with default duration', () => {
        const r = _buildEventBody({ title: '회의', start: '2026-05-21T14:00' }, 60);
        if (!r.ok) throw new Error('expected ok');
        expect(r.event.summary).toBe('회의');
        expect(r.event.start.dateTime).toBe('2026-05-21T14:00');
        expect(r.event.end.dateTime).toBe('2026-05-21T15:00:00');
        // 로컬 timezone 자동 포함 — Intl 결과 (값은 시스템 의존이라 존재만 확인)
        expect(r.event.start.timeZone).toBeTruthy();
        expect(r.event.reminders.overrides).toHaveLength(2);
    });

    test('respects explicit duration', () => {
        const r = _buildEventBody({
            title: '미팅', start: '2026-05-21T14:00', durationMinutes: 90,
        }, 60);
        if (!r.ok) throw new Error('expected ok');
        expect(r.event.end.dateTime).toBe('2026-05-21T15:30:00');
    });

    test('respects explicit end over duration', () => {
        const r = _buildEventBody({
            title: '미팅', start: '2026-05-21T14:00', end: '2026-05-21T16:00', durationMinutes: 30,
        }, 60);
        if (!r.ok) throw new Error('expected ok');
        expect(r.event.end.dateTime).toBe('2026-05-21T16:00');
    });

    test('builds all-day event with exclusive end (+1 day)', () => {
        const r = _buildEventBody({
            title: '생일', start: '2026-06-15', allDay: true,
        }, 60);
        if (!r.ok) throw new Error('expected ok');
        expect(r.event.start.date).toBe('2026-06-15');
        expect(r.event.end.date).toBe('2026-06-16');
        expect(r.event.start.dateTime).toBeUndefined();
    });

    test('omits timeZone when input has explicit offset', () => {
        const r = _buildEventBody({
            title: '회의', start: '2026-05-21T14:00:00+09:00',
        }, 60);
        if (!r.ok) throw new Error('expected ok');
        expect(r.event.start.timeZone).toBeUndefined();
    });
});

describe('_parseCalEventAttrs', () => {
    test('parses double-quoted attrs', () => {
        const a = _parseCalEventAttrs(' title="팀 미팅" start="2026-05-21T14:00" duration="60" ');
        expect(a.title).toBe('팀 미팅');
        expect(a.start).toBe('2026-05-21T14:00');
        expect(a.duration).toBe(60);
    });

    test('parses single-quoted + bare attrs', () => {
        const a = _parseCalEventAttrs(`title='간단' start=2026-05-21T14:00 duration=30`);
        expect(a.title).toBe('간단');
        expect(a.start).toBe('2026-05-21T14:00');
        expect(a.duration).toBe(30);
    });

    test('parses all_day variants', () => {
        const a1 = _parseCalEventAttrs('title="x" start="2026-05-21" all_day="true"');
        expect(a1.allDay).toBe(true);
        const a2 = _parseCalEventAttrs('title="x" start="2026-05-21" allday="1"');
        expect(a2.allDay).toBe(true);
        const a3 = _parseCalEventAttrs('title="x" start="2026-05-21" all-day="yes"');
        expect(a3.allDay).toBe(true);
        const a4 = _parseCalEventAttrs('title="x" start="2026-05-21" all_day="false"');
        expect(a4.allDay).toBe(false);
    });

    test('ignores invalid duration value', () => {
        const a = _parseCalEventAttrs('title="x" start="t" duration="abc"');
        expect(a.duration).toBeUndefined();
    });

    test('returns empty when attrs are missing', () => {
        expect(_parseCalEventAttrs('')).toEqual({});
        expect(_parseCalEventAttrs('   ')).toEqual({});
    });
});
