import OpenAI from "openai";
import { z } from "zod";
import { db } from "./db";
import { eq } from "drizzle-orm";
import {
  sessions,
  speakers,
  sessionSpeakers,
  transcriptions,
  userSessions,
} from "@shared/schema";
import type { Session, Speaker, Transcription } from "@shared/schema";

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

const chatResponseSchema = z.object({
  answer: z.string(),
  confidence: z.number().min(0).max(1),
});

// Function to get dynamic data from database
async function getDynamicScopeData() {
  try {
    // Fetch approved transcriptions
    const transcriptionResults = await db
      .select()
      .from(transcriptions)
      .where(eq(transcriptions.status, "accepted"));

    // First fetch all sessions
    const allSessions = await db.select().from(sessions);

    // Then fetch all speakers
    const allSpeakers = await db.select().from(speakers);

    // Fetch session-speaker relationships
    const sessionSpeakerLinks = await db.select().from(sessionSpeakers);

    // Create a map of speakers by session ID using the junction table
    const speakersBySession = sessionSpeakerLinks.reduce(
      (acc: Record<number, Speaker[]>, link) => {
        if (!acc[link.sessionId]) {
          acc[link.sessionId] = [];
        }
        const speaker = allSpeakers.find((s) => s.id === link.speakerId);
        if (speaker) {
          acc[link.sessionId].push(speaker);
        }
        return acc;
      },
      {},
    );

    // Process sessions with their speakers
    const processedSessions = allSessions.map((session) => ({
      ...session,
      speakers: speakersBySession[session.id] || [],
    }));

    return {
      sessions: processedSessions.map((session) => ({
        title: session.sessionTitle,
        titleAr: session.sessionTitleAr,
        date: session.sessionDate,
        time: session.sessionTime,
        venue: session.venue,
        venueAr: session.venueAr,
        type: session.sessionType,
        id: session.id, // Added session ID
        speakers: session.speakers.map((speaker: Speaker) => ({
          name: speaker.name,
          nameAr: speaker.nameAr,
          title: speaker.title,
          titleAr: speaker.titleAr,
          organization: speaker.organization,
          organizationAr: speaker.organizationAr,
        })),
      })),
      speakers: allSpeakers.map((speaker) => ({
        name: speaker.name,
        nameAr: speaker.nameAr,
        title: speaker.title,
        titleAr: speaker.titleAr,
        organization: speaker.organization,
        organizationAr: speaker.organizationAr,
        bio: speaker.bio,
        bioAr: speaker.bioAr,
      })),
      transcriptions: transcriptionResults.map((trans) => ({
        originalText: trans.originalText,
        translatedText: trans.translatedText,
        sessionId: trans.sessionId,
        createdAt: trans.createdAt,
      })),
    };
  } catch (error) {
    console.error("Error fetching dynamic scope data:", error);
    return null;
  }
}

interface ScopeData {
  title?: string;
  overview?: {
    description_en: string;
    description_ar: string;
  };
  topics?: Array<{
    name: string;
    details: string[];
  }>;
  sessions?: any[];
  speakers?: any[];
  transcriptions?: any[];
  news?: any[]; // Added news property
}

// Helper function to wrap venue links in HTML
function formatVenueLink(text: string, language: string): string {
  const venueLink = "https://maps.app.goo.gl/41BfYx3ahqMx6GmDA";
  const linkText = language === "ar" ? "عرض الموقع" : "View Location";

  // Check for markdown style links first
  const markdownLinkRegex = /\[(.*?)\]\((.*?)\)/;
  if (markdownLinkRegex.test(text)) {
    return text.replace(markdownLinkRegex, '').trim() + `\n<button class="venue-link w-full" data-url="${venueLink}">${linkText}</button>`;
  }

  // Check for venue mentions
  if (
    text.toLowerCase().includes("venue") ||
    text.toLowerCase().includes("location") ||
    text.includes("موقع") ||
    text.includes("مكان") ||
    text.includes("QNCC") ||
    text.includes("Qatar National Convention Centre")
  ) {
    return `${text}\n<button class="venue-link w-full" data-url="${venueLink}">${linkText}</button>`;
  }

  return text;
}

// Function to format session link as a button
function formatSessionLink(session: any, language: string): string {
  const linkText = language === "ar" ? "مشاهدة البث المباشر" : "Watch Live Stream";
  return `${session.title}\n<button class="stream-link w-full" data-url="/live-stream/${session.id}">${linkText}</button>`;
}

// Add new link formatting functions
function formatLiveStreamLink(session: any, language: string): string {
  const linkText = language === "ar" ? "مشاهدة البث المباشر" : "Watch Live Stream";
  return `${session.title}\n<button class="stream-link w-full" data-url="/live-stream/${session.id}">${linkText}</button>`;
}

function formatNewsLink(news: any, language: string): string {
  const linkText = language === "ar" ? "قراءة المزيد" : "Read More";
  return `${language === "ar" ? news.titleAr : news.title}\n<button class="news-link w-full" data-url="/news/${news.id}">${linkText}</button>`;
}


// Function to get user's accessible sessions
async function getUserSessions(userId: number | undefined) {
  if (!userId) return [];

  // Get all main sessions and user's breakout sessions
  const userAccessibleSessions = await db
    .select()
    .from(sessions)
    .leftJoin(userSessions, eq(sessions.id, userSessions.sessionId))
    .where(
      eq(sessions.sessionType, 'main').or(
        eq(userSessions.userId, userId)
      )
    );

  return userAccessibleSessions;
}

// Add new helper function for formatting session details
function formatSessionDetails(session: any, language: string): string {
  const speakersList = session.speakers
    .map((speaker: any) =>
      language === "ar"
        ? `${speaker.nameAr} - ${speaker.titleAr}`
        : `${speaker.name} - ${speaker.title}`
    )
    .join("\n");

  const details = language === "ar"
    ? `🎤 الجلسة: ${session.titleAr}\n📅 التاريخ: ${session.date}\n⏰ الوقت: ${session.time}\n📍 المكان: ${session.venueAr}\n\n👥 المتحدثون:\n${speakersList}`
    : `🎤 Session: ${session.title}\n📅 Date: ${session.date}\n⏰ Time: ${session.time}\n📍 Venue: ${session.venue}\n\n👥 Speakers:\n${speakersList}`;

  return `${details}\n<button class="session-link w-full" data-url="/session/${session.id}">${language === "ar" ? "عرض التفاصيل" : "View Details"}</button>`;
}

// Modify findAnswerInScope to handle session-specific queries
function findAnswerInScope(
  query: string,
  language: string = "en",
  scopeData: ScopeData[]
): string | null {
  const lowerCaseQuery = query.toLowerCase();

  // Check for specific query types
  const sessionKeywords = language === "ar"
    ? ["جلسة", "محاضرة", "برنامج"]
    : ["session", "talk", "presentation", "schedule"];

  const liveStreamKeywords = language === "ar"
    ? ["بث", "مباشر", "مشاهدة"]
    : ["stream", "live", "watch"];

  const newsKeywords = language === "ar"
    ? ["أخبار", "مقال"]
    : ["news", "article"];

  const speakerKeywords = language === "ar"
    ? ["متحدث", "المحاضر", "المتكلم"]
    : ["speaker", "presenter", "panelist"];

  const isSessionQuery = sessionKeywords.some(keyword =>
    lowerCaseQuery.includes(keyword.toLowerCase())
  );

  const isLiveStreamQuery = liveStreamKeywords.some(keyword =>
    lowerCaseQuery.includes(keyword.toLowerCase())
  );

  const isNewsQuery = newsKeywords.some(keyword =>
    lowerCaseQuery.includes(keyword.toLowerCase())
  );

  const isSpeakerQuery = speakerKeywords.some(keyword =>
    lowerCaseQuery.includes(keyword.toLowerCase())
  );

  for (const section of scopeData) {
    // Handle live stream queries
    if (isLiveStreamQuery && section.sessions) {
      const availableSessions = section.sessions.filter(session =>
        session.liveStreamUrl && new Date(session.date) >= new Date()
      );

      if (availableSessions.length > 0) {
        const sessionsList = availableSessions
          .map(session => formatLiveStreamLink(session, language))
          .join("\n\n");

        return language === "ar"
          ? `الجلسات المتاحة للبث المباشر:\n${sessionsList}`
          : `Available live sessions:\n${sessionsList}`;
      }
    }

    // Handle news queries
    if (isNewsQuery && section.news) {
      const relevantNews = section.news.filter(news =>
        (language === "ar" ? news.titleAr : news.title)
          .toLowerCase()
          .includes(lowerCaseQuery)
      );

      if (relevantNews.length > 0) {
        const newsList = relevantNews
          .map(news => formatNewsLink(news, language))
          .join("\n\n");

        return language === "ar"
          ? `الأخبار المتعلقة:\n${newsList}`
          : `Related news:\n${newsList}`;
      }
    }

    // Handle session and speaker queries (keep existing code)
    if (section.sessions) {
      if (isSessionQuery || isSpeakerQuery) {
        const matchingSession = section.sessions.find((session) => {
          const sessionText = language === "ar"
            ? `${session.titleAr} ${session.venueAr}`
            : `${session.title} ${session.venue}`;

          const titleMatch = sessionText.toLowerCase().includes(lowerCaseQuery);
          const speakerMatch = session.speakers?.some((speaker: any) => {
            const speakerText = language === "ar"
              ? `${speaker.nameAr} ${speaker.titleAr} ${speaker.organizationAr}`
              : `${speaker.name} ${speaker.title} ${speaker.organization}`;
            return speakerText.toLowerCase().includes(lowerCaseQuery);
          });

          return titleMatch || speakerMatch;
        });

        if (matchingSession) {
          // Check for related transcriptions
          const sessionTranscriptions = section.transcriptions?.filter(
            (trans) => trans.sessionId === matchingSession.id
          );

          let transcriptionText = "";
          if (sessionTranscriptions && sessionTranscriptions.length > 0) {
            transcriptionText = language === "ar"
              ? "\n\n💬 يتوفر نص محاضرة لهذه الجلسة"
              : "\n\n💬 Transcription available for this session";
          }

          // Format session details with transcription info
          const speakersList = matchingSession.speakers
            .map((speaker: any) =>
              language === "ar"
                ? `${speaker.nameAr}\n📋 ${speaker.titleAr}\n🏢 ${speaker.organizationAr}`
                : `${speaker.name}\n📋 ${speaker.title}\n🏢 ${speaker.organization}`
            )
            .join("\n\n");

          const details = language === "ar"
            ? `🎤 الجلسة: ${matchingSession.titleAr}\n📅 التاريخ: ${matchingSession.date}\n⏰ الوقت: ${matchingSession.time}\n📍 المكان: ${matchingSession.venueAr}\n\n👥 المتحدثون:\n${speakersList}${transcriptionText}`
            : `🎤 Session: ${matchingSession.title}\n📅 Date: ${matchingSession.date}\n⏰ Time: ${matchingSession.time}\n📍 Venue: ${matchingSession.venue}\n\n👥 Speakers:\n${speakersList}${transcriptionText}`;

          return `${details}\n<button class="session-link w-full" data-url="/session/${matchingSession.id}">${language === "ar" ? "عرض التفاصيل" : "View Details"}</button>`;
        }
      }
    }

    // Check speakers independently
    if (section.speakers && isSpeakerQuery) {
      const matchingSpeaker = section.speakers.find((speaker) => {
        const speakerText = language === "ar"
          ? `${speaker.nameAr} ${speaker.titleAr} ${speaker.organizationAr}`
          : `${speaker.name} ${speaker.title} ${speaker.organization}`;
        return speakerText.toLowerCase().includes(lowerCaseQuery);
      });

      if (matchingSpeaker) {
        const response = language === "ar"
          ? `👤 المتحدث: ${matchingSpeaker.nameAr}\n📋 المنصب: ${matchingSpeaker.titleAr}\n🏢 المؤسسة: ${matchingSpeaker.organizationAr}\n\n📝 نبذة:\n${matchingSpeaker.bioAr}`
          : `👤 Speaker: ${matchingSpeaker.name}\n📋 Title: ${matchingSpeaker.title}\n🏢 Organization: ${matchingSpeaker.organization}\n\n📝 Bio:\n${matchingSpeaker.bio}`;
        return formatVenueLink(response, language);
      }
    }

    // Check transcriptions
    if (section.transcriptions) {
      const matchingTranscription = section.transcriptions.find((trans) => {
        const transText = language === "ar" ? trans.originalText : trans.translatedText;
        return transText.toLowerCase().includes(lowerCaseQuery);
      });

      if (matchingTranscription) {
        return formatVenueLink(
          language === "ar"
            ? matchingTranscription.originalText
            : matchingTranscription.translatedText,
          language
        );
      }
    }

    // Check basic info
    if (section.overview) {
      const description = language === "ar"
        ? section.overview.description_ar
        : section.overview.description_en;
      if (description.toLowerCase().includes(lowerCaseQuery)) {
        return formatVenueLink(description, language);
      }
    }

    // Check topic details
    if (section.topics) {
      for (const topic of section.topics) {
        for (const detail of topic.details || []) {
          const [en, ar] = detail.split(" | ");
          const text = language === "ar" ? ar : en;
          if (text.toLowerCase().includes(lowerCaseQuery)) {
            return formatVenueLink(text, language);
          }
        }
      }
    }
  }

  return null;
}


const matchesQuery = (text: string) =>
  text.toLowerCase().includes(lowerCaseQuery);


export async function handleChatbotQuery(
  query: string,
  language: string = "en",
  userId?: number
): Promise<{ answer: string; confidence: number }> {
  try {
    // Get dynamic data including user sessions
    const dynamicData = await getDynamicScopeData();
    const userSessions = await getUserSessions(userId);

    // Define keywords for different types of queries
    const liveStreamKeywords = language === "ar"
      ? ["بث", "مباشر", "مشاهدة"]
      : ["stream", "live", "watch"];

    const isLiveStreamQuery = liveStreamKeywords.some(keyword =>
      query.toLowerCase().includes(keyword.toLowerCase())
    );

    // Only check live stream access if specifically asking about watching/streaming
    if (isLiveStreamQuery) {
      if (userSessions.length === 0) {
        return {
          answer: language === "ar"
            ? "عذراً، لا يوجد لديك حالياً جلسات يمكنك مشاهدتها."
            : "Sorry, you don't have any sessions available to watch at the moment.",
          confidence: 1.0,
        };
      }

      const sessionsList = userSessions
        .map(session => formatSessionLink(session, language))
        .join("\n\n");

      return {
        answer: language === "ar"
          ? `الجلسات المتاحة لك:\n${sessionsList}`
          : `Your available sessions:\n${sessionsList}`,
        confidence: 1.0,
      };
    }

    // Create combined scope data for general queries
    const fullScopeData = [
      ...baseScopeData,
      {
        title: "Sessions and Speakers | الجلسات والمتحدثون",
        sessions: dynamicData?.sessions || [],
        speakers: dynamicData?.speakers || [],
        transcriptions: dynamicData?.transcriptions || [],
      },
    ];

    // Try to find an answer in our scope data
    const scopeAnswer = findAnswerInScope(query, language, fullScopeData);
    if (scopeAnswer) {
      return {
        answer: scopeAnswer,
        confidence: 1.0,
      };
    }

    // If no answer found in scope, use OpenAI
    const response = await openai.chat.completions.create({
      model: "gpt-4",
      messages: [
        {
          role: "system",
          content: `You are an AI assistant for the National Development Summit 2025.
Keep your responses under 150 words and focus only on the exact question asked.
Use bullet points for clarity when appropriate.
Respond in ${language === "ar" ? "Arabic" : "English"}.
Include specific session, speaker, or transcription details when relevant.
Format dates and times appropriately for ${language === "ar" ? "Arabic" : "English"} locale.

Use this contextual data to answer questions:
${JSON.stringify(fullScopeData, null, 2)}

Do not answer questions unrelated to:
- The summit and its sessions
- Speakers and their presentations
- Transcriptions from sessions
- Qatar's official policies
- Venue and logistics`
        },
        {
          role: "user",
          content: query
        }
      ],
      temperature: 0.7,
      max_tokens: 300
    });

    const content = response.choices[0].message.content;
    if (!content) {
      throw new Error("No response content received from OpenAI");
    }

    return {
      answer: content,
      confidence: 0.9
    };
  } catch (error: unknown) {
    const errorMessage =
      error instanceof Error ? error.message : "Unknown error occurred";
    throw new Error("Failed to process chat query: " + errorMessage);
  }
}

const baseScopeData = [
  {
    title: "National Development Summit 2025 | قمة التنمية الوطنية 2025",
    overview: {
      description_en:
        "The National Development Summit 2025 will be held at the Qatar National Convention Centre (QNCC) in Doha, Qatar, on March 8, 2025. This summit will bring together policymakers, business leaders, and industry experts to discuss economic development, social progress, and sustainability.",
      description_ar:
        "ستُعقد قمة التنمية الوطنية 2025 في مركز قطر الوطني للمؤتمرات (QNCC) في الدوحة، قطر، في 8 مارس 2025. ستجمع هذه القمة صانعي السياسات وقادة الأعمال والخبراء لمناقشة التنمية الاقتصادية والتقدم الاجتماعي والاستدامة.",
    },
    topics: [
      {
        name: "Event Details | تفاصيل الفعالية",
        details: [
          "📅 Date: March 12, 2025 | 📅 التاريخ: 12 مارس 2025",
          "📍 Venue: QNCC, Doha, Qatar | 📍 الموقع: مركز قطر الوطني للمؤتمرات (QNCC)، الدوحة، قطر",
          "🎤 Speakers: Top government officials, industry leaders | 🎤 المتحدثون: كبار المسؤولين الحكوميين وقادة الصناعة",
          "📝 Registration: Available online | 📝 التسجيل: متاح عبر الإنترنت",
          "💡 Key Topics: Economic diversification, sustainability, AI in governance | 💡 المواضيع الرئيسية: تنويع الاقتصاد، الاستدامة، الذكاء الاصطناعي في الحوكمة",
        ],
      },
    ],
  },
];