import { NextResponse } from "next/server";
import { z } from "zod";
import { getCurrentUser } from "@/lib/auth";
import { prisma } from "@/lib/prisma";

const importSchema = z.object({
  images: z.array(z.string()).min(1, "At least one image is required"),
});

const CLAUDE_API_URL = "https://api.anthropic.com/v1/messages";

const SYSTEM_PROMPT = `You are analyzing photos of handwritten workout logs, Apple Notes, or other workout records. Extract all workout data you can find.

IMPORTANT RULES:
- If you can identify a date for the workout, include it as an ISO date string (YYYY-MM-DD)
- If no date is visible, set date to null
- Extract exercise names as closely as written
- For each exercise, extract all sets with whatever data is visible (reps, weight, duration, etc.)
- If you're unsure about an exercise name or value, set "uncertain": true and explain in "uncertainReason"
- Weight units: assume lbs unless kg or kilograms is explicitly written
- For cardio exercises (running, biking, rowing, assault bike, jump rope, etc.), look for duration, distance, and calories
- Be conservative — only include data you can actually read

Return ONLY valid JSON with this exact structure (no markdown, no code fences):
{
  "workouts": [
    {
      "date": "2025-01-15" or null,
      "name": "Upper Body" or null,
      "notes": "any overall notes" or null,
      "exercises": [
        {
          "name": "Bench Press",
          "type": "barbell" | "dumbbell" | "machine" | "cable" | "bodyweight" | "cardio" | "kettlebell" | "other",
          "sets": [
            {
              "reps": 8,
              "weight": 225,
              "weightUnit": "lbs",
              "durationSeconds": null,
              "distance": null,
              "distanceUnit": null,
              "calories": null,
              "rpe": null,
              "notes": null
            }
          ],
          "notes": null,
          "uncertain": false,
          "uncertainReason": null
        }
      ]
    }
  ],
  "confidence": "high" | "medium" | "low",
  "warnings": ["list any legibility issues or assumptions made"]
}`;

export async function POST(request: Request) {
  try {
    const user = await getCurrentUser();
    if (!user) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }

    // Get user's Claude API key from preferences
    const preferences = await prisma.userPreferences.findUnique({
      where: { userId: user.id },
    });

    if (!preferences?.enableClaudeAI || !preferences?.claudeApiKey) {
      return NextResponse.json(
        {
          error: "Claude AI is not configured. Please add your API key in Settings.",
          code: "NO_API_KEY",
        },
        { status: 400 }
      );
    }

    const body = await request.json();
    const validated = importSchema.parse(body);

    // Build Claude API request with vision
    const content: any[] = [
      {
        type: "text",
        text: "Please analyze the following workout log image(s) and extract all workout data. Return ONLY valid JSON.",
      },
    ];

    // Add each image
    for (const imageData of validated.images) {
      // imageData could be a data URL or raw base64
      let base64 = imageData;
      let mediaType = "image/jpeg";

      if (imageData.startsWith("data:")) {
        const match = imageData.match(/^data:(image\/\w+);base64,(.+)$/);
        if (match) {
          mediaType = match[1];
          base64 = match[2];
        }
      }

      content.push({
        type: "image",
        source: {
          type: "base64",
          media_type: mediaType,
          data: base64,
        },
      });
    }

    // Call Claude API
    const claudeResponse = await fetch(CLAUDE_API_URL, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "x-api-key": preferences.claudeApiKey,
        "anthropic-version": "2023-06-01",
      },
      body: JSON.stringify({
        model: "claude-sonnet-4-20250514",
        max_tokens: 4096,
        system: SYSTEM_PROMPT,
        messages: [
          {
            role: "user",
            content,
          },
        ],
      }),
    });

    if (!claudeResponse.ok) {
      const errorBody = await claudeResponse.text();
      console.error("Claude API error:", claudeResponse.status, errorBody);

      if (claudeResponse.status === 401) {
        return NextResponse.json(
          { error: "Invalid Claude API key. Please check your key in Settings.", code: "INVALID_KEY" },
          { status: 400 }
        );
      }
      if (claudeResponse.status === 429) {
        return NextResponse.json(
          { error: "Claude API rate limit reached. Please try again in a moment.", code: "RATE_LIMITED" },
          { status: 429 }
        );
      }

      return NextResponse.json(
        { error: "Failed to analyze images. Please try again.", code: "API_ERROR" },
        { status: 502 }
      );
    }

    const claudeData = await claudeResponse.json();

    // Extract text content from Claude's response
    const textContent = claudeData.content?.find((c: any) => c.type === "text");
    if (!textContent?.text) {
      return NextResponse.json(
        { error: "No response from Claude. Please try again.", code: "EMPTY_RESPONSE" },
        { status: 502 }
      );
    }

    // Parse the JSON response
    let parsed;
    try {
      // Try to extract JSON from the response (Claude might wrap it in code fences)
      let jsonText = textContent.text.trim();
      const jsonMatch = jsonText.match(/```(?:json)?\s*([\s\S]*?)```/);
      if (jsonMatch) {
        jsonText = jsonMatch[1].trim();
      }
      parsed = JSON.parse(jsonText);
    } catch {
      console.error("Failed to parse Claude response:", textContent.text);
      return NextResponse.json(
        {
          error: "Could not parse the workout data. The image may be too unclear.",
          code: "PARSE_ERROR",
          raw: textContent.text.substring(0, 500),
        },
        { status: 422 }
      );
    }

    // Validate basic structure
    if (!parsed.workouts || !Array.isArray(parsed.workouts)) {
      return NextResponse.json(
        { error: "Invalid response structure from Claude.", code: "INVALID_STRUCTURE" },
        { status: 422 }
      );
    }

    return NextResponse.json(parsed);
  } catch (error) {
    if (error instanceof z.ZodError) {
      return NextResponse.json(
        { error: "Invalid request data", details: error.errors },
        { status: 400 }
      );
    }

    console.error("POST /api/workouts/import error:", error);
    return NextResponse.json(
      { error: "Internal server error" },
      { status: 500 }
    );
  }
}
