import {
  ANTHROPIC_API_URL,
  DEFAULT_CLAUDE_MODEL,
  MAX_TOKENS,
  debugLog,
  debugWarn
} from '../utils/constants';
import { condenseSourcesForClaude } from './sourceParser';

/**
 * Make a request to Claude API
 * @param {string} prompt - The prompt to send
 * @param {Array} messages - Optional message history
 * @returns {Promise<string>} Claude's response
 */
async function callClaude(prompt, messages = []) {
  const apiKey = import.meta.env.REACT_APP_ANTHROPIC_API_KEY;

  if (!apiKey || apiKey === 'sk-ant-your-key-here') {
    console.error('Anthropic API key not configured');
    return 'Please configure your Anthropic API key in .env.local';
  }

  const model = import.meta.env.REACT_APP_CLAUDE_MODEL || DEFAULT_CLAUDE_MODEL;
  debugLog('Using model:', model);
  debugLog('Max tokens:', MAX_TOKENS);
  debugLog('Prompt length:', prompt.length);
  debugLog('Previous messages:', messages.length);

  try {
    const requestBody = {
      apiKey: apiKey,
      model: model,
      maxTokens: MAX_TOKENS,
      messages: [
        ...messages,
        { role: 'user', content: prompt }
      ]
    };

    debugLog('Sending request to proxy...');
    debugLog('Request messages:', requestBody.messages.map(m => ({ role: m.role, contentLength: m.content.length })));

    // Use local proxy server instead of direct API call
    const response = await fetch('http://localhost:3001/api/claude', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(requestBody)
    });

    debugLog('Proxy response status:', response.status);

    if (!response.ok) {
      const error = await response.text();
      console.error('Proxy error response:', error);
      throw new Error(`Claude API error: ${response.status} - ${error}`);
    }

    const data = await response.json();
    debugLog('Response data structure:', Object.keys(data));
    debugLog('Response content:', data.content?.[0]?.text?.substring(0, 200) + '...');
    debugLog('Usage data:', data.usage);

    return {
      text: data.content[0].text,
      usage: data.usage // { input_tokens, output_tokens }
    };
  } catch (error) {
    console.error('Error calling Claude:', error);
    throw error;
  }
}

/**
 * Build briefing prompt with memory
 * @param {Object} currentData - Current source data
 * @param {Object} previousBriefing - Previous briefing object (condensed summary)
 * @returns {string} The prompt
 */
function buildBriefingPrompt(currentData, previousBriefing) {
  const customInstructions = import.meta.env.REACT_APP_CLAUDE_INSTRUCTIONS;

  let prompt = '';

  // Prepend custom instructions if provided
  if (customInstructions && customInstructions.trim()) {
    prompt += `CUSTOM INSTRUCTIONS: ${customInstructions}\n\n`;
  }

  prompt += `You are creating a personalized daily briefing. Be conversational and highlight what's interesting.

CURRENT DATA:
`;
  
  // CONDENSE DATA BEFORE SENDING TO CLAUDE
  const condensedData = condenseSourcesForClaude(currentData.sources || currentData);
  debugLog('Original data size:', JSON.stringify(currentData).length);
  debugLog('Condensed data size:', JSON.stringify(condensedData).length);
  debugLog('Size reduction:', Math.round((1 - JSON.stringify(condensedData).length / JSON.stringify(currentData).length) * 100) + '%');
  
  // Add all condensed source data
  Object.entries(condensedData).forEach(([source, data]) => {
    if (data && !data.error) {
      prompt += `\n${source.toUpperCase()}:\n${JSON.stringify(data, null, 2)}\n`;
    }
  });

  // Add historical context if available (now using condensed summary)
  if (previousBriefing && previousBriefing.condensedSummary) {
    prompt += `\n\nPREVIOUS BRIEFING SUMMARY:\n${previousBriefing.condensedSummary}\n`;
    prompt += `\nHighlight what's changed, any follow-up stories, or interesting trends.`;
  }

  prompt += `\n\nCreate a friendly briefing (300-400 words) that:
- Starts with a warm greeting appropriate for the time of day
- Highlights the most interesting items from the data
- Notes anything that's changed since yesterday (if applicable)
- Has personality and isn't just a dry list
- Includes relevant weather information if available
- Ends with something engaging or thought-provoking

Focus on the most newsworthy and interesting items. Don't try to mention everything.

IMPORTANT: Provide your response as valid JSON with exactly two fields:
{
  "fullBriefing": "Your complete 300-400 word friendly briefing text here",
  "condensedSummary": "A 50-75 word ultra-condensed summary of the key topics and main stories for historical context"
}

The JSON must be properly formatted with escaped quotes where necessary.`;

  return prompt;
}

/**
 * Generate a condensed summary of a briefing for historical storage
 * @param {string} fullBriefing - The full briefing text
 * @returns {Promise<string>} Condensed summary (50-75 words)
 */
async function generateCondensedSummary(fullBriefing) {
  const prompt = `Create an ultra-condensed summary of this briefing in 50-75 words.
Focus only on the key topics and main stories mentioned. 
This will be used as historical context for tomorrow's briefing generation.

FULL BRIEFING:
${fullBriefing}

Provide ONLY the condensed summary, no preamble or explanation.`;

  try {
    const result = await callClaude(prompt);
    return result.text;
  } catch (error) {
    console.error('Error generating condensed summary:', error);
    // Fallback to first 300 chars of original
    return fullBriefing.substring(0, 300) + '...';
  }
}

/**
 * Generate daily briefing with condensed summary
 * @param {Object} currentData - Current data from all sources
 * @param {Object} previousBriefing - Previous briefing for comparison
 * @returns {Promise<Object>} Object containing full briefing and condensed summary
 */
export async function generateBriefing(currentData, previousBriefing) {
  if (!currentData || Object.keys(currentData.sources || currentData).length === 0) {
    return {
      text: 'No data available to generate briefing. Please check your data sources configuration.',
      condensedSummary: 'No data available.'
    };
  }

  try {
    const prompt = buildBriefingPrompt(currentData, previousBriefing);
    const result = await callClaude(prompt);
    
    // Parse JSON response that now includes both fullBriefing and condensedSummary
    try {
      // Strip markdown code blocks if present
      let jsonText = result.text;
      if (jsonText.includes('```json')) {
        jsonText = jsonText.replace(/```json\s*/g, '').replace(/```\s*/g, '');
      } else if (jsonText.includes('```')) {
        jsonText = jsonText.replace(/```\s*/g, '');
      }
      jsonText = jsonText.trim();
      
      const parsed = JSON.parse(jsonText);
      
      // Validate the JSON structure
      if (!parsed.fullBriefing || !parsed.condensedSummary) {
        throw new Error('Invalid response structure from Claude');
      }
      
      debugLog('Successfully parsed briefing with condensed summary');
      debugLog('Condensed summary:', parsed.condensedSummary.substring(0, 100) + '...');
      
      return {
        text: parsed.fullBriefing,
        condensedSummary: parsed.condensedSummary,
        usage: result.usage
      };
    } catch (parseError) {
      console.error('Failed to parse JSON response, attempting fallback:', parseError);
      
      // Fallback: if JSON parsing fails, use the raw text and generate summary separately
      // This maintains backward compatibility but should rarely happen
      debugWarn('Using fallback: generating condensed summary separately');
      const condensedSummary = await generateCondensedSummary(result.text);
      
      return {
        text: result.text,
        condensedSummary: condensedSummary,
        usage: result.usage
      };
    }
  } catch (error) {
    console.error('Error generating briefing:', error);

    // Return a fallback briefing
    const fallbackText = `Good morning! I encountered an issue generating your personalized briefing today.

    Error: ${error.message}

    Please check your API key configuration and try again.`;
    
    return {
      text: fallbackText,
      condensedSummary: `Error: ${error.message}`
    };
  }
}

/**
 * Send a chat message to Claude
 * @param {string} message - User's message
 * @param {Array} conversationHistory - Previous messages
 * @param {string} briefing - Current briefing content
 * @param {Object} sourceData - Source data from dashboard
 * @returns {Promise<string>} Claude's response
 */
export async function sendChatMessage(message, conversationHistory = [], briefing = '', sourceData = {}) {
  if (!message || !message.trim()) {
    throw new Error('Message cannot be empty');
  }

  // Build context from conversation history
  const messages = conversationHistory.map(msg => ({
    role: msg.role === 'user' ? 'user' : 'assistant',
    content: msg.content
  }));

  // Build context with briefing and source data
  let contextPrompt = `You are a helpful assistant embedded in a personal dashboard application.
You have access to the user's daily briefing and source data, and can help answer questions about news, weather,
and other information displayed in their dashboard. Be conversational and helpful.`;

  // Add briefing context if available
  if (briefing && briefing.trim()) {
    contextPrompt += `\n\nCURRENT BRIEFING:\n${briefing}`;
  }

  // Add condensed source data context if available
  if (sourceData && Object.keys(sourceData).length > 0) {
    const condensedData = condenseSourcesForClaude(sourceData);
    contextPrompt += `\n\nSOURCE DATA SUMMARY:\n${JSON.stringify(condensedData, null, 2)}`;
  }

  contextPrompt += `\n\nUser's message: ${message}`;

  try {
    const result = await callClaude(contextPrompt, messages);
    return result.text; // For chat, just return text for now
  } catch (error) {
    console.error('Error in chat:', error);
    return `I apologize, but I encountered an error: ${error.message}. Please try again.`;
  }
}

/**
 * Summarize scraped webpage content using Claude.
 * Produces a structured result with a title, overall summary, and
 * individual items (e.g., blog posts, update notes, products, etc.)
 * contextualized to whatever the page content actually is.
 *
 * @param {string} cleanedText - Pre-cleaned text content (HTML stripped)
 * @param {string} url - The source URL (used for context)
 * @returns {Promise<Object>} Structured summary with title, summary, and items[]
 */
export async function summarizeWebpage(cleanedText, url) {
  // Limit content sent to Claude to avoid huge payloads
  const truncated = cleanedText.length > 12000
    ? cleanedText.substring(0, 12000) + '\n\n[...content truncated...]'
    : cleanedText;

  const prompt = `You are analyzing the text content scraped from a webpage. Your job is to understand what kind of page this is and summarize it appropriately.

URL: ${url}

PAGE TEXT:
${truncated}

Analyze the content and determine what type of page this is (e.g., game update notes, blog, product page, news site, documentation, etc.). Then produce a structured JSON summary contextualized for its type:

- If it's game update/patch notes: summarize recent updates, what changed, key features added or fixed
- If it's a blog: summarize recent posts with dates and key points
- If it's a news page: summarize recent stories
- If it's a product page: summarize features, pricing, what it offers
- For anything else: do your best to extract the most useful information

Respond with ONLY valid JSON in this exact format:
{
  "title": "Short descriptive title for this source",
  "contentType": "What kind of content this is (e.g., 'Game Update Notes', 'Blog', 'News')",
  "summary": "2-3 sentence overall summary of the page content",
  "items": [
    {
      "title": "Title of individual item (update name, post title, etc.)",
      "date": "Date if available, null otherwise",
      "summary": "1-3 sentence summary of this specific item"
    }
  ]
}

Include up to 5 items. If the page doesn't have distinct items, create 1-2 items summarizing the main content sections.`;

  try {
    const result = await callClaude(prompt);
    const responseText = result.text || result;

    // Strip markdown code blocks if present
    let jsonText = responseText;
    if (jsonText.includes('```json')) {
      jsonText = jsonText.replace(/```json\s*/g, '').replace(/```\s*/g, '');
    } else if (jsonText.includes('```')) {
      jsonText = jsonText.replace(/```\s*/g, '');
    }
    jsonText = jsonText.trim();

    const parsed = JSON.parse(jsonText);

    return {
      title: parsed.title || 'Web Content',
      contentType: parsed.contentType || 'Webpage',
      summary: parsed.summary || '',
      items: Array.isArray(parsed.items) ? parsed.items : [],
      usage: result.usage
    };
  } catch (error) {
    console.error('Error summarizing webpage:', error);
    // Return a graceful fallback
    return {
      title: new URL(url).hostname,
      contentType: 'Webpage',
      summary: `Content from ${url}. Automatic summarization failed: ${error.message}`,
      items: [],
      error: true
    };
  }
}

/**
 * Extract meaningful content from HTML using Claude (legacy wrapper)
 * @param {string} html - The HTML content
 * @param {string} url - The source URL
 * @returns {Promise<Object>} Extracted content
 */
export async function extractContentFromHTML(html, url) {
  // Delegate to the new summarizeWebpage function
  return summarizeWebpage(html, url);
}

/**
 * Generate a summary of specific data
 * @param {Object} data - Data to summarize
 * @param {string} dataType - Type of data (reddit, news, etc.)
 * @returns {Promise<string>} Summary
 */
export async function summarizeData(data, dataType) {
  const prompt = `Summarize this ${dataType} data in 2-3 sentences, highlighting the most interesting or important items:

${JSON.stringify(data, null, 2)}

Be concise and focus on what would be most relevant to someone checking their daily news.`;

  try {
    return await callClaude(prompt);
  } catch (error) {
    console.error(`Error summarizing ${dataType}:`, error);
    return `Unable to summarize ${dataType} data.`;
  }
}
