import express, { Request, Response } from "express";
import path from "path";
import multer from "multer";
import { GoogleGenAI, Type } from "@google/genai";
import { createServer as createViteServer } from "vite";
import dotenv from "dotenv";

dotenv.config();

const app = express();
const PORT = 3000;

// Lazy dynamic loader for pdf-parse to work in both ESM and CJS without using import.meta
let pdfParser: any = null;
async function parsePdf(buffer: Buffer): Promise<any> {
  if (!pdfParser) {
    const pdfModule = await import("pdf-parse") as any;
    pdfParser = pdfModule.default || pdfModule;
  }
  return pdfParser(buffer);
}

// Configure JSON body parser
app.use(express.json());

// Lazy initialization helper for Gemini API client
let aiClient: GoogleGenAI | null = null;

function getGeminiClient(): GoogleGenAI {
  const currentKey = process.env.GEMINI_API_KEY;
  if (!currentKey) {
    throw new Error("Gemini API Key is missing. Please configure it in Settings > Secrets.");
  }
  if (!aiClient) {
    aiClient = new GoogleGenAI({
      apiKey: currentKey,
      httpOptions: {
        headers: {
          "User-Agent": "aistudio-build",
        },
      },
    });
  }
  return aiClient;
}

// In-memory database for sermon text and translated segments
interface SermonReference {
  title: string;
  text: string;
  wordCount: number;
  uploadedAt: number;
}

interface QuranVerse {
  surahName: string;
  verseNumber: string;
  verifiedText: string;
}

interface SermonSegment {
  id: string;
  timestamp: number;
  originalText: string;
  englishTranslation: string;
  hindiTranslation: string;
  quranVerse: QuranVerse | null;
}

let activeSermon: SermonReference | null = null;
let activeSegments: SermonSegment[] = [];

// Multer setup using Memory Storage for clean file handling
const upload = multer({
  storage: multer.memoryStorage(),
  limits: { fileSize: 10 * 1024 * 1024 }, // 10MB limit
});

// ================= API ENDPOINTS =================

// 1. Get current active sermon reference and translated segments
app.get("/api/sermon/state", (req: Request, res: Response) => {
  res.json({
    activeSermon,
    segments: activeSegments,
  });
});

// 2. Upload PDF sermon reference
app.post("/api/sermon/upload", upload.single("file"), async (req: Request, res: Response) => {
  try {
    if (!req.file) {
      res.status(400).json({ error: "No file was uploaded." });
      return;
    }

    const title = req.file.originalname;
    let text = "";

    if (req.file.mimetype === "application/pdf") {
      const data = await parsePdf(req.file.buffer);
      text = data.text;
    } else if (req.file.mimetype === "text/plain") {
      text = req.file.buffer.toString("utf-8");
    } else {
      res.status(400).json({ error: "Unsupported file type. Please upload a PDF or TXT file." });
      return;
    }

    text = text.replace(/\s+/g, " ").trim();
    if (!text) {
      res.status(400).json({ error: "The file appears to be empty or contains no readable text." });
      return;
    }

    const wordCount = text.split(/\s+/).length;
    activeSermon = {
      title,
      text,
      wordCount,
      uploadedAt: Date.now(),
    };

    res.json({ success: true, activeSermon });
  } catch (error: any) {
    console.error("Error processing sermon upload:", error);
    res.status(500).json({ error: "Failed to parse the uploaded file." });
  }
});

// 3. Paste sermon reference text manually
app.post("/api/sermon/text", (req: Request, res: Response) => {
  try {
    const { title, text } = req.body;
    if (!text || !text.trim()) {
      res.status(400).json({ error: "Sermon text cannot be empty." });
      return;
    }

    const cleanText = text.replace(/\s+/g, " ").trim();
    const wordCount = cleanText.split(/\s+/).length;

    activeSermon = {
      title: title || "Pasted Sermon Text",
      text: cleanText,
      wordCount,
      uploadedAt: Date.now(),
    };

    res.json({ success: true, activeSermon });
  } catch (error: any) {
    res.status(500).json({ error: "Failed to save sermon text." });
  }
});

// 4. Clear active reference sermon
app.post("/api/sermon/clear", (req: Request, res: Response) => {
  activeSermon = null;
  res.json({ success: true });
});

// 5. Clear live translated segments (Reset)
app.post("/api/segments/clear", (req: Request, res: Response) => {
  activeSegments = [];
  res.json({ success: true });
});

// 6. Delete a specific segment
app.delete("/api/segments/:id", (req: Request, res: Response) => {
  const { id } = req.params;
  activeSegments = activeSegments.filter((seg) => seg.id !== id);
  res.json({ success: true });
});

// 7. Translate live Arabic speech segment and verify Quranic verses
app.post("/api/translate-and-verify", async (req: Request, res: Response) => {
  const { originalText } = req.body;
  if (!originalText || !originalText.trim()) {
    res.status(400).json({ error: "Speech text is empty." });
    return;
  }

  try {
    const currentKey = process.env.GEMINI_API_KEY;
    if (!currentKey) {
      // Return a graceful response if API key is missing
      res.status(400).json({
        error: "Gemini API Key is missing. Please configure it in Settings > Secrets.",
      });
      return;
    }

    const ai = getGeminiClient();

    // Prepare system instructions and prompt
    const referenceContext = activeSermon
      ? `Use this written sermon text as a reference/context to resolve homophones, match spoken phrases, and improve context-aware translations:
      --- REFERENCE SERMON ---
      ${activeSermon.text}
      ------------------------`
      : "No written sermon reference is available.";

    const systemInstruction = `You are an expert Islamic scholar, linguist, and translator. You receive real-time Arabic speech transcription segments from a Friday sermon (Khutbah).
Your tasks are:
1. Translate the spoken Arabic speech text accurately and elegantly into English and Hindi.
2. Check if the speech contains or is a quotation of any Quranic verse (Ayah), even if paraphrased or transcribed with errors.
3. If it contains a Quranic verse, identify the Surah name and Verse number(s), and retrieve the exact official Quranic text with full diacritics (tashkeel).
4. Return a clean, structured JSON response matching the required schema.

${referenceContext}`;

    const prompt = `Translate and verify this spoken Arabic segment:
"${originalText}"`;

    const response = await ai.models.generateContent({
      model: "gemini-3.5-flash",
      contents: prompt,
      config: {
        systemInstruction,
        responseMimeType: "application/json",
        responseSchema: {
          type: Type.OBJECT,
          properties: {
            englishTranslation: {
              type: Type.STRING,
              description: "Elegant, accurate English translation of the speech chunk.",
            },
            hindiTranslation: {
              type: Type.STRING,
              description: "Accurate Hindi translation of the speech chunk in Devanagari script.",
            },
            quranVerse: {
              type: Type.OBJECT,
              description: "Identified Quranic verse details. Return null if no verse is quoted in the speech.",
              properties: {
                surahName: {
                  type: Type.STRING,
                  description: "Surah Name in both Arabic and English (e.g., Al-Baqarah - البقرة)",
                },
                verseNumber: {
                  type: Type.STRING,
                  description: "Verse number or range (e.g., '183' or '183-184')",
                },
                verifiedText: {
                  type: Type.STRING,
                  description: "The complete, 100% correct Arabic text of the verse with full tashkeel (diacritics).",
                },
              },
              required: ["surahName", "verseNumber", "verifiedText"],
            },
          },
          required: ["englishTranslation", "hindiTranslation", "quranVerse"],
        },
      },
    });

    const resultText = response.text?.trim() || "{}";
    const resultJson = JSON.parse(resultText);

    const newSegment: SermonSegment = {
      id: "seg_" + Math.random().toString(36).substr(2, 9),
      timestamp: Date.now(),
      originalText: originalText.trim(),
      englishTranslation: resultJson.englishTranslation || "",
      hindiTranslation: resultJson.hindiTranslation || "",
      quranVerse: resultJson.quranVerse || null,
    };

    activeSegments.push(newSegment);
    res.json({ success: true, segment: newSegment });
  } catch (error: any) {
    console.error("Gemini API Error:", error);
    res.status(500).json({ error: "Failed to translate and verify speech. " + error.message });
  }
});

// ================= VITE INTEGRATION =================

async function startServer() {
  if (process.env.NODE_ENV !== "production") {
    const vite = await createViteServer({
      server: { middlewareMode: true },
      appType: "spa",
    });
    app.use(vite.middlewares);
  } else {
    const distPath = path.join(process.cwd(), "dist");
    app.use(express.static(distPath));
    app.get("*", (req, res) => {
      res.sendFile(path.join(distPath, "index.html"));
    });
  }

  app.listen(PORT, "0.0.0.0", () => {
    console.log(`Server running on http://localhost:${PORT}`);
  });
}

startServer();
