const db = require('../db/models');
const Research_queriesDBApi = require('../db/api/research_queries');
const Research_resultsDBApi = require('../db/api/research_results');
const { LocalAIApi } = require('../ai/LocalAIApi');
const processFile = require("../middlewares/upload");
const ValidationError = require('./notifications/errors/validation');
const csv = require('csv-parser');
const axios = require('axios');
const config = require('../config');
const stream = require('stream');





module.exports = class Research_queriesService {
  static async create(data, currentUser) {
    const transaction = await db.sequelize.transaction();
    try {
      await Research_queriesDBApi.create(
        data,
        {
          currentUser,
          transaction,
        },
      );

      await transaction.commit();
    } catch (error) {
      await transaction.rollback();
      throw error;
    }
  };

  static async performSearch(data, currentUser) {
    const transaction = await db.sequelize.transaction();
    try {
      // 1. Create the query record
      const queryData = {
        ...data,
        requested_by: currentUser.id, // Ensure requested_by is set
        searched_at: new Date(),
      };
      
      const queryRecord = await Research_queriesDBApi.create(
        queryData,
        { currentUser, transaction }
      );

      // 2. Call AI
      const prompt = `Perform legal research for the following query: "${data.query_text}". 
      Jurisdiction: "${data.jurisdiction || 'Federal'}".
      Source Scope: "${data.source_scope || 'both'}".
      
      Return a JSON object with a "results" array. Each item in the array should have:
      - "snippet": A summary of the case or statute.
      - "rule_statement": The specific rule of law derived.
      - "relevance_score": An integer from 1-100.
      - "citation": A standard legal citation (e.g., "123 F.3d 456").
      
      Limit to 3 most relevant results.`;

      const aiResponse = await LocalAIApi.createResponse({
        input: [
            { role: 'system', content: 'You are a legal research assistant. Return JSON.' },
            { role: 'user', content: prompt }
        ]
      });

      let results = [];
      if (aiResponse.success) {
          try {
              const decoded = LocalAIApi.decodeJsonFromResponse(aiResponse);
              if (decoded && Array.isArray(decoded.results)) {
                  results = decoded.results;
              } else if (Array.isArray(decoded)) {
                  results = decoded;
              }
          } catch (e) {
              console.error("Failed to decode AI research results", e);
              // Fallback if plain text or partial json
          }
      }

      // 3. Save results
      const createdResults = [];
      for (const res of results) {
          const resultData = {
              research_queryId: queryRecord.id,
              snippet: res.snippet ? `[${res.citation || 'No Citation'}] ${res.snippet}` : (res.text || 'No content'),
              rule_statement: res.rule_statement || '',
              relevance_score: res.relevance_score || 0,
          };
           
           await Research_resultsDBApi.create(resultData, { currentUser, transaction });
           createdResults.push(resultData);
      }

      await transaction.commit();
      return { query: queryRecord, results: createdResults };

    } catch (error) {
      await transaction.rollback();
      console.error("Search error", error);
      throw error;
    }
  }

  static async bulkImport(req, res, sendInvitationEmails = true, host) {
    const transaction = await db.sequelize.transaction();

    try {
      await processFile(req, res);
      const bufferStream = new stream.PassThrough();
      const results = [];

      await bufferStream.end(Buffer.from(req.file.buffer, "utf-8")); // convert Buffer to Stream

      await new Promise((resolve, reject) => {
        bufferStream
          .pipe(csv())
          .on('data', (data) => results.push(data))
          .on('end', async () => {
            console.log('CSV results', results);
            resolve();
          })
          .on('error', (error) => reject(error));
      })

      await Research_queriesDBApi.bulkImport(results, {
          transaction,
          ignoreDuplicates: true,
          validate: true,
          currentUser: req.currentUser
      });

      await transaction.commit();
    } catch (error) {
      await transaction.rollback();
      throw error;
    }
  }

  static async update(data, id, currentUser) {
    const transaction = await db.sequelize.transaction();
    try {
      let research_queries = await Research_queriesDBApi.findBy(
        {id},
        {transaction},
      );

      if (!research_queries) {
        throw new ValidationError(
          'research_queriesNotFound',
        );
      }

      const updatedResearch_queries = await Research_queriesDBApi.update(
        id,
        data,
        {
          currentUser,
          transaction,
        },
      );

      await transaction.commit();
      return updatedResearch_queries;

    } catch (error) {
      await transaction.rollback();
      throw error;
    }
  };

  static async deleteByIds(ids, currentUser) {
    const transaction = await db.sequelize.transaction();

    try {
      await Research_queriesDBApi.deleteByIds(ids, {
        currentUser,
        transaction,
      });

      await transaction.commit();
    } catch (error) {
      await transaction.rollback();
      throw error;
    }
  }

  static async remove(id, currentUser) {
    const transaction = await db.sequelize.transaction();

    try {
      await Research_queriesDBApi.remove(
        id,
        {
          currentUser,
          transaction,
        },
      );

      await transaction.commit();
    } catch (error) {
      await transaction.rollback();
      throw error;
    }
  }

  
};