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

const SYSTEM_PROMPT = `Você é um advogado sênior brasileiro com mais de 30 anos de experiência em todas as áreas do direito. Você domina completamente a legislação brasileira, incluindo mas não limitado a:

- Constituição Federal de 1988 (CF/88)
- Código de Processo Civil (CPC - Lei nº 13.105/2015)
- Código Civil (CC - Lei nº 10.406/2002)
- Código Penal (CP - Decreto-Lei nº 2.848/1940)
- Código de Processo Penal (CPP - Decreto-Lei nº 3.689/1941)
- Consolidação das Leis do Trabalho (CLT)
- Código de Defesa do Consumidor (CDC - Lei nº 8.078/1990)
- Código Tributário Nacional (CTN - Lei nº 5.172/1966)
- Estatuto da Criança e do Adolescente (ECA)
- Lei de Execução Penal (LEP)
- Lei Maria da Penha (Lei nº 11.340/2006)
- Lei de Improbidade Administrativa (Lei nº 8.429/1992)

INSTRUÇÕES RIGOROSAS:

1. ESTRUTURA: Toda peça deve seguir a estrutura formal brasileira:
   - Endereçamento ao juízo competente (em caixa alta)
   - Qualificação completa das partes
   - DOS FATOS (narrativa clara e cronológica)
   - DO DIREITO / DOS FUNDAMENTOS JURÍDICOS (argumentação robusta)
   - DOS PEDIDOS (numerados e específicos)
   - Requerimentos finais
   - Valor da causa (quando aplicável)
   - Local, data e assinatura

2. CITAÇÕES LEGAIS: Cite artigos específicos de leis reais. Use jurisprudência quando relevante (STF, STJ, TJs). Formate citações em itálico.

3. LINGUAGEM: Use português jurídico formal. Trate o juiz como "Excelentíssimo(a) Senhor(a) Doutor(a) Juiz(a)" ou "Meritíssimo". Use "data venia", "ad argumentandum tantum", e demais expressões latinas quando apropriado.

4. QUALIDADE: A peça deve ser completa, profissional e pronta para protocolar. Não deixe campos em branco - use [COMPLETAR] apenas para dados específicos do cliente que não foram fornecidos.

5. FORMATAÇÃO: Use parágrafos numerados, seções em negrito/caixa alta, e espaçamento adequado para leitura jurídica.

6. Nunca mencione que é uma IA. Escreva como um advogado real escreveria.`

function buildUserPrompt(type: string, area: string, details: Record<string, string>): string {
  const typeNames: Record<string, string> = {
    'peticao-inicial': 'Petição Inicial',
    'contestacao': 'Contestação',
    'apelacao-civel': 'Apelação Cível',
    'apelacao-criminal': 'Apelação Criminal',
    'recurso': 'Recurso',
    'contrato': 'Contrato',
    'parecer': 'Parecer Jurídico',
    'impugnacao': 'Impugnação',
    'habeas-corpus': 'Habeas Corpus',
    'mandado-seguranca': 'Mandado de Segurança',
    'embargo': 'Embargo',
    'recurso-especial': 'Recurso Especial',
    'agravo': 'Agravo',
    'outros': 'Peça Jurídica',
  }

  const areaNames: Record<string, string> = {
    'civil': 'Direito Civil',
    'trabalhista': 'Direito Trabalhista',
    'penal': 'Direito Penal',
    'tributario': 'Direito Tributário',
    'familia': 'Direito de Família',
    'empresarial': 'Direito Empresarial',
    'consumidor': 'Direito do Consumidor',
    'administrativo': 'Direito Administrativo',
  }

  const typeName = typeNames[type] || type
  const areaName = areaNames[area] || area

  let prompt = `Elabore uma ${typeName} completa na área de ${areaName}.\n\n`

  if (details.autor) prompt += `AUTOR/REQUERENTE: ${details.autor}\n`
  if (details.reu) prompt += `RÉU/REQUERIDO: ${details.reu}\n`
  if (details.fatos) prompt += `\nFATOS:\n${details.fatos}\n`
  if (details.fundamentos) prompt += `\nFUNDAMENTOS JURÍDICOS RELEVANTES:\n${details.fundamentos}\n`
  if (details.pedidos) prompt += `\nPEDIDOS PRETENDIDOS:\n${details.pedidos}\n`
  if (details.contexto) prompt += `\nCONTEXTO ADICIONAL:\n${details.contexto}\n`

  prompt += `\nElabore a peça completa, profissional e pronta para protocolar.`

  return prompt
}

export async function POST(req: NextRequest) {
  try {
    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' },
      })
    }

    // Check credits
    const user = await prisma.user.findUnique({
      where: { id: session.user.id },
      select: { credits: true },
    })

    if (!user || user.credits < 1) {
      return new Response(JSON.stringify({ error: 'Créditos insuficientes' }), {
        status: 402,
        headers: { 'Content-Type': 'application/json' },
      })
    }

    const body = await req.json()
    const { type, area, details } = body

    if (!type || !area || !details) {
      return new Response(JSON.stringify({ error: 'Dados incompletos' }), {
        status: 400,
        headers: { 'Content-Type': 'application/json' },
      })
    }

    const userPrompt = buildUserPrompt(type, area, details)

    // Create document record
    const document = await prisma.document.create({
      data: {
        userId: session.user.id,
        type: type.toUpperCase().replace(/-/g, '_'),
        title: `${type} - ${area}`,
        prompt: userPrompt,
        content: '',
        area: area.toUpperCase(),
        status: 'GENERATING',
      },
    })

    // Deduct credit
    await prisma.user.update({
      where: { id: session.user.id },
      data: { credits: { decrement: 1 } },
    })

    const OPENAI_API_KEY = process.env.OPENAI_API_KEY

    if (!OPENAI_API_KEY) {
      // Fallback: generate a mock response for development
      const encoder = new TextEncoder()
      const mockContent = generateMockDocument(type, area, details)

      const stream = new ReadableStream({
        async start(controller) {
          const words = mockContent.split(' ')
          for (let i = 0; i < words.length; i++) {
            const chunk = (i === 0 ? '' : ' ') + words[i]
            controller.enqueue(encoder.encode(`data: ${JSON.stringify({ content: chunk, documentId: document.id })}\n\n`))
            await new Promise(r => setTimeout(r, 20))
          }

          // Update document
          await prisma.document.update({
            where: { id: document.id },
            data: {
              content: mockContent,
              wordCount: mockContent.split(/\s+/).length,
              status: 'COMPLETED',
              tokens: mockContent.length,
            },
          })

          // Log usage
          await prisma.usageLog.create({
            data: {
              userId: session.user.id,
              type: 'DOCUMENT',
              tokens: mockContent.length,
              cost: 0,
            },
          })

          controller.enqueue(encoder.encode(`data: ${JSON.stringify({ done: true, documentId: document.id })}\n\n`))
          controller.close()
        },
      })

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

    // Real OpenAI call with streaming
    const openaiRes = await fetch('https://api.openai.com/v1/chat/completions', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${OPENAI_API_KEY}`,
      },
      body: JSON.stringify({
        model: 'gpt-4o-mini',
        messages: [
          { role: 'system', content: SYSTEM_PROMPT },
          { role: 'user', content: userPrompt },
        ],
        stream: true,
        temperature: 0.4,
        max_tokens: 8000,
      }),
    })

    if (!openaiRes.ok) {
      await prisma.document.update({
        where: { id: document.id },
        data: { status: 'ERROR' },
      })
      // Refund credit
      await prisma.user.update({
        where: { id: session.user.id },
        data: { credits: { increment: 1 } },
      })
      return new Response(JSON.stringify({ error: 'Erro ao gerar documento' }), {
        status: 500,
        headers: { 'Content-Type': 'application/json' },
      })
    }

    const encoder = new TextEncoder()
    let fullContent = ''
    let totalTokens = 0

    const transformStream = new TransformStream({
      async transform(chunk, controller) {
        const text = new TextDecoder().decode(chunk)
        const lines = text.split('\n').filter(line => line.startsWith('data: '))

        for (const line of lines) {
          const data = line.slice(6).trim()
          if (data === '[DONE]') {
            // Save final document
            const wordCount = fullContent.split(/\s+/).filter(Boolean).length
            await prisma.document.update({
              where: { id: document.id },
              data: {
                content: fullContent,
                wordCount,
                status: 'COMPLETED',
                tokens: totalTokens,
              },
            })

            await prisma.usageLog.create({
              data: {
                userId: session.user.id,
                type: 'DOCUMENT',
                tokens: totalTokens,
                cost: (totalTokens / 1000) * 0.005,
              },
            })

            controller.enqueue(encoder.encode(`data: ${JSON.stringify({ done: true, documentId: document.id })}\n\n`))
            return
          }

          try {
            const parsed = JSON.parse(data)
            const content = parsed.choices?.[0]?.delta?.content
            if (content) {
              fullContent += content
              totalTokens += content.length // Approximate
              controller.enqueue(encoder.encode(`data: ${JSON.stringify({ content, documentId: document.id })}\n\n`))
            }
          } catch {
            // Skip malformed chunks
          }
        }
      },
    })

    const responseStream = openaiRes.body!.pipeThrough(transformStream)

    return new Response(responseStream, {
      headers: {
        'Content-Type': 'text/event-stream',
        'Cache-Control': 'no-cache',
        'Connection': 'keep-alive',
      },
    })
  } catch (error) {
    console.error('Document generation error:', error)
    return new Response(JSON.stringify({ error: 'Erro interno do servidor' }), {
      status: 500,
      headers: { 'Content-Type': 'application/json' },
    })
  }
}

function generateMockDocument(type: string, area: string, details: Record<string, string>): string {
  const autor = details.autor || '[NOME DO AUTOR]'
  const reu = details.reu || '[NOME DO RÉU]'

  return `EXCELENTÍSSIMO(A) SENHOR(A) DOUTOR(A) JUIZ(A) DE DIREITO DA ___ VARA CÍVEL DA COMARCA DE [CIDADE] - ESTADO DE [UF]

${autor}, brasileiro(a), [estado civil], [profissão], portador(a) do RG nº [COMPLETAR] e CPF nº [COMPLETAR], residente e domiciliado(a) na [endereço completo], por intermédio de seu(sua) advogado(a) que esta subscreve, com escritório profissional na [endereço do escritório], onde recebe intimações, vem, respeitosamente, perante Vossa Excelência, com fundamento nos artigos 319 e seguintes do Código de Processo Civil (Lei nº 13.105/2015), propor a presente

PETIÇÃO INICIAL

em face de ${reu}, [qualificação completa do réu], pelos fatos e fundamentos a seguir expostos:

I - DOS FATOS

${details.fatos || '1. [Narrar os fatos de forma clara e cronológica, indicando datas, locais e circunstâncias relevantes.]'}

2. Conforme restará demonstrado, os fatos narrados configuram clara violação aos direitos do(a) Autor(a), ensejando a tutela jurisdicional ora pleiteada.

3. Diante da situação narrada, não restou alternativa ao(à) Autor(a) senão buscar a tutela do Poder Judiciário para ver seus direitos resguardados.

II - DO DIREITO

${details.fundamentos || `4. O presente caso encontra amparo no ordenamento jurídico brasileiro, especialmente nos seguintes dispositivos legais:

5. A Constituição Federal de 1988, em seu artigo 5º, inciso XXXV, assegura que "a lei não excluirá da apreciação do Poder Judiciário lesão ou ameaça a direito". Trata-se do princípio da inafastabilidade da jurisdição, que garante ao(à) Autor(a) o direito de buscar a tutela jurisdicional.

6. O Código Civil (Lei nº 10.406/2002), em seu artigo 186, estabelece que "aquele que, por ação ou omissão voluntária, negligência ou imprudência, violar direito e causar dano a outrem, ainda que exclusivamente moral, comete ato ilícito".

7. Nesse sentido, o artigo 927 do mesmo diploma legal determina que "aquele que, por ato ilícito (arts. 186 e 187), causar dano a outrem, fica obrigado a repará-lo".

8. A jurisprudência do Superior Tribunal de Justiça é pacífica nesse sentido:

"CIVIL E PROCESSUAL CIVIL. RESPONSABILIDADE CIVIL. DANO MORAL. CONFIGURAÇÃO. O dano moral prescinde de prova quando decorre de fato por si só lesivo à dignidade da pessoa humana." (STJ, AgRg no AREsp nº XXXXX/SP, Rel. Min. XXXXX, DJe XX/XX/XXXX).`}

III - DOS PEDIDOS

Ante o exposto, requer a Vossa Excelência:

${details.pedidos || `a) A citação do(a) Réu(Ré) para, querendo, apresentar contestação no prazo legal, sob pena de revelia e confissão quanto à matéria de fato;

b) A procedência total dos pedidos formulados nesta inicial;

c) A condenação do(a) Réu(Ré) ao pagamento de indenização por danos morais, em valor a ser arbitrado por Vossa Excelência, observados os princípios da razoabilidade e proporcionalidade;

d) A condenação do(a) Réu(Ré) ao pagamento das custas processuais e honorários advocatícios, nos termos do artigo 85 do CPC;`}

e) A produção de todas as provas admitidas em direito, especialmente documental, testemunhal, pericial e depoimento pessoal do(a) Réu(Ré), sob pena de confesso(a).

Dá-se à causa o valor de R$ [COMPLETAR] ([valor por extenso]).

Termos em que,
Pede deferimento.

[Cidade], [data].

_______________________________
[NOME DO ADVOGADO]
OAB/[UF] nº [COMPLETAR]`
}
