import { describe, it, expect } from 'vitest';

// ============================================================
// route.ts 순수 함수 로직 재현
// (export되지 않으므로 동일 로직을 직접 복제하여 테스트)
// ============================================================

// 파일명 규칙: {회사명}_{상품명}_{YYMM}.pdf
const FILE_NAME_REGEX = /^([가-힣a-zA-Z]+(?:_[가-힣a-zA-Z]+)*)_(.+)_(\d{4})\.pdf$/i;

// Item 3: 카테고리 키워드
const NON_LIFE_KEYWORDS = ['화재', '해상', '손보', '손해'];
const VARIABLE_KEYWORDS = ['변액'];

const MAX_FILE_SIZE = 50 * 1024 * 1024; // 50MB

/**
 * Item 3: 회사명 → 카테고리 분류
 * 변액 키워드 우선 검사 → 손해 계열 키워드 → 기본값 생명보험
 */
function getCategoryFromCompany(companyName: string): '생명보험' | '손해보험' | '변액보험' {
    for (const kw of VARIABLE_KEYWORDS) {
        if (companyName.includes(kw)) return '변액보험';
    }
    for (const kw of NON_LIFE_KEYWORDS) {
        if (companyName.includes(kw)) return '손해보험';
    }
    return '생명보험';
}

/**
 * Item 6 (Item 5 related): 회사명 → companyId 변환
 * 공백 → '_', 각 키워드를 영문 약어로 치환 후 소문자화
 */
function toCompanyId(companyName: string): string {
    return companyName
        .replace(/\s/g, '_')
        .replace(/생명/g, 'life')
        .replace(/해상/g, 'marine')
        .replace(/손보/g, 'nonlife')
        .replace(/손해/g, 'nonlife')   // Item 3 추가
        .replace(/화재/g, 'fire')
        .replace(/변액/g, 'variable')
        .toLowerCase();
}

/**
 * Item 4: 파일명 파싱 + YYMM 월 유효성 검사
 */
function parseFileName(fileName: string): {
    companyName: string;
    productName: string;
    effectiveDate: string;
} | null {
    const match = fileName.match(FILE_NAME_REGEX);
    if (!match) return null;

    const [, companyName, productName, yymm] = match;
    const year = `20${yymm.slice(0, 2)}`;
    const month = yymm.slice(2, 4);

    // Item 4: 월 범위 01~12 유효성 검사
    const monthNum = parseInt(month, 10);
    if (monthNum < 1 || monthNum > 12) return null;

    return { companyName, productName, effectiveDate: `${year}-${month}` };
}

/**
 * Item 2: Magic Bytes 검증 - 첫 4바이트가 %PDF (0x25504446) 인지 확인
 */
function validateMagicBytes(buffer: Buffer): boolean {
    return (
        buffer.length >= 4 &&
        buffer[0] === 0x25 && // '%'
        buffer[1] === 0x50 && // 'P'
        buffer[2] === 0x44 && // 'D'
        buffer[3] === 0x46    // 'F'
    );
}

// ============================================================
// 테스트
// ============================================================

describe('drive-upload route 순수함수 로직', () => {

    // ----------------------------------------------------------
    // Item 2: Magic Bytes 검증
    // ----------------------------------------------------------
    describe('Item 2 - Magic Bytes 검증', () => {
        it('유효한 PDF 매직 바이트(%PDF) → true', () => {
            const pdfBuffer = Buffer.from('%PDF-1.4 content here');
            expect(validateMagicBytes(pdfBuffer)).toBe(true);
        });

        it('%PDF로 시작하지 않는 파일 → false', () => {
            const fakeBuffer = Buffer.from('NOT-PDF content');
            expect(validateMagicBytes(fakeBuffer)).toBe(false);
        });

        it('빈 버퍼(0바이트) → false', () => {
            expect(validateMagicBytes(Buffer.from(''))).toBe(false);
        });

        it('3바이트만 있는 버퍼 → false (4바이트 미만)', () => {
            const shortBuffer = Buffer.from([0x25, 0x50, 0x44]); // %PD
            expect(validateMagicBytes(shortBuffer)).toBe(false);
        });

        it('ZIP 파일 시그니처(PK) → false', () => {
            const zipBuffer = Buffer.from([0x50, 0x4b, 0x03, 0x04]); // PK\x03\x04
            expect(validateMagicBytes(zipBuffer)).toBe(false);
        });
    });

    // ----------------------------------------------------------
    // Item 2: 파일 크기 검증
    // ----------------------------------------------------------
    describe('Item 2 - 파일 크기 검증', () => {
        it('50MB 이하 파일은 허용', () => {
            const fileSize = 50 * 1024 * 1024;
            expect(fileSize <= MAX_FILE_SIZE).toBe(true);
        });

        it('50MB 초과 파일은 거부', () => {
            const fileSize = 50 * 1024 * 1024 + 1;
            expect(fileSize > MAX_FILE_SIZE).toBe(true);
        });

        it('정확히 50MB는 허용', () => {
            const fileSize = 50 * 1024 * 1024;
            expect(fileSize > MAX_FILE_SIZE).toBe(false);
        });

        it('1바이트 파일은 허용', () => {
            const fileSize = 1;
            expect(fileSize > MAX_FILE_SIZE).toBe(false);
        });
    });

    // ----------------------------------------------------------
    // Item 3: 카테고리 분류
    // ----------------------------------------------------------
    describe('Item 3 - 카테고리 분류 (getCategoryFromCompany)', () => {
        it("'손해' 포함 → '손해보험' (KB손해보험)", () => {
            expect(getCategoryFromCompany('KB손해보험')).toBe('손해보험');
        });

        it("'손해' 포함 → '손해보험' (DB손해보험)", () => {
            expect(getCategoryFromCompany('DB손해보험')).toBe('손해보험');
        });

        it("'해상' 포함 → '손해보험' (현대해상)", () => {
            expect(getCategoryFromCompany('현대해상')).toBe('손해보험');
        });

        it("'화재' 포함 → '손해보험' (삼성화재)", () => {
            expect(getCategoryFromCompany('삼성화재')).toBe('손해보험');
        });

        it("'손보' 포함 → '손해보험'", () => {
            expect(getCategoryFromCompany('메리츠손보')).toBe('손해보험');
        });

        it("키워드 없음 → '생명보험' (삼성생명)", () => {
            expect(getCategoryFromCompany('삼성생명')).toBe('생명보험');
        });

        it("키워드 없음 → '생명보험' (한화생명)", () => {
            expect(getCategoryFromCompany('한화생명')).toBe('생명보험');
        });

        it("'변액' 포함 → '변액보험' (삼성변액)", () => {
            expect(getCategoryFromCompany('삼성변액')).toBe('변액보험');
        });

        it("'변액'이 '손해'보다 우선 순위 높음 (변액손해 → 변액보험)", () => {
            // 변액 키워드가 먼저 검사되므로 '변액보험'이어야 함
            expect(getCategoryFromCompany('변액손해테스트')).toBe('변액보험');
        });
    });

    // ----------------------------------------------------------
    // Item 4: 파일명 파싱 + YYMM 월 유효성 검증
    // ----------------------------------------------------------
    describe('Item 4 - 파일명 파싱 및 YYMM 검증 (parseFileName)', () => {
        it('정상 파일명 파싱 성공', () => {
            const result = parseFileName('삼성생명_퍼펙트종신_2403.pdf');
            expect(result).not.toBeNull();
            expect(result!.companyName).toBe('삼성생명');
            expect(result!.productName).toBe('퍼펙트종신');
            expect(result!.effectiveDate).toBe('2024-03');
        });

        it('12월(12) → 유효', () => {
            const result = parseFileName('삼성생명_퍼펙트종신_2412.pdf');
            expect(result).not.toBeNull();
            expect(result!.effectiveDate).toBe('2024-12');
        });

        it('1월(01) → 유효', () => {
            const result = parseFileName('삼성생명_퍼펙트종신_2401.pdf');
            expect(result).not.toBeNull();
            expect(result!.effectiveDate).toBe('2024-01');
        });

        it('13월(13) → null (월 범위 초과)', () => {
            expect(parseFileName('삼성생명_퍼펙트종신_2413.pdf')).toBeNull();
        });

        it('00월(00) → null (월 범위 미달)', () => {
            expect(parseFileName('삼성생명_퍼펙트종신_2400.pdf')).toBeNull();
        });

        it('99월(99) → null', () => {
            expect(parseFileName('삼성생명_퍼펙트종신_2499.pdf')).toBeNull();
        });

        it('잘못된 형식(확장자 없음) → null', () => {
            expect(parseFileName('잘못된파일명')).toBeNull();
        });

        it('잘못된 형식(구분자 없음) → null', () => {
            expect(parseFileName('삼성생명퍼펙트종신2403.pdf')).toBeNull();
        });

        it('YYMM이 4자리 미만 → null', () => {
            expect(parseFileName('삼성생명_퍼펙트종신_243.pdf')).toBeNull();
        });

        it('영문 회사명 포함 파일명도 파싱 성공', () => {
            const result = parseFileName('KB손해보험_암보험_2406.pdf');
            expect(result).not.toBeNull();
            expect(result!.companyName).toBe('KB손해보험');
            expect(result!.effectiveDate).toBe('2024-06');
        });
    });

    // ----------------------------------------------------------
    // Item 5/6: toCompanyId 매핑
    // ----------------------------------------------------------
    describe('Item 5/6 - toCompanyId 회사명 → companyId 변환', () => {
        it("'생명' → 'life' 치환 (삼성생명 → 삼성life)", () => {
            expect(toCompanyId('삼성생명')).toBe('삼성life');
        });

        it("'손해' → 'nonlife' 치환 (KB손해보험 → kbnonlife보험)", () => {
            expect(toCompanyId('KB손해보험')).toBe('kbnonlife보험');
        });

        it("'변액' → 'variable' 치환 (삼성변액 → 삼성variable)", () => {
            expect(toCompanyId('삼성변액')).toBe('삼성variable');
        });

        it("'화재' → 'fire' 치환 (삼성화재 → 삼성fire)", () => {
            expect(toCompanyId('삼성화재')).toBe('삼성fire');
        });

        it("'해상' → 'marine' 치환 (현대해상 → 현대marine)", () => {
            expect(toCompanyId('현대해상')).toBe('현대marine');
        });

        it("'손보' → 'nonlife' 치환 (메리츠손보 → 메리츠nonlife)", () => {
            expect(toCompanyId('메리츠손보')).toBe('메리츠nonlife');
        });

        it('공백이 있으면 _ 로 치환', () => {
            expect(toCompanyId('삼성 생명')).toBe('삼성_life');
        });

        it('결과는 소문자로 변환', () => {
            const result = toCompanyId('KB손해보험');
            expect(result).toBe(result.toLowerCase());
        });

        it("'손해'와 '손보' 모두 'nonlife'로 변환", () => {
            expect(toCompanyId('손해')).toBe('nonlife');
            expect(toCompanyId('손보')).toBe('nonlife');
        });
    });

});
