import { PrismaClient } from '@prisma/client'
import * as fs from 'fs'
import * as path from 'path'
import pdfParse from 'pdf-parse'

const prisma = new PrismaClient()

interface BibleVerse {
  book: string
  chapter: number
  verse: number
  text: string
}

interface BibleBook {
  name: string
  testament: string
  orderNum: number
}

// Romanian Bible book names mapping
const romanianBooks: BibleBook[] = [
  // Old Testament
  { name: 'Geneza', testament: 'Vechiul Testament', orderNum: 1 },
  { name: 'Exodul', testament: 'Vechiul Testament', orderNum: 2 },
  { name: 'Leviticul', testament: 'Vechiul Testament', orderNum: 3 },
  { name: 'Numerii', testament: 'Vechiul Testament', orderNum: 4 },
  { name: 'Deuteronomul', testament: 'Vechiul Testament', orderNum: 5 },
  { name: 'Iosua', testament: 'Vechiul Testament', orderNum: 6 },
  { name: 'Judecătorii', testament: 'Vechiul Testament', orderNum: 7 },
  { name: 'Rut', testament: 'Vechiul Testament', orderNum: 8 },
  { name: '1 Samuel', testament: 'Vechiul Testament', orderNum: 9 },
  { name: '2 Samuel', testament: 'Vechiul Testament', orderNum: 10 },
  { name: '1 Regi', testament: 'Vechiul Testament', orderNum: 11 },
  { name: '2 Regi', testament: 'Vechiul Testament', orderNum: 12 },
  { name: '1 Cronici', testament: 'Vechiul Testament', orderNum: 13 },
  { name: '2 Cronici', testament: 'Vechiul Testament', orderNum: 14 },
  { name: 'Ezra', testament: 'Vechiul Testament', orderNum: 15 },
  { name: 'Neemia', testament: 'Vechiul Testament', orderNum: 16 },
  { name: 'Estera', testament: 'Vechiul Testament', orderNum: 17 },
  { name: 'Iov', testament: 'Vechiul Testament', orderNum: 18 },
  { name: 'Psalmii', testament: 'Vechiul Testament', orderNum: 19 },
  { name: 'Proverbele', testament: 'Vechiul Testament', orderNum: 20 },
  { name: 'Ecleziastul', testament: 'Vechiul Testament', orderNum: 21 },
  { name: 'Cântarea Cântărilor', testament: 'Vechiul Testament', orderNum: 22 },
  { name: 'Isaia', testament: 'Vechiul Testament', orderNum: 23 },
  { name: 'Ieremia', testament: 'Vechiul Testament', orderNum: 24 },
  { name: 'Plângerile', testament: 'Vechiul Testament', orderNum: 25 },
  { name: 'Ezechiel', testament: 'Vechiul Testament', orderNum: 26 },
  { name: 'Daniel', testament: 'Vechiul Testament', orderNum: 27 },
  { name: 'Osea', testament: 'Vechiul Testament', orderNum: 28 },
  { name: 'Ioel', testament: 'Vechiul Testament', orderNum: 29 },
  { name: 'Amos', testament: 'Vechiul Testament', orderNum: 30 },
  { name: 'Obadia', testament: 'Vechiul Testament', orderNum: 31 },
  { name: 'Iona', testament: 'Vechiul Testament', orderNum: 32 },
  { name: 'Mica', testament: 'Vechiul Testament', orderNum: 33 },
  { name: 'Naum', testament: 'Vechiul Testament', orderNum: 34 },
  { name: 'Habacuc', testament: 'Vechiul Testament', orderNum: 35 },
  { name: 'Ţefania', testament: 'Vechiul Testament', orderNum: 36 },
  { name: 'Hagai', testament: 'Vechiul Testament', orderNum: 37 },
  { name: 'Zaharia', testament: 'Vechiul Testament', orderNum: 38 },
  { name: 'Maleahi', testament: 'Vechiul Testament', orderNum: 39 },

  // New Testament
  { name: 'Matei', testament: 'Noul Testament', orderNum: 40 },
  { name: 'Marcu', testament: 'Noul Testament', orderNum: 41 },
  { name: 'Luca', testament: 'Noul Testament', orderNum: 42 },
  { name: 'Ioan', testament: 'Noul Testament', orderNum: 43 },
  { name: 'Faptele Apostolilor', testament: 'Noul Testament', orderNum: 44 },
  { name: 'Romani', testament: 'Noul Testament', orderNum: 45 },
  { name: '1 Corinteni', testament: 'Noul Testament', orderNum: 46 },
  { name: '2 Corinteni', testament: 'Noul Testament', orderNum: 47 },
  { name: 'Galateni', testament: 'Noul Testament', orderNum: 48 },
  { name: 'Efeseni', testament: 'Noul Testament', orderNum: 49 },
  { name: 'Filipeni', testament: 'Noul Testament', orderNum: 50 },
  { name: 'Coloseni', testament: 'Noul Testament', orderNum: 51 },
  { name: '1 Tesaloniceni', testament: 'Noul Testament', orderNum: 52 },
  { name: '2 Tesaloniceni', testament: 'Noul Testament', orderNum: 53 },
  { name: '1 Timotei', testament: 'Noul Testament', orderNum: 54 },
  { name: '2 Timotei', testament: 'Noul Testament', orderNum: 55 },
  { name: 'Tit', testament: 'Noul Testament', orderNum: 56 },
  { name: 'Filimon', testament: 'Noul Testament', orderNum: 57 },
  { name: 'Evrei', testament: 'Noul Testament', orderNum: 58 },
  { name: 'Iacob', testament: 'Noul Testament', orderNum: 59 },
  { name: '1 Petru', testament: 'Noul Testament', orderNum: 60 },
  { name: '2 Petru', testament: 'Noul Testament', orderNum: 61 },
  { name: '1 Ioan', testament: 'Noul Testament', orderNum: 62 },
  { name: '2 Ioan', testament: 'Noul Testament', orderNum: 63 },
  { name: '3 Ioan', testament: 'Noul Testament', orderNum: 64 },
  { name: 'Iuda', testament: 'Noul Testament', orderNum: 65 },
  { name: 'Apocalipsa', testament: 'Noul Testament', orderNum: 66 }
]

function parseRomanianBible(text: string): BibleVerse[] {
  const verses: BibleVerse[] = []

  // Remove common headers/footers and normalize text
  const cleanText = text
    .replace(/BIBLIA\s+FIDELA/gi, '')
    .replace(/Copyright.*?România/gi, '')
    .replace(/Cluj-Napoca.*?\d{4}/gi, '')
    .replace(/\d+\s*$/gm, '') // Remove page numbers at end of lines
    .replace(/\s+/g, ' ') // Normalize whitespace
    .trim()

  console.log('Cleaned text preview:', cleanText.substring(0, 2000))

  // Look for patterns like "Geneza 1:1" or "1:1" with verse text
  // First, split by book names to identify sections
  const bookSections: { book: string, content: string }[] = []

  let currentContent = cleanText

  for (const book of romanianBooks) {
    // Look for book name followed by chapter/verse patterns
    const bookPattern = new RegExp(`\\b${book.name}\\b`, 'gi')
    const bookMatch = currentContent.search(bookPattern)

    if (bookMatch !== -1) {
      // Extract content for this book (until next book or end)
      let nextBookStart = currentContent.length

      for (const nextBook of romanianBooks) {
        if (nextBook.orderNum > book.orderNum) {
          const nextPattern = new RegExp(`\\b${nextBook.name}\\b`, 'gi')
          const nextMatch = currentContent.search(nextPattern)
          if (nextMatch > bookMatch && nextMatch < nextBookStart) {
            nextBookStart = nextMatch
          }
        }
      }

      const bookContent = currentContent.substring(bookMatch, nextBookStart)
      bookSections.push({ book: book.name, content: bookContent })
    }
  }

  console.log(`Found ${bookSections.length} book sections`)

  // Parse each book section
  for (const section of bookSections) {
    console.log(`Parsing ${section.book}...`)

    // Look for chapter:verse patterns like "1:1", "1:2", etc.
    const versePattern = /(\d+):(\d+)\s+([^0-9:]+?)(?=\d+:\d+|$)/g
    let match

    while ((match = versePattern.exec(section.content)) !== null) {
      const chapter = parseInt(match[1])
      const verse = parseInt(match[2])
      const text = match[3].trim()

      // Clean up the verse text
      const cleanVerseText = text
        .replace(/\s+/g, ' ')
        .replace(/^\W+|\W+$/g, '') // Remove leading/trailing non-word chars
        .trim()

      if (cleanVerseText.length > 5) { // Only keep substantial text
        verses.push({
          book: section.book,
          chapter: chapter,
          verse: verse,
          text: cleanVerseText
        })
      }
    }

    // Alternative: look for numbered verses within paragraphs
    const numberedVersePattern = /(\d+)\s+([^0-9]+?)(?=\d+\s+|$)/g
    let altMatch
    let currentChapter = 1

    // Try to find chapter indicators
    const chapterPattern = /Capitolul\s+(\d+)|^(\d+)$/gm
    const chapterMatches = [...section.content.matchAll(chapterPattern)]

    if (chapterMatches.length > 0) {
      for (const chMatch of chapterMatches) {
        currentChapter = parseInt(chMatch[1] || chMatch[2])

        // Find content after this chapter marker
        const chapterStart = chMatch.index! + chMatch[0].length
        let chapterEnd = section.content.length

        // Find next chapter marker
        for (const nextChMatch of chapterMatches) {
          if (nextChMatch.index! > chMatch.index! && nextChMatch.index! < chapterEnd) {
            chapterEnd = nextChMatch.index!
          }
        }

        const chapterContent = section.content.substring(chapterStart, chapterEnd)

        // Parse verses in this chapter
        while ((altMatch = numberedVersePattern.exec(chapterContent)) !== null) {
          const verseNum = parseInt(altMatch[1])
          const verseText = altMatch[2].trim()

          const cleanText = verseText
            .replace(/\s+/g, ' ')
            .replace(/^\W+|\W+$/g, '')
            .trim()

          if (cleanText.length > 10) {
            verses.push({
              book: section.book,
              chapter: currentChapter,
              verse: verseNum,
              text: cleanText
            })
          }
        }
      }
    }
  }

  return verses
}

async function importRomanianBible() {
  console.log('Starting Romanian Bible import...')

  const pdfPath = path.join(process.cwd(), 'bibles', 'Biblia-Fidela-limba-romana.pdf')

  if (!fs.existsSync(pdfPath)) {
    throw new Error(`PDF file not found at: ${pdfPath}`)
  }

  console.log('Reading PDF file...')
  const pdfBuffer = fs.readFileSync(pdfPath)
  const pdfData = await pdfParse(pdfBuffer)

  console.log(`PDF parsed. Text length: ${pdfData.text.length} characters`)

  console.log('Parsing Bible verses...')
  const verses = parseRomanianBible(pdfData.text)
  console.log(`Found ${verses.length} verses`)

  if (verses.length === 0) {
    console.log('No verses found. PDF content preview:')
    console.log(pdfData.text.substring(0, 1000))
    throw new Error('Could not parse any verses from the PDF')
  }

  try {
    // First, create all books
    console.log('Creating Bible books...')
    for (const bookData of romanianBooks) {
      await prisma.bibleBook.upsert({
        where: { id: bookData.orderNum },
        update: {},
        create: {
          id: bookData.orderNum,
          name: bookData.name,
          testament: bookData.testament,
          orderNum: bookData.orderNum
        }
      })
    }

    // Group verses by book and chapter
    const versesByBook = verses.reduce((acc, verse) => {
      if (!acc[verse.book]) acc[verse.book] = {}
      if (!acc[verse.book][verse.chapter]) acc[verse.book][verse.chapter] = []
      acc[verse.book][verse.chapter].push(verse)
      return acc
    }, {} as Record<string, Record<number, BibleVerse[]>>)

    console.log('Importing verses by book and chapter...')
    let totalImported = 0

    for (const [bookName, chapters] of Object.entries(versesByBook)) {
      const book = romanianBooks.find(b => b.name === bookName)
      if (!book) {
        console.warn(`Unknown book: ${bookName}`)
        continue
      }

      console.log(`Importing ${bookName}...`)

      for (const [chapterNumStr, chapterVerses] of Object.entries(chapters)) {
        const chapterNum = parseInt(chapterNumStr)

        // Create chapter
        const chapter = await prisma.bibleChapter.upsert({
          where: {
            bookId_chapterNum: {
              bookId: book.orderNum,
              chapterNum: chapterNum
            }
          },
          update: {},
          create: {
            bookId: book.orderNum,
            chapterNum: chapterNum
          }
        })

        // Create verses
        for (const verse of chapterVerses) {
          await prisma.bibleVerse.upsert({
            where: {
              chapterId_verseNum_version: {
                chapterId: chapter.id,
                verseNum: verse.verse,
                version: 'RO'
              }
            },
            update: {},
            create: {
              chapterId: chapter.id,
              verseNum: verse.verse,
              text: verse.text,
              version: 'RO'
            }
          })
          totalImported++
        }
      }
    }

    console.log(`Romanian Bible import completed! Imported ${totalImported} verses.`)

    // Create search function
    console.log('Creating search function...')
    await prisma.$executeRaw`
      CREATE OR REPLACE FUNCTION search_verses(search_query TEXT, limit_count INT DEFAULT 10)
      RETURNS TABLE(
        verse_id TEXT,
        book_name TEXT,
        chapter_num INT,
        verse_num INT,
        verse_text TEXT,
        rank REAL
      ) AS $$
      BEGIN
        RETURN QUERY
        SELECT
          v.id::TEXT,
          b.name,
          c."chapterNum",
          v."verseNum",
          v.text,
          CASE
            WHEN v.text ILIKE '%' || search_query || '%' THEN 1.0
            ELSE ts_rank(to_tsvector('romanian', v.text), plainto_tsquery('romanian', search_query))
          END as rank
        FROM "BibleVerse" v
        JOIN "BibleChapter" c ON v."chapterId" = c.id
        JOIN "BibleBook" b ON c."bookId" = b.id
        WHERE v.text ILIKE '%' || search_query || '%'
           OR to_tsvector('romanian', v.text) @@ plainto_tsquery('romanian', search_query)
        ORDER BY rank DESC, b."orderNum", c."chapterNum", v."verseNum"
        LIMIT limit_count;
      END;
      $$ LANGUAGE plpgsql;
    `

    console.log('Search function created successfully!')

  } catch (error) {
    console.error('Error importing Romanian Bible:', error)
    throw error
  }
}

// Run the import
importRomanianBible()
  .then(() => {
    console.log('Romanian Bible import completed successfully!')
    process.exit(0)
  })
  .catch((error) => {
    console.error('Import failed:', error)
    process.exit(1)
  })
  .finally(() => prisma.$disconnect())