import { NextRequest, NextResponse } from 'next/server';
import ZAI from 'z-ai-web-dev-sdk';

// ─── Types ──────────────────────────────────────────────────────────────────

interface Indicator {
  type: string;
  message: string;
  severity: 'info' | 'warning' | 'danger';
}

interface AnalysisResult {
  scamProbability: number;
  riskLevel: 'low' | 'medium' | 'high' | 'critical';
  indicators: Indicator[];
  recommendations: string[];
}

// ─── Pattern Definitions (fallback) ─────────────────────────────────────────

const URGENCY_PATTERNS = [
  { pattern: /\burgent\b/i, message: 'Urgency language detected', weight: 15 },
  { pattern: /\bimmediately\b/i, message: 'Immediate action demanded', weight: 15 },
  { pattern: /\bhurry\b/i, message: 'Hurry pressure detected', weight: 12 },
  { pattern: /\blimited\s*time\b/i, message: 'Limited time offer pressure', weight: 14 },
  { pattern: /\bact\s*now\b/i, message: '"Act now" pressure detected', weight: 14 },
  { pattern: /\bASAP\b/i, message: 'ASAP urgency detected', weight: 10 },
  { pattern: /\bdeadline\b/i, message: 'Deadline pressure detected', weight: 10 },
  { pattern: /\bexpire/i, message: 'Expiration threat detected', weight: 12 },
  { pattern: /\blast\s*chance\b/i, message: '"Last chance" pressure detected', weight: 13 },
  { pattern: /\bnow\b.{0,20}(or|otherwise|else)/i, message: 'Consequential urgency detected', weight: 14 },
];

const PAYMENT_PATTERNS = [
  { pattern: /\bb[kK]ash\b/i, message: 'bKash payment reference detected', weight: 12 },
  { pattern: /\bnagad\b/i, message: 'Nagad payment reference detected', weight: 12 },
  { pattern: /\bsend\s*money\b/i, message: 'Money transfer request detected', weight: 18 },
  { pattern: /\bpayment\b/i, message: 'Payment request detected', weight: 10 },
  { pattern: /\btransfer\b/i, message: 'Transfer request detected', weight: 12 },
  { pattern: /\badvance\b/i, message: 'Advance payment request detected', weight: 16 },
  { pattern: /\bdeposit\b/i, message: 'Deposit request detected', weight: 12 },
  { pattern: /\bcash\s*out\b/i, message: 'Cash out request detected', weight: 10 },
  { pattern: /\bpay\s*(now|first|before|upfront)\b/i, message: 'Upfront payment demand detected', weight: 16 },
  { pattern: /\baccount\s*number\b/i, message: 'Account number request detected', weight: 10 },
];

const TOO_GOOD_PATTERNS = [
  { pattern: /\bdouble\b.{0,20}(money|payment|return|profit)/i, message: 'Double money scheme detected', weight: 20 },
  { pattern: /\bguaranteed\s*return\b/i, message: 'Guaranteed return promise detected', weight: 18 },
  { pattern: /\bfree\b.{0,20}(money|cash|gift|prize)/i, message: 'Free money/gift promise detected', weight: 18 },
  { pattern: /\bwin\b.{0,15}(prize|lottery|reward)/i, message: 'Prize/lottery winning claim detected', weight: 20 },
  { pattern: /\blottery\b/i, message: 'Lottery reference detected', weight: 18 },
  { pattern: /\bprize\b/i, message: 'Prize claim detected', weight: 14 },
  { pattern: /\bjackpot\b/i, message: 'Jackpot claim detected', weight: 18 },
  { pattern: /\b10[xX]\b|\b5[xX]\b|\b3[xX]\s*return/i, message: 'Unrealistic return multiplier detected', weight: 20 },
  { pattern: /\binvest\b.{0,30}(double|triple|multiply)/i, message: 'Investment multiplication scheme detected', weight: 20 },
  { pattern: /\bprofit.{0,15}(guaranteed|sure|certain)/i, message: 'Guaranteed profit promise detected', weight: 18 },
];

const SUSPICIOUS_CONTACT_PATTERNS = [
  { pattern: /\bWhatsApp\b/i, message: 'WhatsApp contact method detected', weight: 8 },
  { pattern: /\bTelegram\b/i, message: 'Telegram contact method detected', weight: 8 },
  { pattern: /\bdon'?t\s*call\b/i, message: '"Don\'t call" instruction detected', weight: 15 },
  { pattern: /\bsecret\b/i, message: 'Secrecy request detected', weight: 12 },
  { pattern: /\bconfidential\b/i, message: 'Confidentiality demand detected', weight: 10 },
  { pattern: /\bprivate\s*(message|chat|group)/i, message: 'Private communication request detected', weight: 10 },
  { pattern: /\bonly\s*(contact|message|chat|call)/i, message: 'Exclusive contact restriction detected', weight: 10 },
];

const PERSONAL_INFO_PATTERNS = [
  { pattern: /\bOTP\b/i, message: 'OTP request detected — never share your OTP!', weight: 25 },
  { pattern: /\bPIN\b/i, message: 'PIN request detected — never share your PIN!', weight: 25 },
  { pattern: /\bpassword\b/i, message: 'Password request detected — never share your password!', weight: 22 },
  { pattern: /\bbank\s*(details|info|information)\b/i, message: 'Bank details request detected', weight: 20 },
  { pattern: /\bNID\b/i, message: 'NID (National ID) request detected', weight: 15 },
  { pattern: /\bverification\b.{0,20}(code|OTP|PIN)/i, message: 'Verification code request detected', weight: 20 },
  { pattern: /\baccount\s*(details|info|verification)\b/i, message: 'Account information request detected', weight: 18 },
  { pattern: /\bKYC\b/i, message: 'KYC information request detected', weight: 15 },
];

// ─── Fallback Pattern-Matching Analysis ─────────────────────────────────────

function analyzeWithPatterns(text: string): AnalysisResult {
  const indicators: Indicator[] = [];
  let score = 0;

  const allGroups = [
    { patterns: URGENCY_PATTERNS, type: 'urgency' },
    { patterns: PAYMENT_PATTERNS, type: 'payment' },
    { patterns: TOO_GOOD_PATTERNS, type: 'too-good' },
    { patterns: SUSPICIOUS_CONTACT_PATTERNS, type: 'contact' },
    { patterns: PERSONAL_INFO_PATTERNS, type: 'personal-info' },
  ];

  for (const group of allGroups) {
    for (const { pattern, message, weight } of group.patterns) {
      if (pattern.test(text)) {
        score += weight;
        indicators.push({
          type: group.type,
          message,
          severity: weight >= 18 ? 'danger' : weight >= 12 ? 'warning' : 'info',
        });
      }
    }
  }

  // Deduplicate indicators by message
  const seen = new Set<string>();
  const uniqueIndicators = indicators.filter((ind) => {
    if (seen.has(ind.message)) return false;
    seen.add(ind.message);
    return true;
  });

  // Cap the score at 100
  const scamProbability = Math.min(100, score);

  // Determine risk level
  let riskLevel: AnalysisResult['riskLevel'] = 'low';
  if (scamProbability > 80) riskLevel = 'critical';
  else if (scamProbability > 60) riskLevel = 'high';
  else if (scamProbability > 30) riskLevel = 'medium';

  // Generate recommendations based on findings
  const recommendations: string[] = [];

  if (uniqueIndicators.some((i) => i.type === 'personal-info')) {
    recommendations.push('Never share OTP, PIN, or password with anyone — legitimate organizations will never ask for these.');
  }
  if (uniqueIndicators.some((i) => i.type === 'payment')) {
    recommendations.push('Do not send money to unknown persons. Verify the recipient through official channels first.');
  }
  if (uniqueIndicators.some((i) => i.type === 'urgency')) {
    recommendations.push('Scammers create urgency to prevent you from thinking clearly. Take your time and verify independently.');
  }
  if (uniqueIndicators.some((i) => i.type === 'too-good')) {
    recommendations.push('If it sounds too good to be true, it probably is. There are no guaranteed ways to double your money quickly.');
  }
  if (uniqueIndicators.some((i) => i.type === 'contact')) {
    recommendations.push('Be cautious of requests to communicate only through private channels like WhatsApp or Telegram.');
  }
  if (recommendations.length === 0) {
    recommendations.push('This message appears relatively safe, but always stay vigilant.');
    recommendations.push('Verify unknown contacts through official channels before engaging.');
    recommendations.push('Search the phone number or bKash number on ScamChecker BD before making transactions.');
  }

  recommendations.push("Search the sender's number or bKash on ScamChecker BD to check for existing reports.");
  recommendations.push('Report this message on ScamChecker BD if you believe it is a scam.');

  return {
    scamProbability,
    riskLevel,
    indicators: uniqueIndicators,
    recommendations,
  };
}

// ─── System Prompt ──────────────────────────────────────────────────────────

const SYSTEM_PROMPT = `You are a scam detection AI specialized in identifying fraudulent messages targeting people in Bangladesh. Analyze the following text and determine if it's a potential scam.

Consider these scam types common in Bangladesh:
- Fake lottery/prize wins
- Investment scams (double money, guaranteed returns)
- Phishing messages (bKash/Nagad account suspension)
- Advance fee fraud
- Job scam circulars
- Courier/customs scams
- Rental scams

Look for these red flags:
- Urgency language ("act now", "immediately", "hurry")
- Payment requests (bKash, Nagad, bank transfer)
- Too-good-to-be-true offers
- Requests for personal information (OTP, PIN, password, bank details)
- Suspicious contact methods (WhatsApp only, Telegram, secret groups)
- Pressure tactics and deadlines

Return your analysis as a JSON object with this exact structure:
{
  "scamProbability": <number 0-100>,
  "riskLevel": "<low|medium|high|critical>",
  "indicators": [
    {"type": "<urgency|payment|too-good|contact|personal-info>", "message": "<description>", "severity": "<info|warning|danger>"}
  ],
  "recommendations": ["<string>", ...]
}

Rules:
- scamProbability 0-30 = low risk, 31-60 = medium risk, 61-80 = high risk, 81-100 = critical risk
- Only flag genuine red flags, not false positives
- For normal messages, return low probability with empty indicators
- Always provide at least 2 recommendations
- Respond ONLY with the JSON object, no additional text`;

// ─── POST Handler ───────────────────────────────────────────────────────────

export async function POST(request: NextRequest) {
  try {
    const body = await request.json();
    const { text } = body;

    if (!text || typeof text !== 'string' || !text.trim()) {
      return NextResponse.json(
        { success: false, error: 'Text is required for analysis' },
        { status: 400 }
      );
    }

    let analysisResult: AnalysisResult;

    try {
      // Attempt LLM-based analysis
      const zai = await ZAI.create();
      const response = await zai.chat.completions.create({
        messages: [
          { role: 'system', content: SYSTEM_PROMPT },
          { role: 'user', content: text },
        ],
        thinking: { type: 'disabled' },
      });

      const content = response.choices[0]?.message?.content;

      if (!content) {
        throw new Error('Empty response from LLM');
      }

      // Try to extract JSON from the response
      // The LLM might wrap it in markdown code blocks
      let jsonStr = content.trim();

      // Remove markdown code block wrappers if present
      const codeBlockMatch = jsonStr.match(/```(?:json)?\s*\n?([\s\S]*?)\n?\s*```/);
      if (codeBlockMatch) {
        jsonStr = codeBlockMatch[1].trim();
      }

      const parsed = JSON.parse(jsonStr);

      // Validate the parsed result has the expected structure
      if (
        typeof parsed.scamProbability === 'number' &&
        typeof parsed.riskLevel === 'string' &&
        Array.isArray(parsed.indicators) &&
        Array.isArray(parsed.recommendations)
      ) {
        // Clamp scamProbability to 0-100
        parsed.scamProbability = Math.max(0, Math.min(100, Math.round(parsed.scamProbability)));

        // Validate riskLevel
        const validRiskLevels = ['low', 'medium', 'high', 'critical'];
        if (!validRiskLevels.includes(parsed.riskLevel)) {
          // Infer risk level from probability
          if (parsed.scamProbability > 80) parsed.riskLevel = 'critical';
          else if (parsed.scamProbability > 60) parsed.riskLevel = 'high';
          else if (parsed.scamProbability > 30) parsed.riskLevel = 'medium';
          else parsed.riskLevel = 'low';
        }

        // Validate and normalize indicators
        parsed.indicators = parsed.indicators
          .filter(
            (ind: Record<string, unknown>) =>
              ind &&
              typeof ind.type === 'string' &&
              typeof ind.message === 'string' &&
              typeof ind.severity === 'string'
          )
          .map((ind: Record<string, string>) => ({
            type: ind.type,
            message: ind.message,
            severity: ['info', 'warning', 'danger'].includes(ind.severity)
              ? ind.severity
              : 'info',
          }));

        // Ensure recommendations are strings
        parsed.recommendations = parsed.recommendations.filter(
          (rec: unknown) => typeof rec === 'string'
        );

        // Ensure at least 2 recommendations
        if (parsed.recommendations.length < 2) {
          parsed.recommendations.push(
            "Search the sender's number or bKash on ScamChecker BD to check for existing reports.",
            'Report this message on ScamChecker BD if you believe it is a scam.'
          );
        }

        analysisResult = parsed as AnalysisResult;
      } else {
        throw new Error('Invalid analysis structure from LLM');
      }
    } catch (llmError) {
      // Fallback to pattern-matching analysis
      console.warn('LLM analysis failed, falling back to pattern matching:', llmError);
      analysisResult = analyzeWithPatterns(text);
    }

    return NextResponse.json(
      { success: true, data: analysisResult },
      { status: 200 }
    );
  } catch (error) {
    console.error('AI detect error:', error);
    return NextResponse.json(
      { success: false, error: 'Internal server error' },
      { status: 500 }
    );
  }
}
