/**
 * /api/share-target
 * PWA Web Share Target API 핸들러
 * [2026-02-23] 최초 작성
 * [2026-02-24] 번호 체계 자동 감지, My 노트 제목 검색/생성, 마크다운 append
 */

import { NextRequest, NextResponse } from 'next/server';
import { adminDb } from '@/lib/firebase-admin';
import { FieldValue } from 'firebase-admin/firestore';
import { verifyMemberFromParam } from '@/lib/auth-middleware';

/** OG 메타데이터 fetch */
async function fetchOGMeta(url: string): Promise<{ title: string }> {
  try {
    const res = await fetch(url, {
      headers: { 'User-Agent': 'Mozilla/5.0 (compatible; InsuWikiBot/1.0)' },
      signal: AbortSignal.timeout(3000),
    });
    const html = await res.text();
    const ogTitle = html.match(/<meta[^>]+property="og:title"[^>]+content="([^"]+)"/i)?.[1];
    const titleTag = html.match(/<title>([^<]+)<\/title>/i)?.[1];
    return { title: (ogTitle || titleTag || '').trim() };
  } catch {
    return { title: '' };
  }
}

/** KST 기준 Daily 문서 ID */
function getDailyDocId(uid: string): string {
  const kst = new Date(Date.now() + 9 * 60 * 60 * 1000);
  const y = kst.getUTCFullYear();
  const m = String(kst.getUTCMonth() + 1).padStart(2, '0');
  const d = String(kst.getUTCDate()).padStart(2, '0');
  return `daily-${y}-${m}-${d}-${uid}`;
}

/** KST 기준 날짜 문자열 */
function getKSTDateStr(): string {
  const kst = new Date(Date.now() + 9 * 60 * 60 * 1000);
  const y = kst.getUTCFullYear();
  const m = String(kst.getUTCMonth() + 1).padStart(2, '0');
  const d = String(kst.getUTCDate()).padStart(2, '0');
  return `${y}-${m}-${d}`;
}

/**
 * 기존 마크다운 내용에서 최대 번호 감지
 * "1. ...", "2. ..." 형태의 번호 목록을 파싱
 */
function detectNextNumber(content: string): number {
  const matches = content.match(/^(\d+)\./gm);
  if (!matches || matches.length === 0) return 1;
  const numbers = matches.map((m) => parseInt(m));
  return Math.max(...numbers) + 1;
}

/**
 * Daily에 추가할 마크다운 라인 생성
 * "{N}. {cardTitle} - [{ogTitle}]({url})"
 * cardTitle이 없으면 ogTitle만 링크로 표시
 */
function buildDailyLine(url: string, ogTitle: string, cardTitle: string, num: number): string {
  const displayTitle = cardTitle || ogTitle || url;
  const linkPart = `[${ogTitle || url}](${url})`;
  if (cardTitle) {
    return `${num}. ${cardTitle} - ${linkPart}`;
  }
  return `${num}. ${linkPart}`;
}

/**
 * My 노트에 추가할 마크다운 라인 생성
 * "{N}. [{ogTitle}]({url})"
 */
function buildMyLine(url: string, ogTitle: string, num: number): string {
  return `${num}. [${ogTitle || url}](${url})`;
}

export async function GET(req: NextRequest) {
  try {
    const { searchParams } = new URL(req.url);
    const url = searchParams.get('url') || searchParams.get('text') || '';
    const ogTitle = searchParams.get('ogTitle') || searchParams.get('title') || '';
    const cardTitle = (searchParams.get('cardTitle') || '').trim();
    const saveTarget = (searchParams.get('saveTarget') as 'daily' | 'my') || 'daily';

    // Firebase ID Token 검증 (기존 uid 파라미터 대신 token 파라미터 사용)
    const token = searchParams.get('token') || '';
    const authResult = await verifyMemberFromParam(token);
    if (authResult instanceof NextResponse) return authResult;
    const { uid } = authResult;
    if (!url) return NextResponse.json({ error: 'URL is required' }, { status: 400 });
    if (saveTarget === 'my' && !cardTitle) {
      return NextResponse.json({ error: '제목을 입력해주세요.' }, { status: 400 });
    }

    // OG fetch (title이 없을 때만)
    const finalOgTitle = ogTitle || (await fetchOGMeta(url)).title;

    if (saveTarget === 'daily') {
      return await saveToDailyNote({ url, ogTitle: finalOgTitle, cardTitle, uid });
    } else {
      return await saveToMyNote({ url, ogTitle: finalOgTitle, cardTitle, uid });
    }
  } catch (error) {
    console.error('[share-target] Error:', error);
    return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
  }
}

/** Daily Note에 번호 감지 후 append */
async function saveToDailyNote({
  url, ogTitle, cardTitle, uid,
}: { url: string; ogTitle: string; cardTitle: string; uid: string }) {
  const docId = getDailyDocId(uid);
  const docRef = adminDb.collection('documents').doc(docId);
  const docSnap = await docRef.get();

  if (!docSnap.exists) {
    let userName = 'Anonymous';
    try {
      const userSnap = await adminDb.collection('users').doc(uid).get();
      if (userSnap.exists) {
        const uData = userSnap.data();
        userName = uData?.customName || uData?.displayName || uData?.email?.split('@')[0] || 'Anonymous';
      }
    } catch (e) { console.error('user fetch error', e); }

    const dateStr = getKSTDateStr();
    const line = buildDailyLine(url, ogTitle, cardTitle, 1);
    await docRef.set({
      title: dateStr,
      content: line,
      visibility: 'private',
      authorId: uid,
      authorName: userName,
      docType: 'daily',
      isDeleted: false,
      createdAt: FieldValue.serverTimestamp(),
      updatedAt: FieldValue.serverTimestamp(),
    });
  } else {
    const existingContent: string = docSnap.data()!.content || '';
    const nextNum = detectNextNumber(existingContent);
    const line = buildDailyLine(url, ogTitle, cardTitle, nextNum);
    await docRef.update({
      content: existingContent.trimEnd() + '\n' + line,
      updatedAt: FieldValue.serverTimestamp(),
    });
  }

  // savedLinks 인덱스
  await indexSavedLink({ url, ogTitle, uid, docId, saveTarget: 'daily' });
  return NextResponse.json({ success: true, docId, redirectUrl: `/docs/${docId}` });
}

/** My 노트: 제목으로 기존 문서 검색 → 있으면 append, 없으면 생성 */
async function saveToMyNote({
  url, ogTitle, cardTitle, uid,
}: { url: string; ogTitle: string; cardTitle: string; uid: string }) {
  const docsRef = adminDb.collection('documents');
  let docId = '';

  await adminDb.runTransaction(async (transaction: FirebaseFirestore.Transaction) => {
    // 1. 해당 유저가 만든 동일 제목의 위키(My) 문서 검색
    const querySnap = await transaction.get(
      docsRef
        .where('authorId', '==', uid)
        .where('title', '==', cardTitle)
        .limit(5)
    );

    let existingDoc = null;
    if (!querySnap.empty) {
      existingDoc = querySnap.docs.find(d => (d.data() as any).isDeleted !== true);
    }

    if (existingDoc) {
      // 2. 발견 시 기존 내용에 append
      docId = existingDoc.id;
      const existingContent = (existingDoc.data() as any).content || '';
      const nextNum = detectNextNumber(existingContent);
      const line = buildMyLine(url, ogTitle, nextNum);

      transaction.update(existingDoc.ref, {
        content: existingContent.trimEnd() + '\n' + line,
        updatedAt: FieldValue.serverTimestamp(),
      });
    } else {
      // 3. 없으면 새 문서 생성
      const newDocRef = docsRef.doc();
      docId = newDocRef.id;

      // 사용자 정보 가져오기 (비동기 병렬 요청 가능하므로 트랜잭션 내에서 처리 권장)
      let userName = 'Anonymous';
      try {
        const userDocRef = adminDb.collection('users').doc(uid);
        const userSnap: any = await transaction.get(userDocRef);
        if (userSnap.exists) {
          const uData = userSnap.data();
          userName = uData?.customName || uData?.displayName || uData?.email?.split('@')[0] || 'Anonymous';
        }
      } catch (e) { console.error('user fetch error', e); }

      const line = buildMyLine(url, ogTitle, 1);
      transaction.set(newDocRef, {
        title: cardTitle,
        content: line,
        visibility: 'private',
        authorId: uid,
        authorName: userName,
        docType: 'wiki',   // My 노트는 wiki 타입이지만 visibility=private으로 My탭에 표시
        isDeleted: false,
        createdAt: FieldValue.serverTimestamp(),
        updatedAt: FieldValue.serverTimestamp(),
      });
    }
  });

  // savedLinks 인덱스 추가는 트랜잭션 밖에서 가볍게 처리
  await indexSavedLink({ url, ogTitle, uid, docId, saveTarget: 'my' });
  return NextResponse.json({ success: true, docId, redirectUrl: `/docs/${docId}` });
}

/** savedLinks 인덱스 저장 */
async function indexSavedLink({
  url, ogTitle, uid, docId, saveTarget,
}: { url: string; ogTitle: string; uid: string; docId: string; saveTarget: string }) {
  await adminDb.collection('users').doc(uid).collection('savedLinks').add({
    url,
    sourceTitle: ogTitle,
    sourceDomain: (() => { try { return new URL(url).hostname; } catch { return ''; } })(),
    savedAt: FieldValue.serverTimestamp(),
    ownerUid: uid,
    targetDoc: saveTarget,
    docId,
  });
}
