import { NextRequest, NextResponse } from 'next/server';
import { getAuth } from 'firebase-admin/auth';
import { getFirebaseAdmin } from '@/lib/firebase-admin';
import { FieldValue, Timestamp, Transaction } from 'firebase-admin/firestore';
import { getDriveService, findFolder, createFolder } from '@/lib/googleDrive';
import { Readable } from 'stream';
import { ADMIN_EMAILS } from '@/lib/constants';

// 파일명 규칙: {회사명}_{상품명}_{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 = ['변액'];

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 '생명보험';
}

function escapeDriveQuery(value: string): string {
    return value.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
}

function toCompanyId(companyName: string): string {
    return companyName
        .replace(/\s/g, '_')
        .replace(/생명/g, 'life')
        .replace(/해상/g, 'marine')
        .replace(/손보/g, 'nonlife')
        // Item 3: '손해' → 'nonlife' 매핑 추가
        .replace(/손해/g, 'nonlife')
        .replace(/화재/g, 'fire')
        .replace(/변액/g, 'variable')
        .toLowerCase();
}

function parseFileName(fileName: string) {
    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: YYMM 월 유효성 검사 (01~12)
    const monthNum = parseInt(month, 10);
    if (monthNum < 1 || monthNum > 12) return null;

    return { companyName, productName, effectiveDate: `${year}-${month}` };
}

async function getOrCreateFolder(parentId: string, folderName: string): Promise<string> {
    const existing = await findFolder(parentId, folderName);
    if (existing) return existing;
    return createFolder(parentId, folderName);
}

// Item 20: 회사명 정규화 테이블
async function normalizeCompanyName(db: FirebaseFirestore.Firestore, rawName: string): Promise<string> {
    const aliasDoc = await db.collection('company_aliases').doc(rawName).get();
    if (aliasDoc.exists) {
        return aliasDoc.data()?.normalizedName || rawName;
    }
    return rawName;
}

export async function POST(req: NextRequest) {
    try {
        // 1. Admin 권한 확인
        const authHeader = req.headers.get('Authorization');
        if (!authHeader?.startsWith('Bearer ')) {
            return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
        }
        const idToken = authHeader.split('Bearer ')[1];

        getFirebaseAdmin(); // 초기화 보장
        let userEmail: string | undefined;
        try {
            const decoded = await getAuth().verifyIdToken(idToken);
            userEmail = decoded.email;
        } catch {
            return NextResponse.json({ error: 'Unauthorized: Invalid token' }, { status: 401 });
        }

        if (!userEmail || !ADMIN_EMAILS.includes(userEmail)) {
            return NextResponse.json({ error: 'Forbidden: Admin only' }, { status: 403 });
        }

        // 2. FormData 파싱
        const formData = await req.formData();
        const files = formData.getAll('files') as File[];

        if (!files.length) {
            return NextResponse.json({ error: 'No files uploaded' }, { status: 400 });
        }

        const rootFolderId = process.env.GOOGLE_DRIVE_FOLDER_ID;
        if (!rootFolderId) {
            return NextResponse.json({ error: 'Server config error: GOOGLE_DRIVE_FOLDER_ID missing' }, { status: 500 });
        }

        const drive = getDriveService();
        const adminDb = getFirebaseAdmin().firestore();
        const results: Array<{ fileName: string; success: boolean; driveFileId?: string; jobId?: string; error?: string }> = [];

        // 3. 파일별 처리
        for (const file of files) {
            // Item 2: Magic Bytes + 크기 제한 검증을 위해 buffer 먼저 생성
            const MAX_FILE_SIZE = 50 * 1024 * 1024; // 50MB
            if (file.size > MAX_FILE_SIZE) {
                results.push({ fileName: file.name, success: false, error: '파일 크기 초과 (최대 50MB)' });
                continue;
            }

            const buffer = Buffer.from(await file.arrayBuffer());

            // Item 2: Magic Bytes 검증 - PDF 헤더 확인 (첫 4바이트: %PDF = 0x25504446)
            if (
                buffer.length < 4 ||
                buffer[0] !== 0x25 ||
                buffer[1] !== 0x50 ||
                buffer[2] !== 0x44 ||
                buffer[3] !== 0x46
            ) {
                results.push({ fileName: file.name, success: false, error: '유효하지 않은 PDF 파일' });
                continue;
            }

            const parsed = parseFileName(file.name);
            if (!parsed) {
                results.push({ fileName: file.name, success: false, error: '파일명 형식 오류' });
                continue;
            }

            const { productName, effectiveDate } = parsed;
            let { companyName } = parsed;

            // Item 20: 회사명 정규화 (parseFileName 후, getOrCreateFolder 전)
            companyName = await normalizeCompanyName(adminDb, companyName);

            const categoryLabel = getCategoryFromCompany(companyName);

            // Item 3: category 값 매핑 ('변액보험' → 'variable')
            const categoryValue =
                categoryLabel === '생명보험' ? 'life' :
                categoryLabel === '손해보험' ? 'non_life' :
                'variable';

            // Item 10: productId 기반 분산 락
            const companyId = toCompanyId(companyName);
            const productId = `${companyId}_${productName.replace(/\s/g, '_').toLowerCase()}_${effectiveDate.replace('-', '')}`;
            const docId = productId;

            const lockRef = adminDb.collection('upload_locks').doc(productId);
            const lockResult = await (async () => {
                const lockDoc = await adminDb.collection('upload_locks').doc(productId).get();
                if (lockDoc.exists) {
                    const lockData = lockDoc.data();
                    const lockedAt = lockData?.lockedAt?.toDate?.();
                    if (lockedAt && Date.now() - lockedAt.getTime() < 30 * 60 * 1000) {
                        return { locked: true };
                    }
                }
                await lockRef.set({ lockedAt: FieldValue.serverTimestamp(), productId });
                return { locked: false };
            })();

            if (lockResult.locked) {
                results.push({ fileName: file.name, success: false, error: '동일 상품 업로드 진행 중' });
                continue;
            }

            try {
                // 드라이브 폴더 구조: root/01_약관/{생명보험|손해보험|변액보험}/{회사명}/
                const yakwanFolderId = await getOrCreateFolder(rootFolderId, '01_약관');
                const categoryFolderId = await getOrCreateFolder(yakwanFolderId, categoryLabel);
                const companyFolderId = await getOrCreateFolder(categoryFolderId, companyName);

                // 동일 파일명 기존 파일 삭제 (덮어쓰기)
                const existingQuery = await drive.files.list({
                    q: `'${companyFolderId}' in parents and name = '${escapeDriveQuery(file.name)}' and trashed = false`,
                    fields: 'files(id)',
                });
                for (const ef of existingQuery.data.files || []) {
                    if (ef.id) await drive.files.delete({ fileId: ef.id });
                }

                // 파일 업로드 (buffer는 위에서 이미 생성됨)
                const uploadRes = await drive.files.create({
                    requestBody: { name: file.name, parents: [companyFolderId] },
                    media: { mimeType: 'application/pdf', body: Readable.from(buffer) },
                    fields: 'id',
                });

                const driveFileId = uploadRes.data.id!;

                // Item 11: Drive 업로드 성공 후 metadata/job 생성 실패 시 rollback
                try {
                    // insurance_metadata upsert
                    await adminDb.collection('insurance_metadata').doc(docId).set({
                        companyId,
                        companyName,
                        productId,
                        productName,
                        // Item 3: category 필드 반영
                        category: categoryValue,
                        driveFileId,
                        driveFileName: file.name,
                        effectiveDateRange: { start: effectiveDate },
                        isSalesStopped: false,
                        isActive: true,
                        // Item 5: updatedAt 타입 통일
                        updatedAt: FieldValue.serverTimestamp(),
                    }, { merge: true });

                    // index_pdf job 생성 → pdfIndexing Cloud Function 자동 트리거
                    const expireAt = new Date(Date.now() + 20 * 60 * 1000); // 20분 TTL
                    const jobRef = await adminDb.collection('jobs').add({
                        type: 'index_pdf',
                        status: 'pending',
                        driveFileId,
                        companyId,
                        companyName,
                        productId,
                        productName,
                        // Item 3: category 필드 반영
                        category: categoryValue,
                        effectiveDate,
                        createdAt: FieldValue.serverTimestamp(),
                        updatedAt: FieldValue.serverTimestamp(),
                        expireAt: Timestamp.fromDate(expireAt),
                    });

                    results.push({ fileName: file.name, success: true, driveFileId, jobId: jobRef.id });
                } catch (metaErr: any) {
                    // Item 11: metadata/job 생성 실패 시 Drive 파일 rollback
                    console.error(`Metadata/job creation failed for ${file.name}, rolling back Drive file:`, metaErr.message);
                    await drive.files.delete({ fileId: driveFileId }).catch(() => {});
                    results.push({ fileName: file.name, success: false, error: metaErr.message });
                }
            } catch (err: any) {
                console.error(`Upload failed for ${file.name}:`, err.message);
                results.push({ fileName: file.name, success: false, error: err.message });
            } finally {
                // Item 10: 락 해제
                await lockRef.delete().catch(() => {});
            }
        }

        const successCount = results.filter(r => r.success).length;
        return NextResponse.json({ results, successCount, totalCount: files.length });

    } catch (error: any) {
        console.error('Admin drive-upload error:', error);
        return NextResponse.json({ error: 'Internal Server Error', message: error.message }, { status: 500 });
    }
}
