import { NextRequest } from 'next/server'
import { getServerSession } from 'next-auth'
import { authOptions } from '@/lib/auth'
import { prisma } from '@/lib/prisma'

const LEGAL_SYSTEM_PROMPT =
  'Você é um assistente jurídico especialista EXCLUSIVAMENTE em Direito brasileiro. ' +
  'Você SOMENTE responde perguntas relacionadas a temas jurídicos e legais. ' +
  'Se o usuário perguntar sobre QUALQUER assunto que NÃO seja jurídico (tecnologia, culinária, matemática, programação, entretenimento, etc.), ' +
  'responda APENAS: "Desculpe, sou um assistente especializado exclusivamente em Direito brasileiro. Só posso ajudar com questões jurídicas e legais. Por favor, reformule sua pergunta dentro do âmbito jurídico." ' +
  'Não faça exceções. Não tente ajudar parcialmente com temas não jurídicos. ' +
  'Para questões jurídicas, responda com base na legislação vigente (CF/88, CPC, CC, CLT, CP, CDC, CTN, etc.), ' +
  'jurisprudência dos tribunais superiores (STF, STJ, TST) e doutrina. ' +
  'Cite artigos de lei quando relevante. Use linguagem técnica jurídica apropriada.'

const CREDIT_COST = 1

export async function POST(req: NextRequest) {
  const session = await getServerSession(authOptions)
  if (!session?.user?.id) {
    return new Response(JSON.stringify({ error: 'Não autorizado' }), {
      status: 401,
      headers: { 'Content-Type': 'application/json' },
    })
  }

  const userId = session.user.id

  // Check credits
  const user = await prisma.user.findUnique({ where: { id: userId }, select: { credits: true } })
  if (!user || user.credits < CREDIT_COST) {
    return new Response(JSON.stringify({ error: 'Créditos insuficientes' }), {
      status: 402,
      headers: { 'Content-Type': 'application/json' },
    })
  }

  const body = await req.json()
  const { message, chatId } = body as { message: string; chatId?: string }
    // Validate input lengths
    if (message.length > 10000) {
      return new Response(JSON.stringify({ error: "Mensagem muito longa (máx 10.000 caracteres)" }), {
        status: 400,
        headers: { "Content-Type": "application/json" },
      })
    }

  if (!message?.trim()) {
    return new Response(JSON.stringify({ error: 'Mensagem vazia' }), {
      status: 400,
      headers: { 'Content-Type': 'application/json' },
    })
  }

  // Create or get chat
  let chat: { id: string }
  if (chatId) {
    const existing = await prisma.chat.findFirst({ where: { id: chatId, userId } })
    if (!existing) {
      return new Response(JSON.stringify({ error: 'Chat não encontrado' }), {
        status: 404,
        headers: { 'Content-Type': 'application/json' },
      })
    }
    chat = existing
  } else {
    // New chat — title from first message
    const title = message.length > 60 ? message.slice(0, 57) + '...' : message
    chat = await prisma.chat.create({ data: { userId, title } })
  }

  // Save user message
  await prisma.chatMessage.create({
    data: { chatId: chat.id, role: 'USER', content: message },
  })

  // Load conversation history for context
  const history = await prisma.chatMessage.findMany({
    where: { chatId: chat.id },
    orderBy: { createdAt: 'asc' },
    select: { role: true, content: true },
  })

  const messages = [
    { role: 'system' as const, content: LEGAL_SYSTEM_PROMPT },
    ...history.map((m) => ({
      role: (m.role === 'USER' ? 'user' : 'assistant') as 'user' | 'assistant',
      content: m.content,
    })),
  ]

  // Call OpenAI
  const apiKey = process.env.OPENAI_API_KEY
  if (!apiKey) {
    // Fallback: simulated streaming response for development
    return streamSimulated(chat.id, message, userId)
  }

  try {
    const openaiRes = await fetch('https://api.openai.com/v1/chat/completions', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${apiKey}`,
      },
      body: JSON.stringify({
        model: process.env.OPENAI_MODEL || 'gpt-4o-mini',
        messages,
        stream: true,
        temperature: 0.4,
        max_tokens: 2048,
      }),
    })

    if (!openaiRes.ok) {
      const err = await openaiRes.text()
      console.error('OpenAI error:', err)
      return streamSimulated(chat.id, message, userId)
    }

    // Stream SSE to client
    const encoder = new TextEncoder()
    let fullContent = ''

    const stream = new ReadableStream({
      async start(controller) {
        // Send chatId first
        controller.enqueue(encoder.encode(`data: ${JSON.stringify({ chatId: chat.id })}\n\n`))

        const reader = openaiRes.body!.getReader()
        const decoder = new TextDecoder()
        let buffer = ''

        try {
          while (true) {
            const { done, value } = await reader.read()
            if (done) break

            buffer += decoder.decode(value, { stream: true })
            const lines = buffer.split('\n')
            buffer = lines.pop() || ''

            for (const line of lines) {
              if (!line.startsWith('data: ')) continue
              const data = line.slice(6).trim()
              if (data === '[DONE]') continue

              try {
                const parsed = JSON.parse(data)
                const delta = parsed.choices?.[0]?.delta?.content
                if (delta) {
                  fullContent += delta
                  controller.enqueue(
                    encoder.encode(`data: ${JSON.stringify({ token: delta })}\n\n`)
                  )
                }
              } catch {
                // skip malformed chunks
              }
            }
          }
        } catch (e) {
          console.error('Stream error:', e)
        }

        // Save assistant message and deduct credits
        await prisma.chatMessage.create({
          data: {
            chatId: chat.id,
            role: 'ASSISTANT',
            content: fullContent,
            tokens: Math.ceil(fullContent.length / 4),
          },
        })

        await prisma.user.update({
          where: { id: userId },
          data: { credits: { decrement: CREDIT_COST } },
        })

        await prisma.usageLog.create({
          data: {
            userId,
            type: 'CHAT',
            tokens: Math.ceil(fullContent.length / 4),
            cost: 0,
          },
        })

        controller.enqueue(encoder.encode('data: [DONE]\n\n'))
        controller.close()
      },
    })

    return new Response(stream, {
      headers: {
        'Content-Type': 'text/event-stream',
        'Cache-Control': 'no-cache',
        Connection: 'keep-alive',
      },
    })
  } catch (error) {
    console.error('OpenAI fetch error:', error)
    return streamSimulated(chat.id, message, userId)
  }
}

// Simulated streaming for dev without OpenAI key
async function streamSimulated(chatId: string, userMessage: string, userId: string) {
  const encoder = new TextEncoder()

  const simulatedResponse = generateSimulatedLegalResponse(userMessage)

  const stream = new ReadableStream({
    async start(controller) {
      controller.enqueue(encoder.encode(`data: ${JSON.stringify({ chatId })}\n\n`))

      const words = simulatedResponse.split(' ')
      for (let i = 0; i < words.length; i++) {
        const token = (i === 0 ? '' : ' ') + words[i]
        controller.enqueue(encoder.encode(`data: ${JSON.stringify({ token })}\n\n`))
        await new Promise((r) => setTimeout(r, 30 + Math.random() * 40))
      }

      await prisma.chatMessage.create({
        data: {
          chatId,
          role: 'ASSISTANT',
          content: simulatedResponse,
          tokens: Math.ceil(simulatedResponse.length / 4),
        },
      })

      await prisma.user.update({
        where: { id: userId },
        data: { credits: { decrement: CREDIT_COST } },
      })

      await prisma.usageLog.create({
        data: {
          userId,
          type: 'CHAT',
          tokens: Math.ceil(simulatedResponse.length / 4),
          cost: 0,
        },
      })

      controller.enqueue(encoder.encode('data: [DONE]\n\n'))
      controller.close()
    },
  })

  return new Response(stream, {
    headers: {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
      Connection: 'keep-alive',
    },
  })
}

function generateSimulatedLegalResponse(question: string): string {
  const q = question.toLowerCase()

  if (q.includes('contestação') && q.includes('jec')) {
    return `## Prazo para Contestação no JEC

No âmbito dos **Juizados Especiais Cíveis (JEC)**, regulados pela **Lei nº 9.099/95**, o prazo para apresentação de contestação segue regras próprias:

### Regra Geral
A contestação deve ser apresentada **na audiência de instrução e julgamento**, conforme dispõe o **art. 30 da Lei 9.099/95**:

> *"Art. 30. A contestação, que será oral ou escrita, conterá toda matéria de defesa, exceto argüição de suspeição ou impedimento do Juiz, que se processará na forma da legislação em vigor."*

### Aspectos Importantes
1. **Não há prazo em dias** como no procedimento comum do CPC (que é de 15 dias úteis, conforme art. 335 do CPC/2015)
2. A defesa é concentrada na **audiência**, podendo ser oral ou escrita
3. **Toda matéria de defesa** deve ser apresentada neste momento, sob pena de preclusão
4. A **revelia** opera seus efeitos caso o réu não compareça à audiência (art. 20 da Lei 9.099/95)

### Jurisprudência
O **STJ** tem entendimento pacífico de que nos Juizados Especiais, a contestação apresentada antes da audiência é válida, não havendo preclusão temporal antecipada (REsp 1.129.205/RJ).`
  }

  if (q.includes('apelação') || q.includes('recurso de apelação')) {
    return `## Recurso de Apelação no CPC/2015

O recurso de apelação está disciplinado nos **arts. 1.009 a 1.014 do CPC/2015** e é o recurso cabível contra **sentenças** proferidas em primeiro grau.

### Cabimento
Conforme o **art. 1.009 do CPC**:
> *"Da sentença cabe apelação."*

### Prazo
- **15 dias úteis** para interposição (art. 1.003, §5º, CPC)
- **15 dias úteis** para contrarrazões (art. 1.010, §1º, CPC)

### Efeitos
1. **Efeito devolutivo** — regra geral (art. 1.012, CPC)
2. **Efeito suspensivo** — automático, salvo nas hipóteses do §1º do art. 1.012

### Exceções ao Efeito Suspensivo (art. 1.012, §1º)
Começam a produzir efeitos imediatamente as sentenças que:
- Homologam divisão ou demarcação de terras
- Condenam a pagar alimentos
- Julgam procedente pedido de instituição de arbitragem
- Confirmam, concedem ou revogam tutela provisória
- Decretam interdição

### Processamento
1. Interposta perante o juízo *a quo*
2. O juiz não faz juízo de admissibilidade (art. 1.010, §3º, CPC)
3. Remetida diretamente ao tribunal competente
4. Distribuída a um relator

### Jurisprudência Relevante
O **STJ** consolidou que a apelação devolve ao tribunal o conhecimento da matéria impugnada, podendo o tribunal julgar questões de ordem pública ainda que não suscitadas (Súmula 456/STF, aplicável por analogia).`
  }

  if (q.includes('habeas corpus')) {
    return `## Requisitos do Habeas Corpus

O **habeas corpus** é uma garantia constitucional prevista no **art. 5º, LXVIII, da CF/88** e regulamentado nos **arts. 647 a 667 do CPP**.

### Previsão Constitucional
> *"Art. 5º, LXVIII - conceder-se-á habeas corpus sempre que alguém sofrer ou se achar ameaçado de sofrer violência ou coação em sua liberdade de locomoção, por ilegalidade ou abuso de poder."*

### Requisitos Essenciais
1. **Legitimidade ativa** — qualquer pessoa pode impetrá-lo, em seu favor ou de outrem (art. 654, CPP)
2. **Autoridade coatora** — identificação de quem pratica a coação ilegal
3. **Paciente** — pessoa que sofre ou está ameaçada de sofrer a restrição
4. **Constrangimento ilegal** à liberdade de locomoção

### Hipóteses de Cabimento (art. 648, CPP)
A coação será considerada ilegal quando:
- Não houver justa causa
- Alguém estiver preso por mais tempo que a lei determina
- Quem ordenar a coação não tiver competência
- Houver cessado o motivo da coação
- Não for admitida fiança nos casos previstos em lei
- O processo for manifestamente nulo
- Extinta a punibilidade

### Espécies
- **Preventivo** (salvo-conduto) — quando há ameaça de coação
- **Liberatório/Repressivo** — quando a coação já está consumada

### Competência
- **STF** — quando o coator for Tribunal Superior (art. 102, I, *d*, CF)
- **STJ** — quando o coator for tribunal sujeito à sua jurisdição (art. 105, I, *c*, CF)
- **TJ/TRF** — quando o coator for juiz de primeiro grau
- **Juiz de primeiro grau** — quando o coator for autoridade policial`
  }

  return `## Análise Jurídica

Com base na sua consulta, apresento a seguinte análise:

### Fundamentação Legal
A questão apresentada encontra respaldo na legislação brasileira vigente. Para uma análise mais precisa, seria necessário considerar:

1. **Legislação aplicável** — CF/88, CPC/2015, CC/2002 e legislação especial pertinente
2. **Jurisprudência dominante** — posicionamento dos tribunais superiores (STF e STJ)
3. **Doutrina majoritária** — entendimento dos principais juristas brasileiros

### Considerações Gerais
O ordenamento jurídico brasileiro adota o **sistema de direito codificado** (*civil law*), onde as fontes primárias do direito são a lei, os costumes, a jurisprudência e os princípios gerais do direito (art. 4º da LINDB).

### Recomendação
Para uma orientação mais específica e detalhada sobre sua questão, sugiro:
- Reformular a pergunta com mais detalhes sobre o caso concreto
- Indicar a área do direito (civil, penal, trabalhista, tributário, etc.)
- Mencionar se há processo judicial em curso

*Nota: Esta é uma orientação jurídica geral e não substitui a consulta presencial a um advogado.*`
}

// GET: list chats for the authenticated user
export async function GET() {
  const session = await getServerSession(authOptions)
  if (!session?.user?.id) {
    return new Response(JSON.stringify({ error: 'Não autorizado' }), {
      status: 401,
      headers: { 'Content-Type': 'application/json' },
    })
  }

  const chats = await prisma.chat.findMany({
    where: { userId: session.user.id },
    orderBy: { createdAt: 'desc' },
    select: {
      id: true,
      title: true,
      createdAt: true,
      messages: {
        orderBy: { createdAt: 'desc' },
        take: 1,
        select: { content: true, createdAt: true },
      },
    },
  })

  return new Response(JSON.stringify({ chats }), {
    headers: { 'Content-Type': 'application/json' },
  })
}
